@@ -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,30 +186,64 @@ 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
- scsi_read_capacity10_resp_t read_capa10 ;
200
-
201
222
uint32_t block_count ;
202
223
uint32_t block_size ;
203
224
uint16_t block_size_u16 ;
204
225
205
- tud_msc_capacity_cb (p_cbw -> lun , & block_count , & block_size_u16 );
226
+ tud_msc_capacity_cb (lun , & block_count , & block_size_u16 );
206
227
block_size = (uint32_t ) block_size_u16 ;
207
228
208
- read_capa10 .last_lba = ENDIAN_BE (block_count - 1 );
209
- read_capa10 .block_size = ENDIAN_BE (block_size );
229
+ // Invalid block size/count from callback, possibly unit is not ready
230
+ // stall this request, set sense key to NOT READY
231
+ if (block_count == 0 || block_size == 0 )
232
+ {
233
+ resplen = -1 ;
234
+
235
+ // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
236
+ if ( _mscd_itf .sense_key == 0 ) tud_msc_set_sense (lun , SCSI_SENSE_NOT_READY , 0x04 , 0x00 );
237
+ }else
238
+ {
239
+ scsi_read_capacity10_resp_t read_capa10 ;
240
+
241
+ read_capa10 .last_lba = ENDIAN_BE (block_count - 1 );
242
+ read_capa10 .block_size = ENDIAN_BE (block_size );
210
243
211
- ret = sizeof (read_capa10 );
212
- memcpy (buffer , & read_capa10 , ret );
244
+ resplen = sizeof (read_capa10 );
245
+ memcpy (buffer , & read_capa10 , resplen );
246
+ }
213
247
}
214
248
break ;
215
249
@@ -226,12 +260,24 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
226
260
uint32_t block_count ;
227
261
uint16_t block_size ;
228
262
229
- tud_msc_capacity_cb (p_cbw -> lun , & block_count , & block_size );
230
- read_fmt_capa .block_num = ENDIAN_BE (block_count );
231
- read_fmt_capa .block_size_u16 = ENDIAN_BE16 (block_size );
263
+ tud_msc_capacity_cb (lun , & block_count , & block_size );
264
+
265
+ // Invalid block size/count from callback, possibly unit is not ready
266
+ // stall this request, set sense key to NOT READY
267
+ if (block_count == 0 || block_size == 0 )
268
+ {
269
+ resplen = -1 ;
232
270
233
- ret = sizeof (read_fmt_capa );
234
- memcpy (buffer , & read_fmt_capa , ret );
271
+ // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
272
+ if ( _mscd_itf .sense_key == 0 ) tud_msc_set_sense (lun , SCSI_SENSE_NOT_READY , 0x04 , 0x00 );
273
+ }else
274
+ {
275
+ read_fmt_capa .block_num = ENDIAN_BE (block_count );
276
+ read_fmt_capa .block_size_u16 = ENDIAN_BE16 (block_size );
277
+
278
+ resplen = sizeof (read_fmt_capa );
279
+ memcpy (buffer , & read_fmt_capa , resplen );
280
+ }
235
281
}
236
282
break ;
237
283
@@ -242,23 +288,17 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
242
288
.is_removable = 1 ,
243
289
.version = 2 ,
244
290
.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
291
};
250
292
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
-
293
+ // vendor_id, product_id, product_rev is space padded string
294
+ memset (inquiry_rsp .vendor_id , ' ' , sizeof (inquiry_rsp .vendor_id ));
295
+ memset (inquiry_rsp .product_id , ' ' , sizeof (inquiry_rsp .product_id ));
257
296
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
297
260
- ret = sizeof (inquiry_rsp );
261
- memcpy (buffer , & inquiry_rsp , ret );
298
+ tud_msc_inquiry_cb (lun , inquiry_rsp .vendor_id , inquiry_rsp .product_id , inquiry_rsp .product_rev );
299
+
300
+ resplen = sizeof (inquiry_rsp );
301
+ memcpy (buffer , & inquiry_rsp , resplen );
262
302
}
263
303
break ;
264
304
@@ -275,12 +315,12 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
275
315
276
316
bool writable = true;
277
317
if (tud_msc_is_writable_cb ) {
278
- writable = tud_msc_is_writable_cb (p_cbw -> lun );
318
+ writable = tud_msc_is_writable_cb (lun );
279
319
}
280
320
mode_resp .write_protected = !writable ;
281
321
282
- ret = sizeof (mode_resp );
283
- memcpy (buffer , & mode_resp , ret );
322
+ resplen = sizeof (mode_resp );
323
+ memcpy (buffer , & mode_resp , resplen );
284
324
}
285
325
break ;
286
326
@@ -298,18 +338,18 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
298
338
sense_rsp .add_sense_code = _mscd_itf .add_sense_code ;
299
339
sense_rsp .add_sense_qualifier = _mscd_itf .add_sense_qualifier ;
300
340
301
- ret = sizeof (sense_rsp );
302
- memcpy (buffer , & sense_rsp , ret );
341
+ resplen = sizeof (sense_rsp );
342
+ memcpy (buffer , & sense_rsp , resplen );
303
343
304
344
// Clear sense data after copy
305
- tud_msc_set_sense (p_cbw -> lun , 0 , 0 , 0 );
345
+ tud_msc_set_sense (lun , 0 , 0 , 0 );
306
346
}
307
347
break ;
308
348
309
- default : ret = -1 ; break ;
349
+ default : resplen = -1 ; break ;
310
350
}
311
351
312
- return ret ;
352
+ return resplen ;
313
353
}
314
354
315
355
bool mscd_xfer_cb (uint8_t rhport , uint8_t ep_addr , xfer_result_t event , uint32_t xferred_bytes )
@@ -348,60 +388,50 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
348
388
else
349
389
{
350
390
// 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 )
391
+ // 1. OUT : queue transfer (invoke app callback after done)
392
+ // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length
393
+ if ( (p_cbw -> total_bytes > 0 ) && !TU_BIT_TEST (p_cbw -> dir , 7 ) )
355
394
{
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 ) )
372
- {
373
- // OUT transfer
395
+ // queue transfer
374
396
TU_ASSERT ( dcd_edpt_xfer (rhport , p_msc -> ep_out , _mscd_buf , p_msc -> total_len ) );
375
- }
376
- else
397
+ }else
377
398
{
378
- // IN Transfer
379
- int32_t cb_result ;
399
+ int32_t resplen ;
380
400
381
- // first process if it is a built-in commands
382
- cb_result = proc_builtin_scsi (p_cbw , _mscd_buf , sizeof (_mscd_buf ));
401
+ // First process if it is a built-in commands
402
+ resplen = proc_builtin_scsi (p_cbw -> lun , p_cbw -> command , _mscd_buf , sizeof (_mscd_buf ));
383
403
384
- // Not an built-in command , invoke user callback
385
- if ( cb_result < 0 )
404
+ // Not built-in, invoke user callback
405
+ if ( ( resplen < 0 ) && ( p_msc -> sense_key == 0 ) )
386
406
{
387
- cb_result = tud_msc_scsi_cb (p_cbw -> lun , p_cbw -> command , _mscd_buf , p_msc -> total_len );
407
+ resplen = tud_msc_scsi_cb (p_cbw -> lun , p_cbw -> command , _mscd_buf , p_msc -> total_len );
388
408
}
389
409
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
410
+ if ( resplen < 0 )
398
411
{
399
412
p_msc -> total_len = 0 ;
400
413
p_csw -> status = MSC_CSW_STATUS_FAILED ;
401
414
p_msc -> stage = MSC_STAGE_STATUS ;
402
415
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 );
416
+ // failed but senskey is not set: default to Illegal Request
417
+ if ( p_msc -> sense_key == 0 ) tud_msc_set_sense (p_cbw -> lun , SCSI_SENSE_ILLEGAL_REQUEST , 0x20 , 0x00 );
418
+
419
+ /// Stall bulk In if needed
420
+ if (p_cbw -> total_bytes ) usbd_edpt_stall (rhport , p_msc -> ep_in );
421
+ }
422
+ else
423
+ {
424
+ p_msc -> total_len = (uint32_t ) resplen ;
425
+ p_csw -> status = MSC_CSW_STATUS_PASSED ;
426
+
427
+ if (p_msc -> total_len )
428
+ {
429
+ TU_ASSERT ( p_cbw -> total_bytes >= p_msc -> total_len ); // cannot return more than host expect
430
+ TU_ASSERT ( dcd_edpt_xfer (rhport , p_msc -> ep_in , _mscd_buf , p_msc -> total_len ) );
431
+ }else
432
+ {
433
+ p_msc -> stage = MSC_STAGE_STATUS ;
434
+ }
405
435
}
406
436
}
407
437
}
0 commit comments