@@ -69,7 +69,7 @@ struct scsi_cbw {
6969 /* Size of the attached command block data */
7070 size_t command_block_length ;
7171 /* Command block data */
72- uint8_t const * command_block ;
72+ const uint8_t * command_block ;
7373 /* Data phase transfer length */
7474 size_t data_transfer_length ;
7575};
@@ -168,13 +168,20 @@ static int clear_feature_endpoint_halt(struct driver_data *driver_data, uint8_t
168168 */
169169static int sync_cb (struct usb_device * const udev , struct uhc_transfer * const xfer )
170170{
171- ARG_UNUSED (udev );
172171 struct driver_data * driver_data = xfer -> priv ;
173172
174173 if (xfer -> err != 0 ) {
175174 LOG_DBG ("Request finished %p, err %d, sem %i" , xfer , xfer -> err ,
176175 k_sem_count_get (& driver_data -> sync ));
177176 }
177+ /* If the transfer was cancelled we deallocate it here */
178+ else if (xfer -> err == - ECONNRESET ) {
179+ LOG_INF ("Transfer %p cancelled" , (void * )xfer );
180+ usbh_xfer_free (udev , xfer );
181+
182+ return 0 ;
183+ }
184+
178185 k_sem_give (& driver_data -> sync );
179186
180187 return 0 ;
@@ -188,17 +195,17 @@ static int sync_cb(struct usb_device *const udev, struct uhc_transfer *const xfe
188195 */
189196static int wait_for_sync (struct driver_data * driver_data , struct uhc_transfer * xfer )
190197{
191- if (k_sem_take (& driver_data -> sync , K_MSEC (SCSI_REQ_TIMEOUT )) != 0 ) {
192- int result = 0 ;
198+ int result = 0 ;
193199
200+ if (k_sem_take (& driver_data -> sync , K_MSEC (100u )) != 0 ) {
194201 LOG_ERR ("Timeout" );
195202
196203 result = usbh_xfer_dequeue (driver_data -> udev , xfer );
197204 /* While the semaphore take timed out, the transfer was actually already
198205 * done and the callback on its way. */
199206 if (result == - EALREADY ) {
200207 /* Take the semaphore again to be sure that the callback is done */
201- if (k_sem_take (& driver_data -> sync , K_MSEC (SCSI_REQ_TIMEOUT )) != 0 ) {
208+ if (k_sem_take (& driver_data -> sync , K_MSEC (100u )) != 0 ) {
202209 /* Should not happen */
203210 LOG_ERR ("Double timeout" );
204211 }
@@ -207,11 +214,22 @@ static int wait_for_sync(struct driver_data *driver_data, struct uhc_transfer *x
207214 else if (result != 0 ) {
208215 LOG_ERR ("Failed to cancel transfer" );
209216 }
217+ /* Dequeue succeeded, do nothing */
218+ else {
219+ }
220+
221+ /* The USB host driver may still need to work with the transfer, so we leave it to
222+ * the callback to deallocate it.
223+ */
210224
211225 return - ETIMEDOUT ;
226+ } else {
227+ /* The transfer was successful, store the result and free it */
228+ result = xfer -> err ;
229+ usbh_xfer_free (driver_data -> udev , xfer );
212230 }
213231
214- return xfer -> err ;
232+ return result ;
215233}
216234
217235/*
@@ -276,10 +294,11 @@ static int scsi_transfer_data(struct driver_data *driver_data, size_t data_lengt
276294 result = usbh_xfer_enqueue (driver_data -> udev , xfer );
277295 if (result != 0 ) {
278296 LOG_ERR ("Unable to enqueue the transfer: %i" , result );
297+ usbh_xfer_free (driver_data -> udev , xfer );
279298 goto error_cleanup ;
280299 }
281300
282- /* Wait for completion */
301+ /* Wait for completion, deallocation handled automatically */
283302 result = wait_for_sync (driver_data , xfer );
284303 if (result != 0 ) {
285304 goto error_cleanup ;
@@ -296,7 +315,6 @@ static int scsi_transfer_data(struct driver_data *driver_data, size_t data_lengt
296315error_cleanup :
297316 /* Done with the buffer and transfer */
298317 usbh_xfer_buf_free (driver_data -> udev , xfer -> buf );
299- usbh_xfer_free (driver_data -> udev , xfer );
300318 return result ;
301319}
302320
@@ -311,7 +329,7 @@ static int scsi_read_status(struct driver_data *driver_data, struct scsi_csw *cs
311329
312330 result = scsi_transfer_data (driver_data , sizeof (buffer ), buffer , SCSI_DIRECTION_DATA_IN );
313331 /* Stall, clear in endpoint and retry once */
314- if (result == - ENOTSUP ) {
332+ if (result == - EPIPE ) {
315333 LOG_DBG ("CSW stalled, clearing endpoint and retrying..." );
316334 result = clear_feature_endpoint_halt (driver_data ,
317335 driver_data -> in_bulk_ep -> bEndpointAddress );
@@ -406,14 +424,15 @@ static int scsi_command(struct driver_data *driver_data, struct scsi_cbw cbw)
406424 result = usbh_xfer_enqueue (driver_data -> udev , xfer );
407425 if (result != 0 ) {
408426 LOG_ERR ("Unable to enqueue the transfer: %i" , result );
427+ usbh_xfer_free (driver_data -> udev , xfer );
409428 goto error_cleanup ;
410429 }
411430
431+ /* Wait for completion, deallocation handled automatically */
412432 result = wait_for_sync (driver_data , xfer );
413433
414434error_cleanup :
415435 usbh_xfer_buf_free (driver_data -> udev , xfer -> buf );
416- usbh_xfer_free (driver_data -> udev , xfer );
417436 return result ;
418437}
419438
@@ -461,7 +480,7 @@ static int scsi_transaction(struct driver_data *driver_data, struct scsi_cbw cbw
461480 cbw .direction );
462481 /* The device stalled the transaction; it's a valid response, we should just
463482 * clear the endpoint and continue with the status to check what happened */
464- if (result == - ENOTSUP ) {
483+ if (result == - EPIPE ) {
465484 /* Pick the target endpoint */
466485 uint8_t endpoint_address =
467486 get_endpoint_for_direction (driver_data , cbw .direction );
@@ -486,6 +505,7 @@ static int scsi_transaction(struct driver_data *driver_data, struct scsi_cbw cbw
486505
487506 /* Wrong tag */
488507 if (csw .tag != driver_data -> tag ) {
508+ result = - EIO ;
489509 LOG_ERR ("Mismatching CBW and CSW tags: 0x%04X vs 0x%04X" , driver_data -> tag ,
490510 csw .tag );
491511 continue ;
@@ -548,6 +568,8 @@ static int scsi_request_sense(struct driver_data *driver_data, struct scsi_sense
548568 .command_block = command_block ,
549569 .data_transfer_length = sizeof (buffer ),
550570 };
571+ /* We need data up to the 14th byte */
572+ const size_t required_sense_data = 14u ;
551573
552574 result = scsi_transaction (driver_data , cbw , buffer , true);
553575
@@ -556,17 +578,17 @@ static int scsi_request_sense(struct driver_data *driver_data, struct scsi_sense
556578 return result ;
557579 }
558580 /* Not enough data */
559- else if (result < 14 ) {
581+ else if (result < required_sense_data ) {
560582 LOG_ERR ("Not enough sense data: %i" , result );
561583 return - EIO ;
562584 }
563585
564586 /* See SPC document, section 4.4 */
565- sense_data -> valid = (buffer [0 ] & 0x80 ) > 0 ;
566- sense_data -> response_code = buffer [0 ] & 0x7F ;
567- sense_data -> sense_key = buffer [2 ] & 0xF ;
568- sense_data -> additional_sense_code = buffer [12 ];
569- sense_data -> additional_sense_code_qualifier = buffer [13 ];
587+ sense_data -> valid = (buffer [0u ] & 0x80u ) > 0u ;
588+ sense_data -> response_code = buffer [0u ] & 0x7Fu ;
589+ sense_data -> sense_key = buffer [2u ] & 0xFu ;
590+ sense_data -> additional_sense_code = buffer [12u ];
591+ sense_data -> additional_sense_code_qualifier = buffer [13u ];
570592
571593 return 0 ;
572594}
@@ -729,6 +751,8 @@ static int mode_sense_6(struct driver_data *driver_data, uint8_t lun_index)
729751 SCSI_MODE_SENSE_DATA_LENGTH & 0xFFu , /* Data length */
730752 0u ,
731753 };
754+ /* We need data up to the 4th byte */
755+ const size_t required_sense_data = 4u ;
732756
733757 struct scsi_cbw cbw = {
734758 .lun = lun_index ,
@@ -750,7 +774,7 @@ static int mode_sense_6(struct driver_data *driver_data, uint8_t lun_index)
750774 return result ;
751775 }
752776 /* Not enough data */
753- else if (result < 4 ) {
777+ else if (result < required_sense_data ) {
754778 LOG_ERR ("Not enough mode data: %i" , result );
755779 return - EIO ;
756780 }
@@ -866,7 +890,7 @@ static int synchronize_cache(struct driver_data *driver_data, uint8_t lun_index)
866890 }
867891 }
868892
869- return 0 ;
893+ return result ;
870894}
871895#endif /* CONFIG_USBH_MSC_IGNORE_SYNC */
872896
@@ -931,7 +955,7 @@ static int read_blocks(struct driver_data *driver_data, uint8_t lun_index, uint3
931955 * Write a number of blocks to a logical unit.
932956 */
933957static int write_blocks (struct driver_data * driver_data , uint8_t lun_index , uint32_t lba ,
934- uint16_t block_count , uint8_t const * buffer )
958+ uint16_t block_count , const uint8_t * buffer )
935959{
936960 int result = 0 ;
937961 uint32_t transfer_length =
@@ -1002,7 +1026,7 @@ static int get_max_lun(struct driver_data *driver_data)
10021026 result = usbh_req_setup (driver_data -> udev , bmRequestType , GET_MAX_LUN , 0 ,
10031027 driver_data -> target_iface , 1 , buf );
10041028 /* A stalled GET_MAX_LUN request shall be interpreted as a unique unit */
1005- if (result == - ENOTSUP ) {
1029+ if (result == - EPIPE ) {
10061030 driver_data -> max_logical_unit = 0 ;
10071031 result = 0 ;
10081032 }
@@ -1121,19 +1145,23 @@ static int scan_interface_endpoints(struct driver_data *driver_data, uint8_t ifa
11211145 if (desc -> bDescriptorType == USB_DESC_ENDPOINT ) {
11221146 ep_desc = (const void * )desc ;
11231147
1124- /* Input bulk endpoint */
1125- if (USB_EP_DIR_IS_IN (ep_desc -> bEndpointAddress ) &&
1126- driver_data -> in_bulk_ep == NULL ) {
1127- LOG_DBG ("Input bulk endpoint: 0x%02X" ,
1128- ep_desc -> bEndpointAddress );
1129- driver_data -> in_bulk_ep = ep_desc ;
1130- }
1131- /* Output bulk endpoint */
1132- else if (USB_EP_DIR_IS_OUT (ep_desc -> bEndpointAddress ) &&
1133- driver_data -> out_bulk_ep == NULL ) {
1134- LOG_DBG ("Output bulk endpoint: 0x%02X" ,
1135- ep_desc -> bEndpointAddress );
1136- driver_data -> out_bulk_ep = ep_desc ;
1148+ /* Only pick bulk endpoints */
1149+ if ((ep_desc -> bmAttributes & USB_EP_TRANSFER_TYPE_MASK ) ==
1150+ USB_EP_TYPE_BULK ) {
1151+ /* Input bulk endpoint */
1152+ if (USB_EP_DIR_IS_IN (ep_desc -> bEndpointAddress ) &&
1153+ driver_data -> in_bulk_ep == NULL ) {
1154+ LOG_DBG ("Input bulk endpoint: 0x%02X" ,
1155+ ep_desc -> bEndpointAddress );
1156+ driver_data -> in_bulk_ep = ep_desc ;
1157+ }
1158+ /* Output bulk endpoint */
1159+ else if (USB_EP_DIR_IS_OUT (ep_desc -> bEndpointAddress ) &&
1160+ driver_data -> out_bulk_ep == NULL ) {
1161+ LOG_DBG ("Output bulk endpoint: 0x%02X" ,
1162+ ep_desc -> bEndpointAddress );
1163+ driver_data -> out_bulk_ep = ep_desc ;
1164+ }
11371165 }
11381166
11391167 ep_count ++ ;
@@ -1268,6 +1296,12 @@ static int disk_access_read(struct disk_info *disk, uint8_t *data_buf, uint32_t
12681296 struct driver_data * driver_data = lun_data -> driver_data ;
12691297 int result = 0 ;
12701298
1299+ if (num_sector > 0xFFFF ) {
1300+ LOG_ERR ("Cannot read more than 65535 sectors, and %" PRIu32 " were requested" ,
1301+ num_sector );
1302+ return - EINVAL ;
1303+ }
1304+
12711305 k_mutex_lock (& driver_data -> lock , K_FOREVER );
12721306 if (start_sector + num_sector > lun_data -> last_logical_block_address + 1 ) {
12731307 k_mutex_unlock (& driver_data -> lock );
@@ -1292,6 +1326,12 @@ static int disk_access_write(struct disk_info *disk, const uint8_t *data_buf, ui
12921326 struct driver_data * driver_data = lun_data -> driver_data ;
12931327 int result = 0 ;
12941328
1329+ if (num_sector > 0xFFFF ) {
1330+ LOG_ERR ("Cannot write more than 65535 sectors, and %" PRIu32 " were requested" ,
1331+ num_sector );
1332+ return - EINVAL ;
1333+ }
1334+
12951335 k_mutex_lock (& driver_data -> lock , K_FOREVER );
12961336 if (start_sector + num_sector > lun_data -> last_logical_block_address + 1 ) {
12971337 k_mutex_unlock (& driver_data -> lock );
@@ -1422,7 +1462,7 @@ static int usbh_msc_probe(struct usbh_class_data *const c_data, struct usb_devic
14221462{
14231463 const struct device * dev = c_data -> priv ;
14241464 struct driver_data * driver_data = (void * )dev -> data ;
1425- struct driver_config const * driver_config = (void * )dev -> config ;
1465+ const struct driver_config * driver_config = (void * )dev -> config ;
14261466 int result ;
14271467
14281468 LOG_INF ("MSC device connected" );
@@ -1449,7 +1489,7 @@ static int usbh_msc_probe(struct usbh_class_data *const c_data, struct usb_devic
14491489 }
14501490
14511491 /* Fetch bulk endpoints */
1452- result = scan_interface_endpoints (driver_data , iface );
1492+ result = scan_interface_endpoints (driver_data , driver_data -> target_iface );
14531493 if (result != 0 ) {
14541494 LOG_ERR ("Failed to scan endpoints: %d" , result );
14551495 goto error_cleanup ;
0 commit comments