@@ -159,7 +159,7 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque
159
159
case MSC_REQ_GET_MAX_LUN :
160
160
{
161
161
uint8_t maxlun = 1 ;
162
- if (tud_msc_maxlun_cb ) maxlun = tud_msc_maxlun_cb ();
162
+ if (tud_msc_get_maxlun_cb ) maxlun = tud_msc_get_maxlun_cb ();
163
163
TU_VERIFY (maxlun );
164
164
165
165
// MAX LUN is minus 1 by specs
@@ -186,14 +186,37 @@ bool mscd_control_request_complete(uint8_t rhport, tusb_control_request_t const
186
186
return true;
187
187
}
188
188
189
- // return length of response (copied to buffer), -1 if it is not an built-in commands
190
- int32_t proc_builtin_scsi (msc_cbw_t const * p_cbw , uint8_t * buffer , uint32_t bufsize )
189
+ // return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW)
190
+ // In case of a failed status, sense key must be set for reason of failure
191
+ int32_t proc_builtin_scsi (uint8_t lun , uint8_t const scsi_cmd [16 ], uint8_t * buffer , uint32_t bufsize )
191
192
{
192
193
(void ) bufsize ; // TODO refractor later
193
- int32_t ret ;
194
+ int32_t resplen ;
194
195
195
- switch ( p_cbw -> command [0 ] )
196
+ switch ( scsi_cmd [0 ] )
196
197
{
198
+ case SCSI_CMD_TEST_UNIT_READY :
199
+ resplen = 0 ;
200
+ if ( !tud_msc_test_unit_ready_cb (lun ) )
201
+ {
202
+ // not ready response with Failed status and sense key = not ready
203
+ resplen = - 1 ;
204
+
205
+ // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
206
+ if ( _mscd_itf .sense_key == 0 ) tud_msc_set_sense (lun , SCSI_SENSE_NOT_READY , 0x04 , 0x00 );
207
+ }
208
+ break ;
209
+
210
+ case SCSI_CMD_START_STOP_UNIT :
211
+ resplen = 0 ;
212
+
213
+ if (tud_msc_start_stop_cb )
214
+ {
215
+ scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const * ) scsi_cmd ;
216
+ tud_msc_start_stop_cb (lun , start_stop -> power_condition , start_stop -> start , start_stop -> load_eject );
217
+ }
218
+ break ;
219
+
197
220
case SCSI_CMD_READ_CAPACITY_10 :
198
221
{
199
222
scsi_read_capacity10_resp_t read_capa10 ;
@@ -202,14 +225,14 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
202
225
uint32_t block_size ;
203
226
uint16_t block_size_u16 ;
204
227
205
- tud_msc_capacity_cb (p_cbw -> lun , & block_count , & block_size_u16 );
228
+ tud_msc_capacity_cb (lun , & block_count , & block_size_u16 );
206
229
block_size = (uint32_t ) block_size_u16 ;
207
230
208
231
read_capa10 .last_lba = ENDIAN_BE (block_count - 1 );
209
232
read_capa10 .block_size = ENDIAN_BE (block_size );
210
233
211
- ret = sizeof (read_capa10 );
212
- memcpy (buffer , & read_capa10 , ret );
234
+ resplen = sizeof (read_capa10 );
235
+ memcpy (buffer , & read_capa10 , resplen );
213
236
}
214
237
break ;
215
238
@@ -226,12 +249,12 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
226
249
uint32_t block_count ;
227
250
uint16_t block_size ;
228
251
229
- tud_msc_capacity_cb (p_cbw -> lun , & block_count , & block_size );
252
+ tud_msc_capacity_cb (lun , & block_count , & block_size );
230
253
read_fmt_capa .block_num = ENDIAN_BE (block_count );
231
254
read_fmt_capa .block_size_u16 = ENDIAN_BE16 (block_size );
232
255
233
- ret = sizeof (read_fmt_capa );
234
- memcpy (buffer , & read_fmt_capa , ret );
256
+ resplen = sizeof (read_fmt_capa );
257
+ memcpy (buffer , & read_fmt_capa , resplen );
235
258
}
236
259
break ;
237
260
@@ -242,23 +265,17 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
242
265
.is_removable = 1 ,
243
266
.version = 2 ,
244
267
.response_data_format = 2 ,
245
- // vendor_id, product_id, product_rev is space padded string
246
- .vendor_id = "" ,
247
- .product_id = "" ,
248
- .product_rev = "" ,
249
268
};
250
269
251
- memset (inquiry_rsp .vendor_id , ' ' , sizeof (inquiry_rsp .vendor_id ));
252
- memcpy (inquiry_rsp .vendor_id , CFG_TUD_MSC_VENDOR , tu_min32 (strlen (CFG_TUD_MSC_VENDOR ), sizeof (inquiry_rsp .vendor_id )));
253
-
254
- memset (inquiry_rsp .product_id , ' ' , sizeof (inquiry_rsp .product_id ));
255
- memcpy (inquiry_rsp .product_id , CFG_TUD_MSC_PRODUCT , tu_min32 (strlen (CFG_TUD_MSC_PRODUCT ), sizeof (inquiry_rsp .product_id )));
256
-
270
+ // vendor_id, product_id, product_rev is space padded string
271
+ memset (inquiry_rsp .vendor_id , ' ' , sizeof (inquiry_rsp .vendor_id ));
272
+ memset (inquiry_rsp .product_id , ' ' , sizeof (inquiry_rsp .product_id ));
257
273
memset (inquiry_rsp .product_rev , ' ' , sizeof (inquiry_rsp .product_rev ));
258
- memcpy (inquiry_rsp .product_rev , CFG_TUD_MSC_PRODUCT_REV , tu_min32 (strlen (CFG_TUD_MSC_PRODUCT_REV ), sizeof (inquiry_rsp .product_rev )));
259
274
260
- ret = sizeof (inquiry_rsp );
261
- memcpy (buffer , & inquiry_rsp , ret );
275
+ tud_msc_inquiry_cb (lun , inquiry_rsp .vendor_id , inquiry_rsp .product_id , inquiry_rsp .product_rev );
276
+
277
+ resplen = sizeof (inquiry_rsp );
278
+ memcpy (buffer , & inquiry_rsp , resplen );
262
279
}
263
280
break ;
264
281
@@ -275,12 +292,12 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
275
292
276
293
bool writable = true;
277
294
if (tud_msc_is_writable_cb ) {
278
- writable = tud_msc_is_writable_cb (p_cbw -> lun );
295
+ writable = tud_msc_is_writable_cb (lun );
279
296
}
280
297
mode_resp .write_protected = !writable ;
281
298
282
- ret = sizeof (mode_resp );
283
- memcpy (buffer , & mode_resp , ret );
299
+ resplen = sizeof (mode_resp );
300
+ memcpy (buffer , & mode_resp , resplen );
284
301
}
285
302
break ;
286
303
@@ -298,18 +315,18 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
298
315
sense_rsp .add_sense_code = _mscd_itf .add_sense_code ;
299
316
sense_rsp .add_sense_qualifier = _mscd_itf .add_sense_qualifier ;
300
317
301
- ret = sizeof (sense_rsp );
302
- memcpy (buffer , & sense_rsp , ret );
318
+ resplen = sizeof (sense_rsp );
319
+ memcpy (buffer , & sense_rsp , resplen );
303
320
304
321
// Clear sense data after copy
305
- tud_msc_set_sense (p_cbw -> lun , 0 , 0 , 0 );
322
+ tud_msc_set_sense (lun , 0 , 0 , 0 );
306
323
}
307
324
break ;
308
325
309
- default : ret = -1 ; break ;
326
+ default : resplen = -1 ; break ;
310
327
}
311
328
312
- return ret ;
329
+ return resplen ;
313
330
}
314
331
315
332
bool mscd_xfer_cb (uint8_t rhport , uint8_t ep_addr , xfer_result_t event , uint32_t xferred_bytes )
@@ -348,60 +365,50 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
348
365
else
349
366
{
350
367
// For other SCSI commands
351
- // 1. Zero : Invoke app callback, skip DATA and move to STATUS stage
352
- // 2. OUT : queue transfer (invoke app callback after done)
353
- // 3. IN : invoke app callback to get response
354
- if ( p_cbw -> total_bytes == 0 )
355
- {
356
- int32_t const cb_result = tud_msc_scsi_cb (p_cbw -> lun , p_cbw -> command , NULL , 0 );
357
-
358
- p_msc -> total_len = 0 ;
359
- p_msc -> stage = MSC_STAGE_STATUS ;
360
-
361
- if ( cb_result < 0 )
362
- {
363
- p_csw -> status = MSC_CSW_STATUS_FAILED ;
364
- tud_msc_set_sense (p_cbw -> lun , SCSI_SENSE_ILLEGAL_REQUEST , 0x20 , 0x00 ); // Sense = Invalid Command Operation
365
- }
366
- else
367
- {
368
- p_csw -> status = MSC_CSW_STATUS_PASSED ;
369
- }
370
- }
371
- else if ( !TU_BIT_TEST (p_cbw -> dir , 7 ) )
368
+ // 1. OUT : queue transfer (invoke app callback after done)
369
+ // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length
370
+ if ( (p_cbw -> total_bytes > 0 ) && !TU_BIT_TEST (p_cbw -> dir , 7 ) )
372
371
{
373
- // OUT transfer
372
+ // queue transfer
374
373
TU_ASSERT ( dcd_edpt_xfer (rhport , p_msc -> ep_out , _mscd_buf , p_msc -> total_len ) );
375
- }
376
- else
374
+ }else
377
375
{
378
- // IN Transfer
379
- int32_t cb_result ;
376
+ int32_t resplen ;
380
377
381
- // first process if it is a built-in commands
382
- cb_result = proc_builtin_scsi (p_cbw , _mscd_buf , sizeof (_mscd_buf ));
378
+ // First process if it is a built-in commands
379
+ resplen = proc_builtin_scsi (p_cbw -> lun , p_cbw -> command , _mscd_buf , sizeof (_mscd_buf ));
383
380
384
- // Not an built-in command , invoke user callback
385
- if ( cb_result < 0 )
381
+ // Not built-in, invoke user callback
382
+ if ( ( resplen < 0 ) && ( p_msc -> sense_key == 0 ) )
386
383
{
387
- cb_result = tud_msc_scsi_cb (p_cbw -> lun , p_cbw -> command , _mscd_buf , p_msc -> total_len );
384
+ resplen = tud_msc_scsi_cb (p_cbw -> lun , p_cbw -> command , _mscd_buf , p_msc -> total_len );
388
385
}
389
386
390
- if ( cb_result > 0 )
391
- {
392
- p_msc -> total_len = (uint32_t ) cb_result ;
393
- p_csw -> status = MSC_CSW_STATUS_PASSED ;
394
-
395
- TU_ASSERT ( p_cbw -> total_bytes >= p_msc -> total_len ); // cannot return more than host expect
396
- TU_ASSERT ( dcd_edpt_xfer (rhport , p_msc -> ep_in , _mscd_buf , p_msc -> total_len ) );
397
- }else
387
+ if ( resplen < 0 )
398
388
{
399
389
p_msc -> total_len = 0 ;
400
390
p_csw -> status = MSC_CSW_STATUS_FAILED ;
401
391
p_msc -> stage = MSC_STAGE_STATUS ;
402
392
403
- tud_msc_set_sense (p_cbw -> lun , SCSI_SENSE_ILLEGAL_REQUEST , 0x20 , 0x00 ); // Sense = Invalid Command Operation
404
- usbd_edpt_stall (rhport , p_msc -> ep_in );
393
+ // failed but senskey is not set: default to Illegal Request
394
+ if ( p_msc -> sense_key == 0 ) tud_msc_set_sense (p_cbw -> lun , SCSI_SENSE_ILLEGAL_REQUEST , 0x20 , 0x00 );
395
+
396
+ /// Stall bulk In if needed
397
+ if (p_cbw -> total_bytes ) usbd_edpt_stall (rhport , p_msc -> ep_in );
398
+ }
399
+ else
400
+ {
401
+ p_msc -> total_len = (uint32_t ) resplen ;
402
+ p_csw -> status = MSC_CSW_STATUS_PASSED ;
403
+
404
+ if (p_msc -> total_len )
405
+ {
406
+ TU_ASSERT ( p_cbw -> total_bytes >= p_msc -> total_len ); // cannot return more than host expect
407
+ TU_ASSERT ( dcd_edpt_xfer (rhport , p_msc -> ep_in , _mscd_buf , p_msc -> total_len ) );
408
+ }else
409
+ {
410
+ p_msc -> stage = MSC_STAGE_STATUS ;
411
+ }
405
412
}
406
413
}
407
414
}
0 commit comments