Paparazzi UAS  v5.15_devel-47-g0391b4d
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
usb_msd.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Gautier Hattenberger, Alexandre Bustico
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * @file modules/loggers/sdlog_chibios/usb_msd.c
24  *
25  */
26 
28 #include "mcu_periph/ram_arch.h"
29 
30 
31 static THD_WORKING_AREA(mass_storage_thread_wa, 1024);
32 
34 /* Request types */
35 #define MSD_REQ_RESET 0xFF
36 #define MSD_GET_MAX_LUN 0xFE
37 
38 /* CBW/CSW block signatures */
39 #define MSD_CBW_SIGNATURE 0x43425355
40 #define MSD_CSW_SIGNATURE 0x53425355
41 
42 /* Setup packet access macros */
43 #define MSD_SETUP_WORD(setup, index) (uint16_t)(((uint16_t)setup[index + 1] << 8) | (setup[index] & 0x00FF))
44 #define MSD_SETUP_VALUE(setup) MSD_SETUP_WORD(setup, 2)
45 #define MSD_SETUP_INDEX(setup) MSD_SETUP_WORD(setup, 4)
46 #define MSD_SETUP_LENGTH(setup) MSD_SETUP_WORD(setup, 6)
47 
48 /* Command statuses */
49 #define MSD_COMMAND_PASSED 0x00
50 #define MSD_COMMAND_FAILED 0x01
51 #define MSD_COMMAND_PHASE_ERROR 0x02
52 
53 /* SCSI commands */
54 #define SCSI_CMD_TEST_UNIT_READY 0x00
55 #define SCSI_CMD_REQUEST_SENSE 0x03
56 #define SCSI_CMD_FORMAT_UNIT 0x04
57 #define SCSI_CMD_INQUIRY 0x12
58 #define SCSI_CMD_MODE_SENSE_6 0x1A
59 #define SCSI_CMD_START_STOP_UNIT 0x1B
60 #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
61 #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
62 #define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
63 #define SCSI_CMD_READ_CAPACITY_10 0x25
64 #define SCSI_CMD_READ_10 0x28
65 #define SCSI_CMD_WRITE_10 0x2A
66 #define SCSI_CMD_VERIFY_10 0x2F
67 
68 /* SCSI sense keys */
69 #define SCSI_SENSE_KEY_GOOD 0x00
70 #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
71 #define SCSI_SENSE_KEY_NOT_READY 0x02
72 #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
73 #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
74 #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
75 #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
76 #define SCSI_SENSE_KEY_DATA_PROTECT 0x07
77 #define SCSI_SENSE_KEY_BLANK_CHECK 0x08
78 #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
79 #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
80 #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
81 #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
82 #define SCSI_SENSE_KEY_MISCOMPARE 0x0E
83 
84 #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
85 #define SCSI_ASENSE_WRITE_FAULT 0x03
86 #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
87 #define SCSI_ASENSE_READ_ERROR 0x11
88 #define SCSI_ASENSE_INVALID_COMMAND 0x20
89 #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
90 #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
91 #define SCSI_ASENSE_WRITE_PROTECTED 0x27
92 #define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
93 #define SCSI_ASENSE_FORMAT_ERROR 0x31
94 #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
95 
96 #define SCSI_ASENSEQ_NO_QUALIFIER 0x00
97 #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
98 #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
99 #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
100 
101 
102 
103 static void mass_storage_thread(void *arg);
104 void debug_snd_evt_i(eventmask_t evt);
105 void debug_snd_evt_inl(eventmask_t evt);
106 void debug_snd_evt_nl(eventmask_t evt);
107 
108 
109 thread_t *dbg_printer = NULL;
113 PACK_STRUCT_BEGIN typedef struct {
116 } PACK_STRUCT_STRUCT msd_scsi_read_capacity_10_response_t PACK_STRUCT_END;
117 
121 PACK_STRUCT_BEGIN typedef struct {
122  uint8_t reserved[3];
126 } PACK_STRUCT_STRUCT msd_scsi_read_format_capacities_response_t PACK_STRUCT_END;
127 
131 static uint8_t IN_DMA_SECTION_CLEAR(rw_buf[2][512]);
132 
133 typedef uint32_t DWORD __attribute__((__may_alias__));;
134 typedef uint16_t WORD __attribute__((__may_alias__));
135 
140 static inline DWORD swap_uint32(const DWORD val)
141 {
142  DWORD v = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
143  return ((v << 16) & 0xFFFF0000) | ((v >> 16) & 0x0000FFFF);
144 }
149 static inline WORD swap_uint16(const WORD val)
150 {
151  return (((val >> 8) & 0xff) | ((val & 0xff) << 8));
152 }
153 static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep);
154 
158 static USBInEndpointState ep1_in_state;
159 
163 static USBOutEndpointState ep1_out_state;
164 
168 static const USBEndpointConfig ep_data_config = {
169  USB_EP_MODE_TYPE_BULK,
170  NULL,
173  64,
174  64,
175  &ep1_in_state,
176  &ep1_out_state,
177  1,
178  NULL
179 };
180 
189 {
190  usbInitEndpointI(msdp->config->usbp, msdp->config->bulk_ep, &ep_data_config);
191  chBSemSignalI(&msdp->bsem);
192  SEM_RELEASED;
194  chEvtBroadcastI(&msdp->evt_connected);
195 }
196 
205 bool msdRequestsHook(USBDriver *usbp)
206 {
207 
208  /* check that the request is of type Class / Interface */
209  if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
210  ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
211 
212  /* check that the request is for interface 0 */
213  if (MSD_SETUP_INDEX(usbp->setup) != 0) {
214  return false;
215  }
216 
217  /* act depending on bRequest = setup[1] */
218  switch (usbp->setup[1]) {
219  case MSD_REQ_RESET:
220  /* check that it is a HOST2DEV request */
221  if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_HOST2DEV) ||
222  (MSD_SETUP_LENGTH(usbp->setup) != 0) ||
223  (MSD_SETUP_VALUE(usbp->setup) != 0)) {
224  return false;
225  }
226 
227  /*
228  As required by the BOT specification, the Bulk-only mass storage reset request (classspecific
229  request) is implemented. This request is used to reset the mass storage device and
230  its associated interface. This class-specific request should prepare the device for the next
231  CBW from the host.
232  To generate the BOT Mass Storage Reset, the host must send a device request on the
233  default pipe of:
234  bmRequestType: Class, interface, host to device
235  bRequest field set to 255 (FFh)
236  wValue field set to 0
237  wIndex field set to the interface number
238  wLength field set to 0
239  */
240  UMSD.bot_reset = true;
241  chSysLockFromISR();
242 
243  /* release and abandon current transmission */
244  chBSemResetI(&UMSD.bsem, false);
245  usbStallReceiveI(usbp, UMSD.config->bulk_ep);
246  usbStallTransmitI(usbp, UMSD.config->bulk_ep);
247  /* The device shall NAK the status stage of the device request until
248  * the Bulk-Only Mass Storage Reset is complete.
249  * NAK EP1 in and out */
250  UMSD.config->usbp->otg->ie[UMSD.config->bulk_ep].DIEPCTL = DIEPCTL_SNAK;
251  UMSD.config->usbp->otg->oe[UMSD.config->bulk_ep].DOEPCTL = DOEPCTL_SNAK;
252 
253  chSysUnlockFromISR();
254  UMSD.state = MSD_BOT_RESET;
255 
256  /* response to this request using EP0 */
257  usbSetupTransfer(usbp, 0, 0, NULL);
259 
260  return true;
261  case MSD_GET_MAX_LUN:
262  /* check that it is a DEV2HOST request */
263  if (((usbp->setup[0] & USB_RTYPE_DIR_MASK) != USB_RTYPE_DIR_DEV2HOST) ||
264  (MSD_SETUP_LENGTH(usbp->setup) != 1) ||
265  (MSD_SETUP_VALUE(usbp->setup) != 0)) {
266  return false;
267  }
268 
269  static uint8_t len_buf[1] = {0};
270  /* stall to indicate that we don't support LUN */
271  usbSetupTransfer(usbp, len_buf, 1, NULL);
272  return true;
273  default:
274  return false;
275  break;
276  }
277  }
278 
279  return false;
280 }
281 
286 {
287  /* sleep until it completes */
288  chSysLock();
289  chBSemWaitS(&msdp->bsem);
291  SEM_TAKEN;
292  chSysUnlock();
293 }
294 
298 static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep)
299 {
300 
301  (void)usbp;
302  chSysLockFromISR();
303  chBSemSignalI(&((USBMassStorageDriver *)usbp->in_params[ep])->bsem);
304  SEM_RELEASED;
305  chSysUnlockFromISR();
306 }
307 
311 static void msd_start_transmit(USBMassStorageDriver *msdp, const uint8_t *buffer, size_t size)
312 {
313 
314  chSysLock();
315  if (msdp->bot_reset) {
316  msdp->config->usbp->transmitting = 0;
317  }
318  usbStartTransmitI(msdp->config->usbp, msdp->config->bulk_ep, buffer, size);
319  chSysUnlock();
320 }
321 
325 static void msd_start_receive(USBMassStorageDriver *msdp, uint8_t *buffer, size_t size)
326 {
327 
328  chSysLock();
329  if (msdp->bot_reset) {
330  msdp->config->usbp->receiving = 0;
331  }
332  usbStartReceiveI(msdp->config->usbp, msdp->config->bulk_ep, buffer, size);
333  chSysUnlock();
334 }
335 
339 static inline void msd_scsi_set_sense(USBMassStorageDriver *msdp, uint8_t key, uint8_t acode, uint8_t aqual)
340 {
341  msdp->sense.byte[2] = key;
342  msdp->sense.byte[12] = acode;
343  msdp->sense.byte[13] = aqual;
344 }
345 
350 {
351 
353 
354  msd_cbw_t *cbw = &(msdp->cbw);
355 
356  /* check the EVPD bit (Vital Product Data) */
357  if (cbw->scsi_cmd_data[1] & 0x01) {
358 
359  /* check the Page Code byte to know the type of product data to reply */
360  switch (cbw->scsi_cmd_data[2]) {
361 
362  /* unit serial number */
363  case 0x80: {
364  uint8_t response[] = {'0'}; /* TODO */
365  msd_start_transmit(msdp, response, sizeof(response));
366  msdp->result = true;
367  /* wait for ISR */
368  return true;
369  }
370 
371  /* unhandled */
372  default:
373  msd_scsi_set_sense(msdp,
377  return false;
378  }
379  } else {
380  msd_start_transmit(msdp, (const uint8_t *)&msdp->inquiry, sizeof(msdp->inquiry));
381  msdp->result = true;
382 
383  /* wait for ISR */
384  return true;
385  }
386 }
387 
392 {
393 
394  msd_start_transmit(msdp, (const uint8_t *)&msdp->sense, sizeof(msdp->sense));
395  msdp->result = true;
396 
397  /* wait for ISR immediately, otherwise the caller may reset the sense bytes before they are sent to the host! */
398  msd_wait_for_isr(msdp);
399 
400  /* ... don't wait for ISR, we just did it */
401  return false;
402 }
403 
408 {
410  static msd_scsi_read_capacity_10_response_t response;
411 
412  response.block_size = swap_uint32(msdp->block_dev_info.blk_size);
413  response.last_block_addr = swap_uint32(msdp->block_dev_info.blk_num - 1);
414 
415  msd_start_transmit(msdp, (const uint8_t *)&response, sizeof(response));
416  msdp->result = true;
417 
418  /* wait for ISR */
419  return true;
420 }
421 
426 {
427  msd_cbw_t *cbw = &(msdp->cbw);
428 
429  if (!(cbw->scsi_cmd_data[1] & (1 << 2))) {
430  /* only self-test supported - update SENSE key and fail the command */
431  msd_scsi_set_sense(msdp,
435  msdp->result = false;
436  return false;
437  }
438 
439  /* TODO: actually perform the test */
440  msdp->result = true;
441 
442  /* don't wait for ISR */
443  return false;
444 }
445 
450 {
452  msd_cbw_t *cbw = &(msdp->cbw);
453 
454  if ((cbw->scsi_cmd_data[0] == SCSI_CMD_WRITE_10) && blkIsWriteProtected(msdp->config->bbdp)) {
455  /* device is write protected and a write has been issued */
456  /* block address is invalid, update SENSE key and return command fail */
457  msd_scsi_set_sense(msdp,
461  msdp->result = false;
462 
463  /* don't wait for ISR */
464  return false;
465  }
466 
467  uint32_t rw_block_address = swap_uint32(*(DWORD *)&cbw->scsi_cmd_data[2]);
468  uint16_t total = swap_uint16(*(WORD *)&cbw->scsi_cmd_data[7]);
469  uint16_t i = 0;
470 
471  if (rw_block_address >= msdp->block_dev_info.blk_num) {
472  /* block address is invalid, update SENSE key and return command fail */
473  msd_scsi_set_sense(msdp,
477  msdp->result = false;
478 
479  /* don't wait for ISR */
480  return false;
481  }
482 
483  if (cbw->scsi_cmd_data[0] == SCSI_CMD_WRITE_10) {
484  /* process a write command */
485 
486  /* get the first packet */
487  msd_start_receive(msdp, rw_buf[i % 2], msdp->block_dev_info.blk_size);
488  msd_wait_for_isr(msdp);
489 
490  /* loop over each block */
491  for (i = 0; i < total; i++) {
492 
493  if (i < (total - 1)) {
494  /* there is at least one block of data left to be read over USB */
495  /* queue this read before issuing the blocking write */
496  msd_start_receive(msdp, rw_buf[(i + 1) % 2], msdp->block_dev_info.blk_size);
497  }
498 
499  /* now write the block to the block device */
500  if (blkWrite(msdp->config->bbdp, rw_block_address++, rw_buf[i % 2], 1) == HAL_FAILED) {
501  /* write failed */
502  msd_scsi_set_sense(msdp,
506  msdp->result = false;
507 
508  /* don't wait for ISR */
509  return false;
510  }
511 
512  if (i < (total - 1)) {
513  /* now wait for the USB event to complete */
514  msd_wait_for_isr(msdp);
515  }
516  }
517  } else {
518  /* process a read command */
519 
520  i = 0;
521 
522  /* read the first block from block device */
523  if (blkRead(msdp->config->bbdp, rw_block_address++, rw_buf[i % 2], 1) == HAL_FAILED) {
524  /* read failed */
525  msd_scsi_set_sense(msdp,
529  msdp->result = false;
530 
531  /* don't wait for ISR */
532  return false;
533  }
534 
535  /* loop over each block */
536  for (i = 0; i < total; i++) {
537  /* transmit the block */
538  msd_start_transmit(msdp, rw_buf[i % 2], msdp->block_dev_info.blk_size);
539 
540  if (i < (total - 1)) {
541  /* there is at least one more block to be read from device */
542  /* so read that whilst the USB transfer takes place */
543  if (blkRead(msdp->config->bbdp, rw_block_address++, rw_buf[(i + 1) % 2], 1) == HAL_FAILED) {
544  /* read failed */
545  msd_scsi_set_sense(msdp,
549  msdp->result = false;
550 
551  /* wait for ISR (the previous transmission is still running) */
552  return true;
553  }
554  }
555 
556  /* wait for the USB event to complete */
557  msd_wait_for_isr(msdp);
558  }
559  }
560 
561  msdp->result = true;
562 
563  /* don't wait for ISR */
564  return false;
565 }
566 
571 {
572 
573  if ((msdp->cbw.scsi_cmd_data[4] & 0x03) == 0x02) {
574  /* device has been ejected */
575  chEvtBroadcast(&msdp->evt_ejected);
576  msdp->state = MSD_EJECTED;
577  }
578 
579  msdp->result = true;
580 
581  /* don't wait for ISR */
582  return false;
583 }
584 
589 {
591  static uint8_t response[4] = {
592  0x03, /* number of bytes that follow */
593  0x00, /* medium type is SBC */
594  0x00, /* not write protected (TODO handle it correctly) */
595  0x00 /* no block descriptor */
596  };
597 
598  msd_start_transmit(msdp, response, sizeof(response));
599  msdp->result = true;
600 
601  /* wait for ISR */
602  return true;
603 }
604 
609 {
610 
612  msd_scsi_read_format_capacities_response_t response;
613  response.capacity_list_length = 1;
614  response.block_count = swap_uint32(msdp->block_dev_info.blk_num);
615  response.desc_and_block_length = swap_uint32((0x02 << 24) | (msdp->block_dev_info.blk_size & 0x00FFFFFF));
616 
617  msd_start_transmit(msdp, (const uint8_t *)&response, sizeof(response));
618  msdp->result = true;
619 
620  /* wait for ISR */
621  return true;
622 }
623 
628 {
630  if (blkIsInserted(msdp->config->bbdp)) {
631  /* device inserted and ready */
632  msdp->result = true;
633  /* device not present or not ready */
634  msd_scsi_set_sense(msdp,
638  } else {
639  /* device not present or not ready */
640  msd_scsi_set_sense(msdp,
644  msdp->result = false;
645  }
646 
647  /* don't wait for ISR */
648  return false;
649 }
650 
655 {
657 
658  msd_start_receive(msdp, (uint8_t *)&msdp->cbw, sizeof(msdp->cbw));
659 
661 
662  /* wait for ISR */
663  return true;
664 }
665 
670 {
671 
672  msd_cbw_t *cbw = &(msdp->cbw);
673 
674  /* by default transition back to the idle state */
675  msdp->state = MSD_IDLE;
676 
677 
678  /* check the command */
679  if ((cbw->signature != MSD_CBW_SIGNATURE) ||
680  (cbw->lun > 0) ||
681  ((cbw->data_len > 0) && (cbw->flags & 0x1F)) ||
682  (cbw->scsi_cmd_len == 0) ||
683  (cbw->scsi_cmd_len > 16)) {
684 
685  /* stall both IN and OUT endpoints */
686  chSysLock();
687  usbStallReceiveI(msdp->config->usbp, msdp->config->bulk_ep);
688  usbStallTransmitI(msdp->config->usbp, msdp->config->bulk_ep);
689  chSysUnlock();
690 
691  msd_scsi_set_sense(msdp,
695 
696  /* don't wait for ISR */
697  msdp->result = false;
698  return false;
699  }
700 
701  bool sleep = false;
702 
703 
704  /* check the command */
705  if (cbw->signature != MSD_CBW_SIGNATURE) {
706  sleep = msd_scsi_process_test_unit_ready(msdp);
707  }
708  //if (msdp->result == true)
709  /* check the command */
710  switch (cbw->scsi_cmd_data[0]) {
711  case SCSI_CMD_INQUIRY:
712  sleep = msd_scsi_process_inquiry(msdp);
713  break;
715  sleep = msd_scsi_process_request_sense(msdp);
716  break;
718  sleep = msd_scsi_process_read_capacity_10(msdp);
719  break;
720  case SCSI_CMD_READ_10:
721  case SCSI_CMD_WRITE_10:
722  if (msdp->config->rw_activity_callback) {
723  msdp->config->rw_activity_callback(true);
724  }
726  if (msdp->config->rw_activity_callback) {
727  msdp->config->rw_activity_callback(false);
728  }
729  break;
731  sleep = msd_scsi_process_send_diagnostic(msdp);
732  break;
734  sleep = msd_scsi_process_mode_sense_6(msdp);
735  break;
737  sleep = msd_scsi_process_start_stop_unit(msdp);
738  break;
741  break;
743  sleep = msd_scsi_process_test_unit_ready(msdp);
744  break;
746  /* don't handle */
747  msdp->result = true;
748  break;
750  /* don't handle */
751  msdp->result = true;
752  break;
753  case SCSI_CMD_VERIFY_10:
754  /* don't handle */
755  msdp->result = true;
756  break;
757  default:
758  msd_scsi_set_sense(msdp,
762 
763  /* stall IN endpoint */
764  chSysLock();
765  usbStallTransmitI(msdp->config->usbp, msdp->config->bulk_ep);
766  chSysUnlock();
767 
768  return false;
769  }
770 
771  if (msdp->result) {
772  /* update sense with success status */
773  msd_scsi_set_sense(msdp,
777 
778  /* reset data length left */
779  cbw->data_len = 0;
780  }
781 
782  /* wait for ISR if needed */
783  if (sleep & !msdp->bot_reset) {
784  msd_wait_for_isr(msdp);
785  }
786 
787  msd_csw_t *csw = &(msdp->csw);
788 
789  if (!msdp->result && cbw->data_len) {
790  /* still bytes left to send, this is too early to send CSW? */
791  chSysLock();
792  usbStallReceiveI(msdp->config->usbp, msdp->config->bulk_ep);
793  usbStallTransmitI(msdp->config->usbp, msdp->config->bulk_ep);
794  chSysUnlock();
795 
796  return false;
797  }
798 
799  /* update the command status wrapper and send it to the host */
800  csw->status = (msdp->result) ? MSD_COMMAND_PASSED : MSD_COMMAND_FAILED;
801  csw->signature = MSD_CSW_SIGNATURE;
802  csw->data_residue = cbw->data_len;
803  csw->tag = cbw->tag;
804 
805  msd_start_transmit(msdp, (const uint8_t *)csw, sizeof(*csw));
806 
807  /* wait for ISR */
808  return true;
809 }
810 
811 
816 {
817 
818  chDbgCheck(msdp != NULL);
819  msdp->bot_reset = false;
820  msdp->reconfigured_or_reset_event = false;
821  msdp->config = NULL;
822  msdp->thread = NULL;
823  msdp->state = MSD_IDLE;
824 
825  /* initialize the driver events */
826  chEvtObjectInit(&msdp->evt_connected);
827  chEvtObjectInit(&msdp->evt_ejected);
828 
829  /* initialise the binary semaphore as taken */
830  chBSemObjectInit(&msdp->bsem, true);
832 
833  /* initialise the sense data structure */
834  size_t i;
835  for (i = 0; i < sizeof(msdp->sense.byte); i++) {
836  msdp->sense.byte[i] = 0x00;
837  }
838  msdp->sense.byte[0] = 0x70; /* response code */
839  msdp->sense.byte[7] = 0x0A; /* additional sense length */
840 
841  /* initialize the inquiry data structure */
842  msdp->inquiry.peripheral = 0x00; /* direct access block device */
843  msdp->inquiry.removable = 0x80; /* removable */
844  msdp->inquiry.version = 0x04; /* SPC-2 */
845  msdp->inquiry.response_data_format = 0x02; /* response data format */
846  msdp->inquiry.additional_length = 0x20; /* response has 0x20 + 4 bytes */
847  msdp->inquiry.sccstp = 0x00;
848  msdp->inquiry.bqueetc = 0x00;
849  msdp->inquiry.cmdque = 0x00;
850 }
851 
856 {
857 
858  chDbgCheck(msdp != NULL);
859  chDbgCheck(config != NULL);
860  chDbgCheck(msdp->thread == NULL);
861 
862  /* save the configuration */
863  msdp->config = config;
864 
865  /* copy the config strings to the inquiry response structure */
866  size_t i;
867  for (i = 0; i < sizeof(msdp->config->short_vendor_id); ++i) {
868  msdp->inquiry.vendor_id[i] = config->short_vendor_id[i];
869  }
870  for (i = 0; i < sizeof(msdp->config->short_product_id); ++i) {
871  msdp->inquiry.product_id[i] = config->short_product_id[i];
872  }
873  for (i = 0; i < sizeof(msdp->config->short_product_version); ++i) {
874  msdp->inquiry.product_rev[i] = config->short_product_version[i];
875  }
876 
877  /* set the initial state */
878  msdp->state = MSD_IDLE;
879 
880  /* make sure block device is working */
881  while (blkGetDriverState(config->bbdp) != BLK_READY) {
882  chThdSleepMilliseconds(50);
883  }
884 
885  /* get block device information */
886  blkGetInfo(config->bbdp, &msdp->block_dev_info);
887 
888  /* store the pointer to the mass storage driver into the user param
889  of the USB driver, so that we can find it back in callbacks */
890  config->usbp->in_params[config->bulk_ep] = (void *)msdp;
891  config->usbp->out_params[config->bulk_ep] = (void *)msdp;
892 
893  /* run the thread */
894  msdp->thread = chThdCreateStatic(mass_storage_thread_wa, sizeof(mass_storage_thread_wa), NORMALPRIO, mass_storage_thread, msdp);
895 }
896 
901 {
902 
903  chDbgCheck(msdp->thread != NULL);
904 
905  /* notify the thread that it's over */
906  chThdTerminate(msdp->thread);
907 
908  /* wake the thread up and wait until it ends */
909  chBSemSignal(&msdp->bsem);
910  chThdWait(msdp->thread);
911  msdp->thread = NULL;
912 
913  /* release the user params in the USB driver */
914  msdp->config->usbp->in_params[msdp->config->bulk_ep] = NULL;
915  msdp->config->usbp->out_params[msdp->config->bulk_ep] = NULL;
916 }
917 
918 
919 
920 
921 void debug_snd_evt_i(eventmask_t evt)
922 {
923  if (dbg_printer != NULL) {
924  chSysLockFromISR();
925  chEvtSignalI(dbg_printer, evt);
926  chSysUnlockFromISR();
927  }
928 }
929 
930 void debug_snd_evt_inl(eventmask_t evt)
931 {
932  if (dbg_printer != NULL) {
933  chEvtSignalI(dbg_printer, evt);
934  }
935 }
936 
937 void debug_snd_evt_nl(eventmask_t evt)
938 {
939  if (dbg_printer != NULL) {
940  chEvtSignal(dbg_printer, evt);
941  }
942 }
943 
944 /* Handles global events of the USB driver */
945 static void usbEvent(USBDriver *usbp, usbevent_t event)
946 {
947  (void) usbp;
948  switch (event) {
949  case USB_EVENT_CONFIGURED:
950  chSysLockFromISR();
951  UMSD.reconfigured_or_reset_event = true;
952  msdConfigureHookI(&UMSD);
953  chSysUnlockFromISR();
954  break;
955 
956  case USB_EVENT_RESET:
958  UMSD.reconfigured_or_reset_event = true;
959  break;
960  case USB_EVENT_ADDRESS:
961  case USB_EVENT_SUSPEND:
962  case USB_EVENT_WAKEUP:
963  case USB_EVENT_STALLED:
964  break;
965  default:
966  break;
967  }
968 }
969 
970 /* USB device descriptor */
971 static const uint8_t deviceDescriptorData[] = {
972  USB_DESC_DEVICE
973  (
974  0x0200, /* supported USB version (2.0) */
975  0x00, /* interface class */
976  0x00, /* interface sub-class */
977  0x00, /* interface protocol */
978  64, /* max packet size of control end-point */
979  0x0483, /* vendor ID (ST) */
980  0xBABE, /* product ID (Babe) */
981  0x0100, /* device release number */
982  1, /* index of manufacturer string descriptor */
983  2, /* index of product string descriptor */
984  3, /* index of serial number string descriptor */
985  1 /* number of possible configurations */
986  )
987 };
988 static const USBDescriptor deviceDescriptor = {
989  sizeof(deviceDescriptorData),
990  deviceDescriptorData
991 };
992 
993 /* configuration descriptor */
995  /* configuration descriptor */
996  USB_DESC_CONFIGURATION
997  (
998  32, /* total length */
999  1, /* number of interfaces */
1000  1, /* value that selects this configuration */
1001  0, /* index of string descriptor describing this configuration */
1002  0xC0, /* attributes (self-powered) */
1003  100 /* max power (100 mA) */
1004  ),
1005 
1006  /* interface descriptor */
1007  USB_DESC_INTERFACE
1008  (
1009  0, /* interface number */
1010  0, /* value used to select alternative setting */
1011  2, /* number of end-points used by this interface */
1012  0x08, /* interface class (Mass Storage) */
1013  0x06, /* interface sub-class (SCSI Transparent Storage) */
1014  0x50, /* interface protocol (Bulk Only) */
1015  0 /* index of string descriptor describing this interface */
1016  ),
1017 
1018  /* end-point descriptor */
1019  USB_DESC_ENDPOINT
1020  (
1021  USB_MS_DATA_EP | 0x80, /* address (end point index | OUT direction) */
1022  USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
1023  64, /* max packet size */
1024  0x05 /* polling interval (ignored for bulk end-points) */
1025  ),
1026 
1027  /* end-point descriptor */
1028  USB_DESC_ENDPOINT
1029  (
1030  USB_MS_DATA_EP | 0x00, /* address (end point index | IN direction) */
1031  USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
1032  64, /* max packet size */
1033  0x05 /* polling interval (ignored for bulk end-points) */
1034  )
1035 };
1036 static const USBDescriptor configurationDescriptor = {
1038  configurationDescriptorData
1039 };
1040 
1041 /* Language descriptor */
1043  USB_DESC_BYTE(4),
1044  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
1045  USB_DESC_WORD(0x0409) /* U.S. english */
1046 };
1047 static const USBDescriptor languageDescriptor = {
1048  sizeof(languageDescriptorData),
1049  languageDescriptorData
1050 };
1051 
1052 /* Vendor descriptor */
1053 static const uint8_t vendorDescriptorData[] = {
1054  USB_DESC_BYTE(22),
1055  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
1056  'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'M', 0, 'S', 0, 'D', 0
1057 };
1058 static const USBDescriptor vendorDescriptor = {
1059  sizeof(vendorDescriptorData),
1060  vendorDescriptorData
1061 };
1062 
1063 /* Product descriptor */
1064 static const uint8_t productDescriptorData[] = {
1065  USB_DESC_BYTE(24),
1066  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
1067  'M', 0, 'S', 0, 'D', 0, ' ', 0, 'E', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0
1068 };
1069 static const USBDescriptor productDescriptor = {
1070  sizeof(productDescriptorData),
1071  productDescriptorData
1072 };
1073 
1074 /* Serial number descriptor */
1076  USB_DESC_BYTE(26),
1077  USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
1078  '0', 0, '1', 0, '4', 0, '2', 0, '3', 0, '0', 0, 'F', 0, 'K', 0, '0', 0, '0', 0, '0', 0, '1', 0
1079 };
1080 static const USBDescriptor serialNumberDescriptor = {
1082  serialNumberDescriptorData
1083 };
1084 
1085 
1086 /* Handles GET_DESCRIPTOR requests from the USB host */
1087 static const USBDescriptor *getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
1088 {
1089  (void)usbp;
1090  (void)lang;
1091 
1092  switch (type) {
1093  case USB_DESCRIPTOR_DEVICE:
1094  return &deviceDescriptor;
1095 
1096  case USB_DESCRIPTOR_CONFIGURATION:
1097  return &configurationDescriptor;
1098 
1099  case USB_DESCRIPTOR_STRING:
1100  switch (index) {
1101  case 0: return &languageDescriptor;
1102  case 1: return &vendorDescriptor;
1103  case 2: return &productDescriptor;
1104  case 3: return &serialNumberDescriptor;
1105  }
1106  }
1107 
1108  return 0;
1109 }
1110 
1111 /* Configuration of the USB driver */
1112 static const USBConfig usbConfig = {
1113  usbEvent,
1114  getDescriptor,
1116  0
1117 };
1118 
1119 
1120 
1122 {
1123  msdStop(&UMSD);
1124 }
1125 
1127 {
1128  msdInit(&UMSD);
1129  /* start the USB mass storage service */
1130  msdStart(&UMSD, msdConfig);
1131 
1132  dbg_printer = (thread_t *)dbgThreadPtr;
1133 
1134  /* start the USB driver */
1135  usbDisconnectBus(&USBD);
1136  chThdSleepMilliseconds(1000);
1137  usbStop(&USBD);
1138  usbStart(&USBD, &usbConfig);
1139  usbConnectBus(&USBD);
1140 }
1141 
1142 void msd_register_evt_connected(event_listener_t *elp, eventmask_t mask)
1143 {
1144  chEvtRegisterMask(&UMSD.evt_connected, elp, mask);
1145 }
1146 
1147 void msd_register_evt_ejected(event_listener_t *elp, eventmask_t mask)
1148 {
1149  chEvtRegisterMask(&UMSD.evt_ejected, elp, mask);
1150 }
1151 
1152 
1156 static void mass_storage_thread(void *arg)
1157 {
1158 
1160 
1161  chRegSetThreadName("USB-MSD");
1162 
1163  bool wait_for_isr = false;
1164 
1165  /* wait for the usb to be initialised */
1166  msd_wait_for_isr(msdp);
1167 
1168  while (!chThdShouldTerminateX()) {
1169 
1170  if (msdp->reconfigured_or_reset_event) {
1171  /*If the devices is unplugged and re-plugged but did not have a CPU reset,
1172  * we must set the state back to idle.*/
1173  msdp->reconfigured_or_reset_event = false;
1174  msdp->state = MSD_IDLE;
1175  msd_scsi_set_sense(msdp,
1179  }
1180 
1181 
1182 
1183  wait_for_isr = false;
1184 
1185  /* wait on data depending on the current state */
1186  switch (msdp->state) {
1187  case MSD_IDLE:
1188  wait_for_isr = msd_wait_for_command_block(msdp);
1189  break;
1191  wait_for_isr = msd_read_command_block(msdp);
1192  break;
1193  case MSD_EJECTED:
1194  /* disconnect usb device */
1195  usbDisconnectBus(msdp->config->usbp);
1196  usbStop(msdp->config->usbp);
1197  chThdExit(0);
1198  return;
1199  case MSD_BOT_RESET:
1200  chThdSleepMilliseconds(100);
1201  chSysLock();
1202  usb_lld_disable_endpoints(msdp->config->usbp);
1203  chSysUnlock();
1204  chThdSleepMilliseconds(100);
1205  chSysLock();
1206  msdp->config->usbp->epc[USB_MS_DATA_EP] = &ep_data_config;
1207  usb_lld_init_endpoint(msdp->config->usbp, USB_MS_DATA_EP);
1208  chBSemReset(&msdp->bsem, false);
1209  chSysUnlock();
1210 
1211  msdp->state = MSD_READ_COMMAND_BLOCK;
1212  wait_for_isr = true;
1213  break;
1214  }
1215 
1216  /* wait until the ISR wakes thread */
1217  if (wait_for_isr) {
1218  msd_wait_for_isr(msdp);
1219  }
1220  }
1221 
1222  return;
1223 }
static void msd_handle_end_point_notification(USBDriver *usbp, usbep_t ep)
Called when data can be read or written on the endpoint – wakes the thread up.
Definition: usb_msd.c:298
static const USBDescriptor vendorDescriptor
Definition: usb_msd.c:1058
unsigned short uint16_t
Definition: types.h:16
Specific RAM section for DMA usage on F7.
#define SCSI_CMD_REQUEST_SENSE
Definition: usb_msd.c:55
bool msd_scsi_process_read_capacity_10(USBMassStorageDriver *msdp)
Processes a READ_CAPACITY_10 SCSI command.
Definition: usb_msd.c:407
static const USBEndpointConfig ep_data_config
End-point 1 initialization structure.
Definition: usb_msd.c:168
void msdStop(USBMassStorageDriver *msdp)
Stops a USB mass storage driver.
Definition: usb_msd.c:900
static const uint8_t productDescriptorData[]
Definition: usb_msd.c:1064
static const uint8_t serialNumberDescriptorData[]
Definition: usb_msd.c:1075
void debug_snd_evt_nl(eventmask_t evt)
Definition: usb_msd.c:937
uint16_t WORD
Definition: usb_msd.c:133
#define MSD_REQ_RESET
Definition: usb_msd.c:35
#define SCSI_SENSE_KEY_DATA_PROTECT
Definition: usb_msd.c:76
static const uint8_t vendorDescriptorData[]
Definition: usb_msd.c:1053
void msdConfigureHookI(USBMassStorageDriver *msdp)
USB device configured handler.
Definition: usb_msd.c:188
BlockDeviceInfo block_dev_info
Definition: usb_msd.h:177
static THD_WORKING_AREA(mass_storage_thread_wa, 1024)
static USBOutEndpointState ep1_out_state
OUT end-point 1 state.
Definition: usb_msd.c:163
#define USBD
Definition: usb_msd.h:44
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST
Definition: usb_msd.c:74
bool msd_scsi_process_start_read_write_10(USBMassStorageDriver *msdp)
Processes a READ_WRITE_10 SCSI command.
Definition: usb_msd.c:449
static const USBDescriptor serialNumberDescriptor
Definition: usb_msd.c:1080
msd_state_t state
Definition: usb_msd.h:178
static void mass_storage_thread(void *arg)
Mass storage thread that processes commands.
Definition: usb_msd.c:1156
#define SCSI_CMD_READ_CAPACITY_10
Definition: usb_msd.c:63
#define SCSI_ASENSE_WRITE_FAULT
Definition: usb_msd.c:85
uint8_t capacity_list_length
Definition: usb_msd.c:123
void msdInit(USBMassStorageDriver *msdp)
Initializse a USB mass storage driver.
Definition: usb_msd.c:815
#define MSD_SETUP_INDEX(setup)
Definition: usb_msd.c:45
usbep_t bulk_ep
Index of the USB endpoint to use for transfers.
Definition: usb_msd.h:137
static USBInEndpointState ep1_in_state
IN end-point 1 state.
Definition: usb_msd.c:158
#define SCSI_SENSE_KEY_MEDIUM_ERROR
Definition: usb_msd.c:72
#define USB_MS_DATA_EP
Definition: usb_msd.h:40
#define MSD_COMMAND_FAILED
Definition: usb_msd.c:50
#define EVT_SEM_RELEASED
Definition: usb_msd.h:52
static const USBConfig usbConfig
Definition: usb_msd.c:1112
static uint8_t IN_DMA_SECTION_CLEAR(rw_buf[2][512])
Read-write buffers (TODO: need a way of specifying the size of this)
#define EVT_SCSI_PROC_INQ
Definition: usb_msd.h:61
bool msd_scsi_process_request_sense(USBMassStorageDriver *msdp)
Processes a REQUEST_SENSE SCSI command.
Definition: usb_msd.c:391
#define EVT_WAIT_FOR_COMMAND_BLOCK
Definition: usb_msd.h:58
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB
Definition: usb_msd.c:90
bool msd_scsi_process_send_diagnostic(USBMassStorageDriver *msdp)
Processes a SEND_DIAGNOSTIC SCSI command.
Definition: usb_msd.c:425
Response to a READ_CAPACITY_10 SCSI command.
Definition: usb_msd.c:113
event_source_t evt_connected
Definition: usb_msd.h:176
thread_t * thread
Definition: usb_msd.h:175
const USBMassStorageConfig * config
Definition: usb_msd.h:173
#define EVT_BOT_RESET
Definition: usb_msd.h:50
bool msd_scsi_process_mode_sense_6(USBMassStorageDriver *msdp)
Processes a MODE_SENSE_6 SCSI command.
Definition: usb_msd.c:588
#define SCSI_SENSE_KEY_GOOD
Definition: usb_msd.c:69
event_source_t evt_ejected
Definition: usb_msd.h:176
#define SCSI_CMD_FORMAT_UNIT
Definition: usb_msd.c:56
#define SCSI_CMD_READ_10
Definition: usb_msd.c:64
uint8_t short_product_version[4]
Short product revision.
Definition: usb_msd.h:163
#define MSD_CSW_SIGNATURE
Definition: usb_msd.c:40
void debug_snd_evt_i(eventmask_t evt)
Definition: usb_msd.c:921
uint32_t DWORD
Definition: usb_msd.c:133
uint32_t desc_and_block_length
Definition: usb_msd.c:125
#define SCSI_CMD_MODE_SENSE_6
Definition: usb_msd.c:58
#define SCSI_CMD_TEST_UNIT_READY
Definition: usb_msd.c:54
#define MSD_COMMAND_PASSED
Definition: usb_msd.c:49
#define MSD_SETUP_LENGTH(setup)
Definition: usb_msd.c:46
void msd_register_evt_ejected(event_listener_t *elp, eventmask_t mask)
register ejected event source in local event mask
Definition: usb_msd.c:1147
#define EVT_SCSI_REQ_READ_CAP10
Definition: usb_msd.h:60
void deinit_msd_driver(void)
Definition: usb_msd.c:1121
#define SCSI_CMD_VERIFY_10
Definition: usb_msd.c:66
static void msd_start_receive(USBMassStorageDriver *msdp, uint8_t *buffer, size_t size)
Starts receiving data.
Definition: usb_msd.c:325
#define SCSI_ASENSE_INVALID_COMMAND
Definition: usb_msd.c:88
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION
Definition: usb_msd.c:84
#define SEM_TAKEN
Definition: usb_msd.h:46
#define EVT_SCSI_REQ_TEST_UNIT_READY
Definition: usb_msd.h:54
USB mass storage driver structure.
Definition: usb_msd.h:172
Driver configuration structure.
Definition: usb_msd.h:123
uint16_t val[TCOUPLE_NB]
unsigned long uint32_t
Definition: types.h:18
#define SCSI_SENSE_KEY_NOT_READY
Definition: usb_msd.c:71
uint32_t block_count
Definition: usb_msd.c:124
#define SCSI_ASENSE_READ_ERROR
Definition: usb_msd.c:87
bool reconfigured_or_reset_event
Definition: usb_msd.h:183
uint32_t last_block_addr
Definition: usb_msd.c:114
#define MSD_GET_MAX_LUN
Definition: usb_msd.c:36
static void msd_scsi_set_sense(USBMassStorageDriver *msdp, uint8_t key, uint8_t acode, uint8_t aqual)
Changes the SCSI sense information.
Definition: usb_msd.c:339
static const USBDescriptor deviceDescriptor
Definition: usb_msd.c:988
#define SCSI_CMD_WRITE_10
Definition: usb_msd.c:65
void init_msd_driver(void *dbgThreadPtr, USBMassStorageConfig *msdConfig)
Definition: usb_msd.c:1126
#define EVT_SEM_TAKEN
Definition: usb_msd.h:51
#define SEM_RELEASED
Definition: usb_msd.h:47
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT
Definition: usb_msd.c:94
USBDriver * usbp
USB driver to use for communication.
Definition: usb_msd.h:127
static USBMassStorageConfig msdConfig
Definition: usbStorage.c:58
static void msd_start_transmit(USBMassStorageDriver *msdp, const uint8_t *buffer, size_t size)
Starts sending data.
Definition: usb_msd.c:311
static const USBDescriptor productDescriptor
Definition: usb_msd.c:1069
void debug_snd_evt_inl(eventmask_t evt)
Definition: usb_msd.c:930
#define SCSI_CMD_INQUIRY
Definition: usb_msd.c:57
static const uint8_t configurationDescriptorData[]
Definition: usb_msd.c:994
#define EVT_USB_RESET
Definition: usb_msd.h:49
bool msd_read_command_block(USBMassStorageDriver *msdp)
Reads a newly received command block.
Definition: usb_msd.c:669
static WORD swap_uint16(const WORD val)
Byte-swap a 16 bits unsigned integer.
Definition: usb_msd.c:149
#define SCSI_CMD_SEND_DIAGNOSTIC
Definition: usb_msd.c:60
#define PACK_STRUCT_BEGIN
Definition: usb_msd.h:36
#define EVT_SCSI_REQ_READ_FMT_CAP
Definition: usb_msd.h:55
#define MSD_SETUP_VALUE(setup)
Definition: usb_msd.c:44
#define SCSI_ASENSEQ_NO_QUALIFIER
Definition: usb_msd.c:96
unsigned char uint8_t
Definition: types.h:14
#define EVT_SCSI_REQ_SENSE6
Definition: usb_msd.h:56
bool msd_wait_for_command_block(USBMassStorageDriver *msdp)
Waits for a new command block.
Definition: usb_msd.c:654
static const struct usb_config_descriptor config
Definition: usb_ser_hw.c:199
#define EVT_SCSI_REQ_SENSE10
Definition: usb_msd.h:57
static const uint8_t languageDescriptorData[]
Definition: usb_msd.c:1042
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL
Definition: usb_msd.c:61
void msd_register_evt_connected(event_listener_t *elp, eventmask_t mask)
register connected event source in local event mask
Definition: usb_msd.c:1142
bool msd_scsi_process_read_format_capacities(USBMassStorageDriver *msdp)
Processes a READ_FORMAT_CAPACITIES SCSI command.
Definition: usb_msd.c:608
uint8_t short_vendor_id[8]
Short vendor identification.
Definition: usb_msd.h:151
#define PACK_STRUCT_END
Definition: usb_msd.h:37
#define SCSI_ASENSE_WRITE_PROTECTED
Definition: usb_msd.c:91
static const USBDescriptor configurationDescriptor
Definition: usb_msd.c:1036
bool msd_scsi_process_start_stop_unit(USBMassStorageDriver *msdp)
Processes a START_STOP_UNIT SCSI command.
Definition: usb_msd.c:570
binary_semaphore_t bsem
Definition: usb_msd.h:174
#define SCSI_SENSE_KEY_RECOVERED_ERROR
Definition: usb_msd.c:70
thread_t * dbg_printer
Definition: usb_msd.c:109
static const uint8_t deviceDescriptorData[]
Definition: usb_msd.c:971
uint32_t block_size
Definition: usb_msd.c:115
#define SCSI_CMD_START_STOP_UNIT
Definition: usb_msd.c:59
bool msd_scsi_process_test_unit_ready(USBMassStorageDriver *msdp)
Processes a TEST_UNIT_READY SCSI command.
Definition: usb_msd.c:627
static void usbEvent(USBDriver *usbp, usbevent_t event)
Definition: usb_msd.c:945
void(* rw_activity_callback)(bool)
Optional callback that will be called whenever there is read/write activity.
Definition: usb_msd.h:145
static void msd_wait_for_isr(USBMassStorageDriver *msdp)
Wait until the end-point interrupt handler has been called.
Definition: usb_msd.c:285
static const USBDescriptor * getDescriptor(USBDriver *usbp, uint8_t type, uint8_t index, uint16_t lang)
Definition: usb_msd.c:1087
void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config)
Starts a USB mass storage driver.
Definition: usb_msd.c:855
msd_scsi_inquiry_response_t inquiry
Definition: usb_msd.h:182
BaseBlockDevice * bbdp
Block device to use for storage.
Definition: usb_msd.h:132
#define MSD_CBW_SIGNATURE
Definition: usb_msd.c:39
#define SCSI_CMD_READ_FORMAT_CAPACITIES
Definition: usb_msd.c:62
bool msd_scsi_process_inquiry(USBMassStorageDriver *msdp)
Processes an INQUIRY SCSI command.
Definition: usb_msd.c:349
bool msdRequestsHook(USBDriver *usbp)
Default requests hook.
Definition: usb_msd.c:205
static const USBDescriptor languageDescriptor
Definition: usb_msd.c:1047
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
Definition: usb_msd.c:89
uint8_t short_product_id[16]
Short product identification.
Definition: usb_msd.h:157
static DWORD swap_uint32(const DWORD val)
Byte-swap a 32 bits unsigned integer.
Definition: usb_msd.c:140
msd_scsi_sense_response_t sense
Definition: usb_msd.h:181
static USBMassStorageDriver UMSD
Definition: usb_msd.c:33