1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * PolarFire SoC MSS USB Driver Stack
7  *      USB Logical Layer (USB-LL)
8  *          USBD-MSC class driver.
9  *
10  * USBD-MSC class driver implementation:
11  * This source file implements Mass storage class functionality.
12  * BoT with Transparent SCSI command set is implemented.
13  *
14  */
15 
16 #include "mpfs_hal/mss_hal.h"
17 #include "mss_usb_device.h"
18 #include "mss_usb_device_msd.h"
19 #include "mss_usb_std_def.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 #ifdef MSS_USB_DEVICE_ENABLED
26 
27 #define MSC_CLASS_BULK_RX_EP                            MSS_USB_RX_EP_1
28 #define MSC_CLASS_BULK_TX_EP                            MSS_USB_TX_EP_1
29 
30 #define MSC_CLASS_INTERFACE_NUM                         0x00
31 /*HS Operation values*/
32 #define MSC_TX_EP_FIFO_SIZE_HS                          512
33 #define MSC_RX_EP_FIFO_SIZE_HS                          512
34 
35 /*Values should be same as described in ep descriptors*/
36 #define MSC_TX_EP_MAX_PKT_SIZE_HS                       512
37 #define MSC_RX_EP_MAX_PKT_SIZE_HS                       512
38 
39 /*LS Operation values*/
40 #define MSC_TX_EP_FIFO_SIZE_FS                          64
41 #define MSC_RX_EP_FIFO_SIZE_FS                          64
42 
43 /*Values should be same as described in ep descriptors*/
44 #define MSC_TX_EP_MAX_PKT_SIZE_FS                       64
45 #define MSC_RX_EP_MAX_PKT_SIZE_FS                       64
46 
47 
48 #define G_BOT_CBW_INIT();                               g_bot_cbw.signature = 0;\
49                                                         g_bot_cbw.tag = 0;\
50                                                         g_bot_cbw.xfr_length = 0;\
51                                                         g_bot_cbw.flags = 0;\
52                                                         g_bot_cbw.lun = 0;\
53                                                         g_bot_cbw.cmd_length = 0;\
54                                                         g_bot_cbw.cmd_block[0]=(uint8_t)0;\
55                                                         g_bot_cbw.cmd_block[1]=(uint8_t)0;\
56                                                         g_bot_cbw.cmd_block[2]=(uint8_t)0;\
57                                                         g_bot_cbw.cmd_block[3]=(uint8_t)0;\
58                                                         g_bot_cbw.cmd_block[4]=(uint8_t)0;\
59                                                         g_bot_cbw.cmd_block[5]=(uint8_t)0;\
60                                                         g_bot_cbw.cmd_block[6]=(uint8_t)0;\
61                                                         g_bot_cbw.cmd_block[7]=(uint8_t)0;\
62                                                         g_bot_cbw.cmd_block[8]=(uint8_t)0;\
63                                                         g_bot_cbw.cmd_block[9]=(uint8_t)0;\
64                                                         g_bot_cbw.cmd_block[10]=(uint8_t)0;\
65                                                         g_bot_cbw.cmd_block[11]=(uint8_t)0;\
66                                                         g_bot_cbw.cmd_block[12]=(uint8_t)0;\
67                                                         g_bot_cbw.cmd_block[13]=(uint8_t)0;\
68                                                         g_bot_cbw.cmd_block[14]=(uint8_t)0;\
69                                                         g_bot_cbw.cmd_block[15]=(uint8_t)0;
70 
71 
72 #define CB_PASS                                         0x01u
73 #define CB_NOT_SUPPORTED                                0x02u
74 #define CB_INTERNAL_ERROR                               0x03u
75 #define CB_LENGTH_MISMATCH                              0x04u
76 #define CB_DATA_DIR_MISMATCH                            0x05u
77 #define CB_MOREDATA                                     0x06u
78 #define CB_LESSDATA                                     0x07u
79 #define CB_INVALID_LUN                                  0x08u
80 #define CB_INVALID_CDB_FIELD                            0x09u
81 #define CB_INVALID_CBW                                  0x0Au
82 #define CB_DATAPHASE_ERROR                              0x0Bu
83 
84 #define MSCD_CONF_DESCR_DESCTYPE_IDX                    1u
85 
86 
87 /***************************************************************************//**
88  Local functions used by USBD-MSC class driver.
89  */
90 static uint8_t usbd_msc_process_cbw(mss_usb_msc_cbw_t * cbw);
91 static void usbd_msc_prepare_sense_data(uint8_t lun, uint8_t skey, uint8_t asc);
92 static void usbd_msc_abort_cbw(uint8_t lun);
93 static void usbd_msc_bot_fsm(uint8_t status, uint32_t rx_count);
94 static void usbd_msc_send_data(uint8_t* buf, uint32_t len);
95 static void usbd_msc_receive_data(uint8_t* buf, uint32_t len);
96 static void usbd_msc_send_csw(void);
97 static void usbd_msc_stallin_sendstatus(void);
98 static void usbd_msc_stallout_sendstatus(void);
99 static uint8_t usbd_msc_process_read_10(void);
100 static uint8_t usbd_msc_process_write_10(void);
101 static uint8_t usbd_msc_process_inquiry(void);
102 static uint8_t usbd_msc_process_read_capacity_10(void);
103 
104 /***************************************************************************//**
105  Implementations of Call-back functions used by USBD.
106  */
107 static uint8_t* usbd_msc_get_descriptor_cb(uint8_t recepient,
108                                            uint8_t type,
109                                            uint32_t* length,
110                                            mss_usb_device_speed_t musb_speed);
111 
112 static uint8_t usbd_msc_init_cb(uint8_t cfgidx, mss_usb_device_speed_t musb_speed);
113 static uint8_t usbd_msc_release_cb(uint8_t cfgidx);
114 static uint8_t usbd_msc_tx_complete_cb(mss_usb_ep_num_t num, uint8_t status);
115 
116 static uint8_t usbd_msc_rx_cb(mss_usb_ep_num_t num,
117                                     uint8_t status,
118                                     uint32_t rx_count);
119 
120 static uint8_t usbd_msc_process_request_cb(mss_usbd_setup_pkt_t* setup_pkt,
121                                            uint8_t** buf_pp,
122                                            uint32_t* length);
123 
124 /*******************************************************************************
125  Global variables used by USBD-MSC class driver.
126  */
127 
128 /*Buffer for responding to GET_MAX_LUN*/
129 uint8_t get_max_lun_response[]  __attribute__ ((aligned (4))) = {0x00u};
130 
131 /*
132  Buffer for responding to READ_FORMAT CAPACITIES command. Values will be provided
133  by Apps.
134  Driver Does not store Values for All the LUNs.
135  Values of the The LUN on which last USB_MSC_SCSI_READ_FORMAT_CAPACITIES command
136  was executed will be there in this buffer.
137  */
138 uint8_t format_capacity_list[12] __attribute__ ((aligned (4))) = {0};
139 /*
140  Buffer for responding to READ_CAPACITY_10 command. Values will be provided by Apps.
141  Driver retains values for all the supported LUN and uses them to calculate valid
142  address range for that LUN.
143  */
144 mss_usbd_msc_lun_capacity_t lun_capacity[4] __attribute__ ((aligned (4)))= {{0},{0},{0},{0}};
145 /*
146  Buffer to respond to USB_MSC_SCSI_MODE_SENSE_6 command.
147  Values are generated by driver.Same values are returned for all supported LUNs.
148  */
149 uint8_t mode_sense_response[4] __attribute__ ((aligned (4))) = {0x03u, 0x00u, 0x00u, 0x00u};
150 
151 /*
152  The g_sense_response is used to respond to REQUEST_SENSE request.
153  Value of this variable is changed depending on the type of failure while
154  responding to the host request.
155  */
156 mss_usbd_msc_scsi_sense_resp_t g_sense_response __attribute__ ((aligned (4))) = {0xF0,0,0,{0},0x0b,{0},0,{0}};
157 
158  /*
159   The g_bot_cbw is used to store the current CBW sent by the the host as a
160   BOT request.
161   */
162 mss_usb_msc_cbw_t g_bot_cbw __attribute__ ((aligned (4)));
163 
164 /*
165  The g_current_command_csw structure is used to provide the status of the command.
166  The Values of the elements of this structure are updated according to the state
167  of the driver,success/Failure of the command and type of failure.
168  */
169 mss_usbd_msc_csw_t g_current_command_csw __attribute__ ((aligned (4))) =
170                                             {USB_MSC_BOT_CSW_SIGNATURE,
171                                             0,
172                                             0,
173                                             SCSI_COMMAND_PASS};
174 
175 /*****************************************************************************/
176 
177 /* Definition for Flash drive application call-backs. */
178 mss_usbd_msc_media_t *g_usbd_msc_media_ops;
179 
180 /* USB current Speed of operation selected by user*/
181 mss_usb_device_speed_t g_usbd_msc_user_speed;
182 
183 /*
184  Global variables used for multi-transfer OUT transactions
185  */
186 uint8_t* g_xfr_buf_ptr = 0;
187 uint32_t g_xfr_buf_len = 0u;
188 uint32_t g_xfr_lba_addr = 0u;
189 
190 typedef enum scsi_req_type {
191     SCSI_ZDR,
192     SCSI_IN,
193     SCSI_OUT
194 } scsi_req_type_t;
195 scsi_req_type_t g_req_type = SCSI_ZDR;
196 /*
197  The g_bot_state is used to store the current state of the driver during
198  Bulk-only Transport (BOT) transaction.
199  The drivers response to the host request depends on this state.
200  */
201 volatile mss_usbd_msc_bot_state_t g_bot_state;
202 /*
203  This variable tracks the current state of the USBD-MSC driver.
204  */
205 mss_usbd_msc_state_t g_usbd_msc_state = USBD_MSC_NOT_CONFIGURED;
206 
207 /* The g_bot_events is used to know the current event in the BOT transfer */
208 volatile mss_usbd_msc_bot_events_t g_bottx_events = BOT_EVENT_IDLE;
209 volatile mss_usbd_msc_bot_events_t g_botrx_events = BOT_EVENT_IDLE;
210 
211 mss_usbd_class_cb_t usb_msd_class_cb = {usbd_msc_init_cb,
212                                         usbd_msc_release_cb,
213                                         usbd_msc_get_descriptor_cb,
214                                         usbd_msc_process_request_cb,
215                                         usbd_msc_tx_complete_cb,
216                                         usbd_msc_rx_cb,
217                                         0,
218                                         0 };
219 
220 uint8_t msc_fs_conf_descr[FULL_CONFIG_DESCR_LENGTH] =
221 {
222     /*----------------------- Configuration Descriptor -----------------------*/
223     USB_STD_CONFIG_DESCR_LEN,                       /* bLength */
224     USB_CONFIGURATION_DESCRIPTOR_TYPE,              /* bDescriptorType */
225     FULL_CONFIG_DESCR_LENGTH,                       /* wTotalLength LSB */
226     0x00u,                                          /* wTotalLength MSB */
227     0x01u,                                          /* bNumInterfaces */
228     0x01u,                                          /* bConfigurationValue */
229     0x04u,                                          /* iConfiguration */
230     0xC0u,                                          /* bmAttributes */
231     0x32u,                                          /* bMaxPower */
232     /*------------------------- Interface Descriptor -------------------------*/
233     USB_STD_INTERFACE_DESCR_LEN,                    /* bLength */
234     USB_INTERFACE_DESCRIPTOR_TYPE,                  /* bDescriptorType */
235     MSC_CLASS_INTERFACE_NUM,                        /* bInterfaceNumber */
236     0x00u,                                          /* bAlternateSetting */
237     0x02u,                                          /* bNumEndpoints */
238     0x08u,                                          /* bInterfaceClass */
239     0x06u,                                          /* bInterfaceSubClass */
240     0x50u,                                          /* bInterfaceProtocol */
241     0x05u,                                          /* bInterface */
242     /*------------------------- IN Endpoint Descriptor --------------------------*/
243     USB_STD_ENDPOINT_DESCR_LEN,                     /* bLength */
244     USB_ENDPOINT_DESCRIPTOR_TYPE,                   /* bDescriptorType */
245     (0x80u | MSC_CLASS_BULK_TX_EP),                 /* bEndpointAddress */
246     0x02u,                                          /* bmAttributes */
247     0x40u,                                          /* wMaxPacketSize LSB */ //22
248     0x00u,                                          /* wMaxPacketSize MSB */ //23
249     0xFFu,                                          /* bInterval */  //ignored by host for Bulk IN EP
250     /*------------------------- OUT Endpoint Descriptor --------------------------*/
251     USB_STD_ENDPOINT_DESCR_LEN,                     /* bLength */
252     USB_ENDPOINT_DESCRIPTOR_TYPE,                   /* bDescriptorType */
253     MSC_CLASS_BULK_RX_EP,                           /* bEndpointAddress */
254     0x02u,                                          /* bmAttributes */
255     0x40u,                                          /* wMaxPacketSize LSB *///29
256     0x00u,                                          /* wMaxPacketSize MSB *///30
257     0xFFu                                           /* bInterval *//*Max NAK rate*/
258 };
259 
260 /*
261  Configuration descriptor and sub-ordinate descriptors to enumerate the USB device
262  as Mass Storage class Device by host.
263  */
264 uint8_t msc_hs_conf_descr[FULL_CONFIG_DESCR_LENGTH] =
265 {
266     /*----------------------- Configuration Descriptor -----------------------*/
267     USB_STD_CONFIG_DESCR_LEN,                       /* bLength */
268     USB_CONFIGURATION_DESCRIPTOR_TYPE,              /* bDescriptorType */
269     FULL_CONFIG_DESCR_LENGTH,                       /* wTotalLength LSB */
270     0x00u,                                          /* wTotalLength MSB */
271     0x01u,                                          /* bNumInterfaces */
272     0x01u,                                          /* bConfigurationValue */
273     0x04u,                                          /* iConfiguration */
274     0xC0u,                                          /* bmAttributes */
275     0x32u,                                          /* bMaxPower */
276     /*------------------------- Interface Descriptor -------------------------*/
277     USB_STD_INTERFACE_DESCR_LEN,                    /* bLength */
278     USB_INTERFACE_DESCRIPTOR_TYPE,                  /* bDescriptorType */
279     MSC_CLASS_INTERFACE_NUM,                        /* bInterfaceNumber */
280     0x00u,                                          /* bAlternateSetting */
281     0x02u,                                          /* bNumEndpoints */
282     0x08u,                                          /* bInterfaceClass */
283     0x06u,                                          /* bInterfaceSubClass */
284     0x50u,                                          /* bInterfaceProtocol */
285     0x05u,                                          /* bInterface */
286     /*------------------------- IN Endpoint Descriptor --------------------------*/
287     USB_STD_ENDPOINT_DESCR_LEN,                     /* bLength */
288     USB_ENDPOINT_DESCRIPTOR_TYPE,                   /* bDescriptorType */
289     (0x80u | MSC_CLASS_BULK_TX_EP),                 /* bEndpointAddress */
290     0x02u,                                          /* bmAttributes */
291     0x00u,                                          /* wMaxPacketSize LSB */ //22
292     0x02u,                                          /* wMaxPacketSize MSB */ //23
293     0xFFu,                                          /* bInterval *///ignored by host for Bulk IN EP
294     /*------------------------- OUT Endpoint Descriptor --------------------------*/
295     USB_STD_ENDPOINT_DESCR_LEN,                     /* bLength */
296     USB_ENDPOINT_DESCRIPTOR_TYPE,                   /* bDescriptorType */
297     MSC_CLASS_BULK_RX_EP,                           /* bEndpointAddress */
298     0x02u,                                          /* bmAttributes */
299     0x00u,                                          /* wMaxPacketSize LSB *///29
300     0x02u,                                          /* wMaxPacketSize MSB *///30
301     0xFFu                                           /* bInterval */                /*Max NAK rate*/
302 };
303 
304 void
MSS_USBD_MSC_init(mss_usbd_msc_media_t * media_ops,mss_usb_device_speed_t speed)305 MSS_USBD_MSC_init
306 (
307     mss_usbd_msc_media_t* media_ops,
308     mss_usb_device_speed_t speed
309 )
310 {
311     g_usbd_msc_media_ops = media_ops;
312     g_usbd_msc_user_speed = speed;
313 
314     MSS_USBD_set_class_cb_handler(&usb_msd_class_cb);
315 }
316 
317 mss_usbd_msc_state_t
MSS_USBD_MSC_get_state(void)318 MSS_USBD_MSC_get_state
319 (
320     void
321 )
322 {
323     return g_usbd_msc_state;
324 }
325 
326 /***************************************************************************//**
327  returns the configuration descriptor requested by Host.
328  */
329 static uint8_t*
usbd_msc_get_descriptor_cb(uint8_t recepient,uint8_t type,uint32_t * length,mss_usb_device_speed_t musb_speed)330 usbd_msc_get_descriptor_cb
331 (
332     uint8_t recepient,
333     uint8_t type,
334     uint32_t* length,
335     mss_usb_device_speed_t musb_speed
336 )
337 {
338     uint8_t* conf_desc = 0;
339     uint8_t* os_conf_desc = 0;
340     uint8_t conf_desc_len = 0u;
341     uint8_t os_conf_desc_len = 0u;
342 
343     /*User Selected FS:
344         Operate only in FS
345       User Selected HS:
346         Device connected to 2.0 Host(musb_speed = HS):Operate in HS
347         Device connected to 1.x Host(musb_speed = FS):Operate in FS
348     */
349     if(MSS_USB_DEVICE_FS == g_usbd_msc_user_speed)
350     {
351         conf_desc = msc_fs_conf_descr;
352         conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
353         conf_desc_len = sizeof(msc_fs_conf_descr);
354         os_conf_desc = 0u;
355         os_conf_desc_len = 0u;
356     }
357     else if(MSS_USB_DEVICE_HS == g_usbd_msc_user_speed)
358     {
359         if(MSS_USB_DEVICE_HS == musb_speed)
360         {
361             conf_desc = msc_hs_conf_descr;
362             conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
363             conf_desc_len = sizeof(msc_hs_conf_descr);
364             os_conf_desc = msc_fs_conf_descr;
365             os_conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE;
366             os_conf_desc_len = sizeof(msc_fs_conf_descr);
367         }
368         else if(MSS_USB_DEVICE_FS == musb_speed)
369         {
370             conf_desc = msc_fs_conf_descr;
371             conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
372             conf_desc_len = sizeof(msc_fs_conf_descr);
373             os_conf_desc = msc_hs_conf_descr;
374             os_conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE;
375             os_conf_desc_len = sizeof(msc_hs_conf_descr);
376         }
377     }
378     else
379     {
380         ASSERT(0);      //user must select FS or HS, nothing else.
381     }
382 
383     if(USB_STD_REQ_RECIPIENT_DEVICE == recepient)
384     {
385         if(USB_CONFIGURATION_DESCRIPTOR_TYPE == type)
386         {
387            *length = conf_desc_len;
388             return(conf_desc);
389         }
390         else if(USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE == type)
391         {
392             ASSERT(os_conf_desc != 0u);
393             *length = os_conf_desc_len;
394 
395             return(os_conf_desc);
396         }
397     }
398     else if(USB_STD_REQ_RECIPIENT_ENDPOINT == recepient)    /*Need index(EP Num) here*/
399     {
400         /*Do nothing*/
401     }
402     else if(USB_STD_REQ_RECIPIENT_INTERFACE == recepient)     /*Need index(interface number) here*/
403     {
404         /*Do nothing*/
405     }
406     else
407     {
408         /*Do nothing*/
409     }
410 
411     return USB_FAIL;
412 }
413 
414 /***************************************************************************//**
415  usbd_msc_init_cb() call-back is called by USB Device mode driver on receiving
416  SET_CONFIGURATION command. The MSC class specific configurations are performed
417  by this function.
418  */
419 static uint8_t
usbd_msc_init_cb(uint8_t cfgidx,mss_usb_device_speed_t musb_speed)420 usbd_msc_init_cb
421 (
422     uint8_t cfgidx,
423     mss_usb_device_speed_t musb_speed
424 )
425 {
426     uint16_t bulk_rxep_fifo_sz = 0u;
427     uint16_t bulk_rxep_maxpktsz = 0u;
428 
429     uint16_t bulk_txep_fifo_sz = 0u;
430     uint16_t bulk_txep_maxpktsz = 0u;
431 
432     g_bottx_events = BOT_EVENT_IDLE;
433     g_botrx_events = BOT_EVENT_IDLE;
434     g_bot_state = BOT_IDLE;
435     g_current_command_csw.data_residue = 0u;
436     g_current_command_csw.tag = 0u;
437     g_current_command_csw.status = SCSI_COMMAND_FAIL;
438     G_BOT_CBW_INIT();
439     g_xfr_buf_ptr = 0;
440     g_xfr_buf_len = 0u;
441     g_xfr_lba_addr = 0u;
442 
443       /*
444       User Selected FS: Operate only in FS
445       User Selected HS:
446         Device connected to 2.0 Host(musb_speed = HS):Operate in HS
447         Device connected to 1.x Host(musb_speed = FS):Operate in FS
448       */
449       /*
450       We calculate the Bulk endpoint sizes and max_pkt_size based on the
451       respective endpoint speed. This is done so that the config descriptor change
452       reflects here and this function need not be updated for that.
453       */
454     if(MSS_USB_DEVICE_FS == musb_speed)
455     {
456         bulk_txep_fifo_sz = (uint16_t)((msc_fs_conf_descr[23u] << 8u) | (msc_fs_conf_descr[22u]));
457         bulk_txep_maxpktsz = (uint16_t)((msc_fs_conf_descr[23u] << 8u) | (msc_fs_conf_descr[22u]));
458         bulk_rxep_fifo_sz = (uint16_t)((msc_fs_conf_descr[30u] << 8u) | (msc_fs_conf_descr[29u]));
459         bulk_rxep_maxpktsz = (uint16_t)((msc_fs_conf_descr[30u] << 8u) | (msc_fs_conf_descr[29u]));
460     }
461     else if(MSS_USB_DEVICE_HS == musb_speed)
462     {
463         bulk_txep_fifo_sz = (uint16_t)((msc_hs_conf_descr[23u] << 8u) | (msc_hs_conf_descr[22u]));
464         bulk_txep_maxpktsz = (uint16_t)((msc_hs_conf_descr[23u] << 8u) | (msc_hs_conf_descr[22u]));
465         bulk_rxep_fifo_sz = (uint16_t)((msc_hs_conf_descr[30u] << 8u) | (msc_hs_conf_descr[29u]));
466         bulk_rxep_maxpktsz = (uint16_t)((msc_hs_conf_descr[30u] << 8u) | (msc_hs_conf_descr[29u]));
467     }
468     else
469     {
470         ASSERT(0); /*speed value can not be any other than FS or HS*/
471     }
472 
473     MSS_USBD_rx_ep_configure(MSC_CLASS_BULK_RX_EP,
474                              0x100u,
475                              bulk_rxep_fifo_sz,
476                              bulk_rxep_maxpktsz,
477                              1u,
478                              DMA_ENABLE,
479                              MSS_USB_DMA_CHANNEL1,
480                              MSS_USB_XFR_BULK,
481                              NO_ZLP_TO_XFR);
482 
483     MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
484                                 (uint8_t*)&g_bot_cbw,
485                                 USBD_MSC_BOT_CBW_LENGTH);
486 
487     MSS_USBD_tx_ep_configure(MSC_CLASS_BULK_TX_EP,
488                              0x300u,
489                              bulk_txep_fifo_sz,
490                              bulk_txep_maxpktsz,
491                              1u,
492                              DMA_ENABLE,
493                              MSS_USB_DMA_CHANNEL2,
494                              MSS_USB_XFR_BULK,
495                              NO_ZLP_TO_XFR);
496 
497     g_usbd_msc_state = USBD_MSC_CONFIGURED;
498 
499     if(0 != g_usbd_msc_media_ops->media_init)
500     {
501         g_usbd_msc_media_ops->media_init(0);/*Todo:Remove the lun parameter*/
502     }
503 
504     return USB_SUCCESS;
505 }
506 
507 /***************************************************************************//**
508  usbd_msc_release_cb() call-back is called by USB Device mode driver on receiving
509  a command to clear the configuration.
510  */
511 static uint8_t
usbd_msc_release_cb(uint8_t cfgidx)512 usbd_msc_release_cb
513 (
514     uint8_t cfgidx
515 )
516 {
517     g_usbd_msc_state = USBD_MSC_NOT_CONFIGURED;
518     MSS_USB_CIF_tx_ep_disable_irq(MSC_CLASS_BULK_TX_EP);
519     MSS_USB_CIF_tx_ep_clr_csrreg(MSC_CLASS_BULK_TX_EP);
520     MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL2);
521 
522     MSS_USB_CIF_rx_ep_disable_irq(MSC_CLASS_BULK_RX_EP);
523     MSS_USB_CIF_rx_ep_clr_csrreg(MSC_CLASS_BULK_RX_EP);
524     MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL1);
525 
526     if(0 != g_usbd_msc_media_ops->media_release)
527     {
528         g_usbd_msc_media_ops->media_release(cfgidx);
529     }
530 
531     return USB_SUCCESS;
532 }
533 
534 /***************************************************************************//**
535  usbd_msc_process_request_cb() call-back function Process the MSC class requests.
536  */
537 static uint8_t
usbd_msc_process_request_cb(mss_usbd_setup_pkt_t * setup_pkt,uint8_t ** buf_pp,uint32_t * length)538 usbd_msc_process_request_cb
539 (
540     mss_usbd_setup_pkt_t* setup_pkt,
541     uint8_t** buf_pp,
542     uint32_t* length
543 )
544 {
545     if((MSC_CLASS_INTERFACE_NUM == setup_pkt->index) && (0u == setup_pkt->value))
546     {
547         switch(setup_pkt->request)
548         {
549             case USB_MSC_BOT_REQ_GET_MAX_LUN:
550                 /*Return the max LUN index, not the actual number of LUNs*/
551                 ASSERT(g_usbd_msc_media_ops->media_get_max_lun !=0u);
552 
553                 if(0 != g_usbd_msc_media_ops->media_get_max_lun)
554                 {
555                     get_max_lun_response[0] = (g_usbd_msc_media_ops->media_get_max_lun() - 1u);
556                 }
557 
558                 *length = sizeof(get_max_lun_response);
559                 *buf_pp = (uint8_t*)&get_max_lun_response;
560 
561             return USB_SUCCESS;
562 
563             case USB_MSC_BOT_REQ_BMS_RESET:
564                 if(0u == setup_pkt->length)
565                 {
566                     /*
567                     LVp:62 - prepare for next CBW. Don't change the stall
568                     and Data toggle bit on Bulk EPs.
569                     */
570                     g_bottx_events = BOT_EVENT_IDLE;
571                     g_botrx_events = BOT_EVENT_IDLE;
572                     g_bot_state = BOT_IDLE;
573                     g_current_command_csw.data_residue = 0u;
574                     g_current_command_csw.tag = 0u;
575                     g_current_command_csw.status = SCSI_COMMAND_FAIL;
576                     G_BOT_CBW_INIT();
577                     g_xfr_buf_ptr = (uint8_t*)0;
578                     g_xfr_buf_len = 0u;
579                     g_xfr_lba_addr = 0u;
580                     MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
581                                                 (uint8_t*)&g_bot_cbw,
582                                                 USBD_MSC_BOT_CBW_LENGTH);
583 
584                     return USB_SUCCESS;
585                 }
586                 else
587                 {
588                     return USB_FAIL;
589                 }
590 
591             default:
592                 length = 0u;
593 
594                 return USB_FAIL;
595         }
596     }
597     else
598     {
599         return USB_FAIL;
600     }
601 }
602 
603 /***************************************************************************//**
604  usbd_msc_tx_complete_cb() call-back function is called by USB Device mode driver
605  on completion of the Current Data Transmissions (IN Transaction) which was
606  previously initiated using MSS_USBD_tx_ep_configure().
607  */
usbd_msc_tx_complete_cb(mss_usb_ep_num_t num,uint8_t status)608 static uint8_t usbd_msc_tx_complete_cb
609 (
610     mss_usb_ep_num_t num,
611     uint8_t status
612 )
613 {
614     /*Underrun error ignore, it only means we are slow and that is because of
615     the slow serial flash memory*/
616     if(status & (TX_EP_STALL_ERROR))
617     {
618         g_bottx_events = BOT_EVENT_TX_ERROR;
619     }
620     else
621     {
622         g_bottx_events = BOT_EVENT_TX;
623     }
624 
625     usbd_msc_bot_fsm(status, 0u);
626 
627     return USB_SUCCESS;
628 }
629 
630 /***************************************************************************//**
631  usbd_msc_rx_cb() call-back function is called by USB Device mode driver
632  on completion of data reception. USB Device mode driver must have been
633  previously prepared for this data reception using
634  MSS_USBD_rx_ep_read_prepare()
635  */
636 static uint8_t
usbd_msc_rx_cb(mss_usb_ep_num_t num,uint8_t status,uint32_t rx_count)637 usbd_msc_rx_cb
638 (
639     mss_usb_ep_num_t num,
640     uint8_t status,
641     uint32_t rx_count
642 )
643 {
644     /*
645     4.3.5.6
646     xfr length > Allocation length field ==> Terminate with CHECK CONDITION status,
647     sense key = ILLEGAL_REQUEST, additional sense code = INVALID FIELD in CDB
648     when NACA bit = 0 ==> ACA condition is not set = command abort should be done
649     as per sam-5, 5.8.2
650     */
651     if(status & (RX_EP_OVER_RUN_ERROR | RX_EP_STALL_ERROR |
652                  RX_EP_DATA_ERROR | RX_EP_PID_ERROR | RX_EP_ISO_INCOMP_ERROR))
653     {
654         g_botrx_events = BOT_EVENT_RX_ERROR;
655     }
656     else
657     {
658         g_botrx_events = BOT_EVENT_RX;
659     }
660 
661     usbd_msc_bot_fsm(status, rx_count);
662 
663     return USB_SUCCESS;
664 }
665 
666 /***************************************************************************//**
667  usbd_msc_bot_fsm() function is the state machine for BOT transfers.
668  */
669 static void
usbd_msc_bot_fsm(uint8_t status,uint32_t rx_count)670 usbd_msc_bot_fsm
671 (
672     uint8_t status,
673     uint32_t rx_count
674 )
675 {
676     uint8_t cb_result = CB_INTERNAL_ERROR;
677     switch (g_bot_state)
678     {
679     case BOT_IDLE:
680         if(BOT_EVENT_RX == g_botrx_events)
681         {
682             if(rx_count != USBD_MSC_BOT_CBW_LENGTH )
683             {
684                 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
685                 usbd_msc_abort_cbw(0u);
686             }
687             else
688             {
689                 cb_result = usbd_msc_process_cbw(&g_bot_cbw);
690                 g_current_command_csw.data_residue = g_bot_cbw.xfr_length;
691 
692 
693                 switch(cb_result)
694                 {
695                     case CB_PASS:
696                         g_current_command_csw.status = SCSI_COMMAND_PASS;
697                         if(g_req_type == SCSI_OUT)
698                         {
699                             //CASE:12 (Success)
700                             usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
701                         }
702                         else if(g_req_type == SCSI_IN)
703                         {
704                             //CASE:6 (Success)
705                             usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
706                         }
707                         else if(g_req_type == SCSI_ZDR)
708                         {
709                             //CASE:1 (Success)
710                             usbd_msc_send_csw();
711                         }
712                         else
713                         {
714                             ASSERT(0); /*invalid req_type value*/
715                         }
716                     break;
717 
718                     case CB_LESSDATA:
719                         g_current_command_csw.status = SCSI_COMMAND_LESSDATAPASS;
720 
721                         if(SCSI_OUT == g_req_type)
722                         {
723                             if(g_xfr_buf_len)
724                             {
725                                 //CASE11(lvr:dont stall this)
726                                 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
727                             }
728                             else
729                             {
730                                 //CASE9-This needs to be cross-checked
731                                 usbd_msc_stallin_sendstatus();
732                             }
733                         }
734                         else if(SCSI_IN == g_req_type)
735                         {
736                             if(g_xfr_buf_len)
737                             {
738                                 //CASE5: send a stall and status after dataPhase.
739                                 usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
740                             }
741                             else
742                             {
743                                 //CASE4
744                                 usbd_msc_stallin_sendstatus();
745                             }
746                         }
747                         else
748                         {
749                             ASSERT(0);/*invalid req_type value*/
750                         }
751                     break;
752 
753                     case CB_MOREDATA:
754                         if(SCSI_OUT == g_req_type )
755                         {
756                             if(g_xfr_buf_len)
757                             {
758                                 //CASE13
759                                 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
760                                 usbd_msc_stallout_sendstatus();
761                             }
762                             else
763                             {
764                                 ASSERT(0);   //shouldn't happen
765                             }
766                         }
767                         else if(SCSI_IN == g_req_type)
768                         {
769                             //CASE7 stall then send status
770                             g_current_command_csw.status = SCSI_COMMAND_FAIL;
771                             usbd_msc_stallin_sendstatus();
772                         }
773                         else
774                         {
775                             ASSERT(0);
776                         }
777                     break;
778 
779                     case CB_INVALID_CDB_FIELD:
780                         /*No data, only stall*/
781                         g_current_command_csw.status = SCSI_COMMAND_FAIL;
782                         usbd_msc_stallin_sendstatus();
783                     break;
784 
785                     case CB_NOT_SUPPORTED:
786                         /*Command Not supported.*/
787                         g_current_command_csw.status = SCSI_COMMAND_FAIL;
788 
789                         if(0 == g_bot_cbw.xfr_length)
790                         {
791                             usbd_msc_stallin_sendstatus();
792                         }
793                         else
794                         {
795                             if(g_bot_cbw.flags & 0x80u) //IN D2H
796                             {
797                                 usbd_msc_stallin_sendstatus();
798                             }
799                             else    //OUT H2D
800                             {
801                                 usbd_msc_stallout_sendstatus();
802                                 usbd_msc_stallin_sendstatus();
803                             }
804                         }
805                     break;
806 
807                     case CB_INTERNAL_ERROR:
808                         /*Dont respond till reset recovery*/
809                         g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
810                         usbd_msc_abort_cbw(0u);
811                     break;
812 
813                     case CB_LENGTH_MISMATCH:
814                         if(SCSI_OUT == g_req_type)
815                         {
816                             if(0u == g_xfr_buf_len)
817                             {
818                                 g_current_command_csw.status = SCSI_COMMAND_FAIL;
819                                 usbd_msc_stallout_sendstatus();
820                             }
821                             else if(g_xfr_buf_len > g_bot_cbw.xfr_length)
822                             {
823                                 //CASE13
824                                 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
825                                 usbd_msc_stallout_sendstatus();
826                             }
827                             else
828                             {
829                                 //CASE11(lvr:dont stall this)
830                                 g_current_command_csw.status = SCSI_COMMAND_FAIL;
831                                 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
832                             }
833                         }
834                         else if(SCSI_IN == g_req_type)
835                         {
836                             if(0u == g_xfr_buf_len)
837                             {
838                                 g_current_command_csw.status = SCSI_COMMAND_FAIL;
839                                 usbd_msc_stallout_sendstatus();
840                             }
841                             else if(g_xfr_buf_len > g_bot_cbw.xfr_length)
842                             {
843                                 //CASE7 stall then send status
844                                 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
845                                 usbd_msc_stallin_sendstatus();
846                             }
847                             else
848                             {
849                                 g_current_command_csw.status = SCSI_COMMAND_FAIL;
850                                 usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
851                             }
852                         }
853                         else
854                         {
855                             g_current_command_csw.status = SCSI_COMMAND_FAIL;
856 
857                             if(g_bot_cbw.flags & 0x80u)
858                             {
859                                 usbd_msc_stallin_sendstatus();
860                             }
861                             else
862                             {
863                                 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
864                                 usbd_msc_abort_cbw(0u);
865                             }
866                         }
867                     break;
868 
869                     case CB_DATA_DIR_MISMATCH:
870                         g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
871                         usbd_msc_stallin_sendstatus();
872                     break;
873 
874                     case CB_INVALID_CBW:
875                         /*Don't respond till reset recovery*/
876                         g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
877                         usbd_msc_abort_cbw(0u);
878                     break;
879 
880                     default:
881                         /*Don't respond till reset recovery*/
882                         g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
883                         usbd_msc_abort_cbw(0u);                 //Internal Error
884                     break;
885                 }
886             }
887         }
888         else
889         {
890             ASSERT(0);
891         }
892 
893     break;
894         case BOT_DATA_TX:
895             if(BOT_EVENT_TX == g_bottx_events) /* Data TX from Device*/
896             {
897                 if(SCSI_COMMAND_LESSDATAPASS == g_current_command_csw.status)
898                 {
899                     g_xfr_buf_ptr = (uint8_t*)0;
900                     g_xfr_buf_len = 0u;
901                     g_xfr_lba_addr = 0u;
902                     g_current_command_csw.status = SCSI_COMMAND_PASS;
903                     usbd_msc_stallin_sendstatus();
904                 }
905                 else if(SCSI_COMMAND_PASS == g_current_command_csw.status)
906                 {
907                     if(g_current_command_csw.data_residue >= g_xfr_buf_len)
908                     {
909                         g_current_command_csw.data_residue -= g_xfr_buf_len;
910                     }
911                     else
912                     {
913                         ASSERT(0);/*corrupt/invalid data_residue value*/
914                     }
915 
916                     if(0u == g_current_command_csw.data_residue)
917                     {
918                         g_xfr_buf_ptr = (uint8_t*)0;
919                         g_xfr_buf_len = 0u;
920                         g_xfr_lba_addr = 0u;
921                         g_current_command_csw.status = SCSI_COMMAND_PASS;
922                         usbd_msc_send_csw();
923                     }
924                     else
925                     {
926                         /*
927                          Control reaches here because previous App read operation
928                          returned less Data than requested by host.Read rest
929                          of the data now.
930                         */
931                         uint32_t actual_read_len;
932                         uint8_t* buf;
933 
934                         if(0 != g_usbd_msc_media_ops->media_read)
935                         {
936                             g_xfr_lba_addr += g_xfr_buf_len;
937                             actual_read_len = g_usbd_msc_media_ops->media_read(g_bot_cbw.lun,
938                                                                                &buf,
939                                                                                g_xfr_lba_addr,
940                                                                                g_current_command_csw.data_residue);
941                             if (actual_read_len > g_current_command_csw.data_residue)
942                             {
943                                 ASSERT(0);/*App should not read more data than asked for*/
944                             }
945                             else
946                             {
947                                 g_xfr_buf_ptr = buf;
948                                 g_xfr_buf_len = actual_read_len;
949                                 g_current_command_csw.status = SCSI_COMMAND_PASS;
950                                 usbd_msc_send_data(buf, g_xfr_buf_len);
951                             }
952                         }
953                         else
954                         {
955                             g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
956                             usbd_msc_abort_cbw(0u);             //Internal Error
957                         }
958                     }
959                 }
960                 else if(SCSI_COMMAND_FAIL == g_current_command_csw.status)
961                 {
962                     g_xfr_buf_ptr = (uint8_t*)0;
963                     g_xfr_buf_len = 0u;
964                     g_xfr_lba_addr = 0u;
965                     usbd_msc_stallin_sendstatus();
966                 }
967                 else
968                 {
969                     ASSERT(0); //should never come there with Phase Error status
970                 }
971             }
972             else if(BOT_EVENT_TX_ERROR == g_bottx_events)
973             {
974                 /* Stall Error*/
975                 if(status & TX_EP_STALL_ERROR)
976                 {
977                     ASSERT(0); //should never get a stall in this state
978                 }
979             }
980             else
981             {
982                 ASSERT(0);/*corrupt g_bottx_events value*/
983             }
984         break;
985 
986         case BOT_DATA_RX:
987             if(BOT_EVENT_RX == g_botrx_events)
988             {
989                 if(SCSI_COMMAND_LESSDATAPASS == g_current_command_csw.status)
990                 {
991                     g_xfr_buf_ptr = (uint8_t*)0;
992                     g_xfr_buf_len = 0u;
993                     g_xfr_lba_addr = 0u;
994                     g_current_command_csw.status = SCSI_COMMAND_PASS;
995                     usbd_msc_stallin_sendstatus();
996                 }
997                 else if(SCSI_COMMAND_PASS == g_current_command_csw.status)
998                 {
999                     uint8_t result = CB_DATAPHASE_ERROR;
1000 
1001                     if(g_current_command_csw.data_residue >= g_xfr_buf_len)
1002                     {
1003                         g_current_command_csw.data_residue -= g_xfr_buf_len;
1004                     }
1005                     else
1006                     {
1007                         ASSERT(0);/*corrupt/invalid data_residue value*/
1008                     }
1009 
1010                     /*Write the received data on flash*/
1011                     if(rx_count == g_xfr_buf_len)
1012                     {
1013                         result = CB_PASS;
1014                     }
1015                     else
1016                     {
1017                         result = CB_DATAPHASE_ERROR;
1018                     }
1019 
1020                     if(0 != g_usbd_msc_media_ops->media_write_ready)
1021                     {
1022                         g_usbd_msc_media_ops->media_write_ready(g_bot_cbw.lun,
1023                                                                 g_xfr_lba_addr,
1024                                                                 g_xfr_buf_len);
1025                          result = CB_PASS;
1026                     }
1027                     else
1028                     {
1029                          result = CB_DATAPHASE_ERROR;
1030                     }
1031 
1032                     if(CB_PASS == result)
1033                     {
1034                         /*
1035                         data_residue == 0 means we are done with current Data
1036                         phase of OUT transaction, send the status.
1037                         */
1038                         if(0u == g_current_command_csw.data_residue)
1039                         {
1040                             g_xfr_buf_ptr = 0; // Data end.
1041                             g_xfr_buf_len = 0u;
1042                             g_xfr_lba_addr = 0u;
1043                             g_current_command_csw.status = SCSI_COMMAND_PASS;
1044                             usbd_msc_send_csw();
1045                         }
1046                         else
1047                         {
1048                             uint32_t app_write_len;
1049                             uint8_t* write_buf = (uint8_t*) 0;
1050 
1051                             /*
1052                             Data phase of current OUT transaction is still in
1053                             progress.
1054                             Prepare to write more data on flash
1055                             */
1056                             g_xfr_lba_addr += g_xfr_buf_len;
1057 
1058                             if(0 != g_usbd_msc_media_ops->media_acquire_write_buf)
1059                                 write_buf = g_usbd_msc_media_ops->media_acquire_write_buf(g_bot_cbw.lun,
1060                                                                                           g_xfr_lba_addr,
1061                                                                                           &app_write_len);
1062 
1063                             /*
1064                             If application buffer is not big enough to handle all
1065                             requested data from Host,then read amount of data
1066                             that the application can handle at the moment.
1067                             */
1068                             if(app_write_len < g_current_command_csw.data_residue)
1069                             {
1070                                 g_xfr_buf_len = app_write_len;
1071                             }
1072                             else
1073                             {
1074                                 g_xfr_buf_len = g_current_command_csw.data_residue;
1075                             }
1076 
1077                             g_xfr_buf_ptr = write_buf;
1078                             g_current_command_csw.status = SCSI_COMMAND_PASS;
1079                             usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
1080                         }
1081                     }
1082                     else
1083                     {
1084                         g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
1085                         usbd_msc_abort_cbw(0u);                //Internal Error
1086                     }
1087                 }
1088                 else if(SCSI_COMMAND_FAIL == g_current_command_csw.status)
1089                 {
1090                     g_xfr_buf_ptr = 0;
1091                     g_xfr_buf_len = 0u;
1092                     g_xfr_lba_addr = 0u;
1093                     usbd_msc_send_csw();
1094                 }
1095             }
1096             else if(BOT_EVENT_RX_ERROR == g_botrx_events)
1097             {
1098                 /* Stall Error*/
1099                 if(status & 0x02u)
1100                 {
1101                     ASSERT(0); //should never get a stall in this state
1102                 }
1103             }
1104             else
1105             {
1106                 ASSERT(0); //invalid g_botrx_events
1107             }
1108         break;
1109 
1110         case BOT_SEND_STATUS:
1111 
1112             if(BOT_EVENT_TX == g_bottx_events)
1113             {
1114                 G_BOT_CBW_INIT();
1115                 g_current_command_csw.data_residue = 0u;
1116                 g_current_command_csw.tag = 0u;
1117                 g_current_command_csw.status = SCSI_COMMAND_FAIL;
1118                 g_xfr_buf_ptr = (uint8_t*)0;
1119                 g_xfr_buf_len = 0u;
1120                 g_xfr_lba_addr = 0u;
1121 
1122                 g_bot_state = BOT_IDLE;
1123                 /*Prepare to receive next command*/
1124                 MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
1125                                             (uint8_t*)&g_bot_cbw,
1126                                             USBD_MSC_BOT_CBW_LENGTH);
1127             }
1128             else if(BOT_EVENT_TX_ERROR == g_bottx_events)
1129             {
1130                 /* Stall Error*/
1131                 if(status & TX_EP_STALL_ERROR)
1132                 {
1133                     if(g_current_command_csw.status == SCSI_COMMAND_LESSDATAPASS)
1134                     {
1135                         g_current_command_csw.status = SCSI_COMMAND_PASS;
1136                     }
1137                     usbd_msc_send_csw();
1138                 }
1139             }
1140         break;
1141 
1142         case BOT_ABORTED:
1143         {
1144             g_bot_state = BOT_ABORTED;
1145             usbd_msc_abort_cbw(0u);
1146         }
1147         break;
1148 
1149         default:
1150         {
1151             ASSERT(0);  //invalid BOT state
1152         }
1153         break;
1154     }
1155 
1156     g_bottx_events = BOT_EVENT_IDLE;
1157     g_botrx_events = BOT_EVENT_IDLE;
1158 }
1159 
1160 /***************************************************************************//**
1161  usbd_msc_process_cbw() function decodes current command sent by host in CBW,
1162  and Processes the command. If the command was valid and meaningful, it asks for
1163  required information from application and returns the status. If the Command
1164  was invalid or is not processed by this driver, it returns the Failure status.
1165  */
1166 
1167 
1168 static uint8_t
usbd_msc_process_cbw(mss_usb_msc_cbw_t * cbw)1169 usbd_msc_process_cbw
1170 (
1171     mss_usb_msc_cbw_t * cbw
1172 )
1173 {
1174     uint8_t cbw_command = cbw->cmd_block[0];
1175     uint8_t result = CB_PASS;
1176     g_current_command_csw.tag = cbw->tag;
1177 
1178     /*
1179      Check for valid cbw
1180      1) CBW received after csw or reset
1181      2) cbw is 32 bytes
1182      3) Signature is correct
1183 
1184      CBW is meaningful if all reserved bytes are zero
1185      Lun value is supported
1186      CBWCBLength and cbwcb are valid for the interface subclass.
1187      No. Max LUN index provided by App in get_max_lun request.
1188      */
1189 
1190     if((cbw->signature != USB_MSC_BOT_CBW_SIGNATURE) ||
1191        (cbw->lun > get_max_lun_response[0]) ||
1192        (cbw->cmd_length < 1) ||
1193        (cbw->cmd_length > 16))
1194     {
1195         result = CB_INVALID_CBW;
1196     }
1197     else
1198     {
1199         if(g_current_command_csw.data_residue != 0u)
1200         {
1201             ASSERT(0);
1202         }
1203 
1204 
1205         switch(cbw_command)
1206         {
1207             case USB_MSC_SCSI_INQUIRY:
1208                 result = usbd_msc_process_inquiry();
1209             break;
1210 
1211             case USB_MSC_SCSI_READ_CAPACITY_10:/*returns last LBA and block size*/
1212                 result = usbd_msc_process_read_capacity_10();
1213             break;
1214 
1215             case USB_MSC_SCSI_READ_FORMAT_CAPACITIES:/*Returns no. of blocks and block size*/
1216             {
1217                 uint32_t no_of_blocks, block_size;
1218                 uint32_t dev_data_len = 0;
1219 
1220                 dev_data_len = ((g_bot_cbw.cmd_block[7u] << 8u) | g_bot_cbw.cmd_block[8u]);
1221 
1222                 if(0 != g_usbd_msc_media_ops->media_get_capacity)
1223                 {
1224                     g_usbd_msc_media_ops->media_get_capacity(cbw->lun,
1225                                                            (uint32_t*)&no_of_blocks,
1226                                                            (uint32_t*)&block_size);
1227                 }
1228 
1229                 format_capacity_list [4u] = (uint8_t)(no_of_blocks >> 24u);
1230                 format_capacity_list [5u] = (uint8_t)(no_of_blocks >> 16u);
1231                 format_capacity_list [6u] = (uint8_t)(no_of_blocks >> 8u);
1232                 format_capacity_list [7u] = (uint8_t)(no_of_blocks);
1233 
1234                 /* format_capacity_list [8] = Descriptor Code*/
1235                 format_capacity_list [9u]  = (uint8_t)(block_size >> 16u);
1236                 format_capacity_list [10u] = (uint8_t)(block_size >> 8u);
1237                 format_capacity_list [11u] = (uint8_t)(block_size);
1238 
1239                 g_req_type = SCSI_IN;
1240                 g_xfr_buf_ptr = (uint8_t*)format_capacity_list;
1241                 g_xfr_buf_len = sizeof(format_capacity_list);
1242 
1243                 usbd_msc_prepare_sense_data(cbw->lun,
1244                                             SC_ILLEGAL_REQUEST,
1245                                             ASC_INVALID_CDB);
1246 
1247                 if(g_xfr_buf_len < dev_data_len)
1248                 {
1249                     result = CB_LESSDATA;
1250                 }
1251                 else if(g_xfr_buf_len > dev_data_len)
1252                 {
1253                     result = CB_LESSDATA;
1254                 }
1255                 else
1256                 {
1257                     result = CB_PASS;
1258                 }
1259             }
1260             break;
1261 
1262             case USB_MSC_SCSI_READ_10:
1263                   result = usbd_msc_process_read_10();
1264               break;
1265 
1266             case USB_MSC_SCSI_MODE_SENSE_6:
1267             {
1268                 uint32_t dev_data_len =0;
1269                 dev_data_len = g_bot_cbw.cmd_block[4u];
1270 
1271                 g_req_type = SCSI_IN;
1272                 g_xfr_buf_ptr = mode_sense_response;
1273                 g_xfr_buf_len = sizeof(mode_sense_response);
1274 
1275                 if(dev_data_len > g_xfr_buf_len)
1276                 {
1277                     result = CB_LESSDATA;
1278                 }
1279                 else if(dev_data_len < g_xfr_buf_len)
1280                 {
1281                     result = CB_MOREDATA;
1282                 }
1283                 else
1284                 {
1285                     result = CB_PASS;
1286                 }
1287             }
1288             break;
1289 
1290             case USB_MSC_SCSI_REQUEST_SENSE:
1291             {
1292                 uint32_t dev_data_len =0;
1293                 dev_data_len = g_bot_cbw.cmd_block[4u];
1294 
1295                 if(g_bot_cbw.cmd_block[1u] & 0x01u)//DESC bit 0 - only fixed format is supported
1296                 {
1297                     return(CB_INVALID_CDB_FIELD);
1298                 }
1299 
1300                 /*SPC-4, table 39*/
1301                 g_req_type = SCSI_IN;
1302                 g_xfr_buf_ptr = (uint8_t*)&g_sense_response;
1303 
1304                 if(0 == dev_data_len)
1305                 {
1306                     result = CB_LESSDATA;
1307                     g_xfr_buf_len = dev_data_len;
1308                 }
1309                 else if(dev_data_len > (sizeof(g_sense_response)))
1310                 {
1311                     g_xfr_buf_len = dev_data_len;
1312                     result = CB_MOREDATA;
1313                 }
1314                 else
1315                 {
1316                     g_xfr_buf_len = dev_data_len;
1317                     result = CB_PASS;
1318                 }
1319             }
1320             break;
1321 
1322             case USB_MSC_SCSI_WRITE_10:
1323                 result = usbd_msc_process_write_10();
1324             break;
1325 
1326             case USB_MSC_SCSI_TEST_UNIT_READY:
1327                 g_req_type = SCSI_ZDR;
1328                 g_xfr_buf_ptr = (uint8_t*)0;
1329                 g_xfr_buf_len = 0u;
1330 
1331                 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1332                 if(0 != g_bot_cbw.xfr_length)
1333                 {
1334                     result = CB_LENGTH_MISMATCH;
1335                 }
1336                 else
1337                 {
1338                     result = CB_PASS;
1339                 }
1340 
1341             break;
1342             case USB_MSC_SCSI_VERIFY_10:
1343                 g_req_type = SCSI_ZDR;
1344                 g_xfr_buf_ptr = (uint8_t*)0;
1345                 g_xfr_buf_len = 0u;
1346 
1347                 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1348                 if(0 != g_bot_cbw.xfr_length)
1349                 {
1350                     result = CB_LENGTH_MISMATCH;
1351                 }
1352                 else
1353                 {
1354                     result = CB_PASS;
1355                 }
1356 
1357             break;
1358 
1359             default:
1360                 result = CB_NOT_SUPPORTED;
1361                 g_req_type = SCSI_IN;
1362                 g_xfr_buf_ptr = (uint8_t*)0;
1363                 g_xfr_buf_len = 0u;
1364                 usbd_msc_prepare_sense_data(cbw->lun,
1365                                             SC_ILLEGAL_REQUEST,
1366                                             ASC_INVALID_FIELED_IN_COMMAND);
1367             break;
1368         }
1369     }
1370     return result;
1371 }
1372 
1373 /***************************************************************************//**
1374  usbd_msc_prepare_sense_data() function prepares sense information required
1375  by the host in case there was an error in processing CBW. This information is
1376  sent as response to REQUEST_SENSE command.
1377  */
1378 static void
usbd_msc_prepare_sense_data(uint8_t lun,uint8_t skey,uint8_t asc)1379 usbd_msc_prepare_sense_data
1380 (
1381     uint8_t lun,
1382     uint8_t skey,
1383     uint8_t asc
1384 )
1385 {
1386     g_sense_response.sense_key = skey;
1387     g_sense_response.asc = asc;
1388 }
1389 
1390 /***************************************************************************//**
1391  usbd_msc_abort_cbw() function aborts the current command CBW.and prepares
1392  the driver to receive new CBW from HOST.
1393  */
1394 static void
usbd_msc_abort_cbw(uint8_t lun)1395 usbd_msc_abort_cbw
1396 (
1397     uint8_t lun
1398 )
1399 {
1400     g_bot_state = BOT_ABORTED;
1401 
1402     /*
1403     Don't respond to anything from host on Bulk IN or OUT Endpoint.
1404     Reset Recovery request is mandatory now.
1405     */
1406 
1407     MSS_USBD_tx_ep_stall(MSC_CLASS_BULK_TX_EP);
1408     MSS_USBD_rx_ep_stall(MSC_CLASS_BULK_RX_EP);
1409 }
1410 
1411 /***************************************************************************//**
1412  usbd_msc_send_data() function send data to the host (DATA phase of IN transactions)
1413  in response to current CBW command.
1414  */
1415 static void
usbd_msc_send_data(uint8_t * buf,uint32_t len)1416 usbd_msc_send_data
1417 (
1418     uint8_t* buf,
1419     uint32_t len
1420 )
1421 {
1422     /*TODO: check if the length can be accommodated in EP buffer*/
1423     g_bot_state = BOT_DATA_TX;
1424     MSS_USBD_tx_ep_write(MSC_CLASS_BULK_TX_EP, buf, len);
1425 }
1426 
1427 static void
usbd_msc_stallin_sendstatus(void)1428 usbd_msc_stallin_sendstatus
1429 (
1430     void
1431 )
1432 {
1433     g_bot_state = BOT_SEND_STATUS;
1434     MSS_USBD_tx_ep_stall(MSC_CLASS_BULK_TX_EP);
1435 }
1436 
1437 static void
usbd_msc_stallout_sendstatus(void)1438 usbd_msc_stallout_sendstatus
1439 (
1440     void
1441 )
1442 {
1443     g_bot_state = BOT_SEND_STATUS;
1444     MSS_USBD_rx_ep_stall(MSC_CLASS_BULK_RX_EP);
1445 }
1446 
1447 /***************************************************************************//**
1448  usbd_msc_receive_data() function prepares the driver to receive data
1449  from USB host (DATA phase of OUT transactions) in response to the current CBW
1450  command.
1451  */
1452 static void
usbd_msc_receive_data(uint8_t * buf,uint32_t len)1453 usbd_msc_receive_data
1454 (
1455     uint8_t* buf,
1456     uint32_t len
1457 )
1458 {
1459     g_bot_state = BOT_DATA_RX;
1460     MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP, g_xfr_buf_ptr, len);
1461 }
1462 
1463 /***************************************************************************//**
1464  usbd_msc_send_csw() function sends status information to USB host
1465  (DATA phase of IN transactions), indicating the Success/Failure status of the
1466  current CBW command.
1467  */
1468 static void
usbd_msc_send_csw(void)1469 usbd_msc_send_csw
1470 (
1471     void
1472 )
1473 {
1474     g_bot_state = BOT_SEND_STATUS;
1475     MSS_USBD_tx_ep_write(MSC_CLASS_BULK_TX_EP,
1476                          (uint8_t*)&g_current_command_csw,
1477                          USBD_MSC_BOT_CSW_LENGTH);
1478 }
1479 
1480 /***************************************************************************//**
1481  usbd_msc_process_read_10() function processes read command and calls application
1482  call-back function to read data from media.
1483  */
1484 static uint8_t
usbd_msc_process_read_10(void)1485 usbd_msc_process_read_10
1486 (
1487     void
1488 )
1489 {
1490     uint32_t app_read_len = 0u;
1491     uint32_t lba = 0u;
1492     uint32_t lba_addr = 0u;
1493     uint8_t* buf = 0;
1494     uint32_t dev_data_len = 0u;
1495     uint8_t cb_res = CB_PASS;
1496 
1497     g_req_type = SCSI_IN;
1498     /*Lba address is in command block byte 2 to 4 with MSB first.*/
1499     lba =  (g_bot_cbw.cmd_block[2u] << 24u) |
1500            (g_bot_cbw.cmd_block[3u] << 16u) |
1501            (g_bot_cbw.cmd_block[4u] << 8u) |
1502             g_bot_cbw.cmd_block[5u];
1503 
1504     /*Block size was received in USB_MSC_SCSI_READ_CAPACITY_10 command*/
1505     lba_addr = (lba * lun_capacity[g_bot_cbw.lun].blk_sz_len);
1506 
1507     /*
1508     Number of LBAs to be read is provided in command block byte 7 to 8,
1509     calculate the total size to be read
1510     */
1511     dev_data_len = ((g_bot_cbw.cmd_block[7u] << 8u) | g_bot_cbw.cmd_block[8u]) *
1512                                             lun_capacity[g_bot_cbw.lun].blk_sz_len;
1513 
1514     /*Data Direction must be D2H (IN)*/
1515     if(!(g_bot_cbw.flags & 0x80u))
1516     {
1517         g_xfr_buf_len = dev_data_len;
1518         cb_res = CB_DATA_DIR_MISMATCH;
1519     }
1520     /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1521     if(dev_data_len != g_bot_cbw.xfr_length)
1522     {
1523         cb_res = CB_LENGTH_MISMATCH;
1524     }
1525 
1526     if(0 == g_usbd_msc_media_ops->media_read)
1527     {
1528         cb_res = CB_INTERNAL_ERROR;
1529     }
1530 
1531     if(CB_PASS == cb_res)
1532     {
1533         if(0 != g_usbd_msc_media_ops->media_read)
1534         {
1535             app_read_len = g_usbd_msc_media_ops->media_read(g_bot_cbw.lun,
1536                                                             &buf,
1537                                                             lba_addr,
1538                                                             dev_data_len);
1539         }
1540 
1541         if((uint8_t*)0 == buf)
1542         {
1543             cb_res = CB_INTERNAL_ERROR;
1544         }
1545         else
1546         {
1547             cb_res = CB_PASS;
1548             g_xfr_buf_ptr = buf;
1549 
1550             if(app_read_len < dev_data_len)
1551             {
1552                 g_xfr_buf_len = app_read_len;
1553             }
1554             else
1555             {
1556                 g_xfr_buf_len = dev_data_len;
1557             }
1558             /*
1559             Store the current LBA address so that it will be used to calculate
1560             new LBA  address when remaining data is read from flash.
1561             */
1562             g_xfr_lba_addr = lba_addr;
1563         }
1564     }
1565 
1566     if(CB_PASS != cb_res)
1567     {
1568         g_xfr_buf_ptr = (uint8_t*)0;
1569         g_xfr_buf_len = 0u;
1570         g_xfr_lba_addr = 0u;
1571     }
1572 
1573     return (cb_res);
1574 }
1575 
1576 /***************************************************************************//**
1577  usbd_msc_process_write_10() function processes Write command and calls application
1578  call-back function to acquire a buffer where the data will be receive.
1579  */
1580 static uint8_t
usbd_msc_process_write_10(void)1581 usbd_msc_process_write_10
1582 (
1583     void
1584 )
1585 {
1586     uint32_t lba = 0u;
1587     uint32_t lba_addr = 0u;
1588     uint8_t* write_buf;
1589     uint32_t app_write_len = 0u;
1590     uint32_t dev_data_len = 0u;
1591     uint8_t cb_res = CB_PASS;
1592 
1593     g_req_type = SCSI_OUT;
1594     g_xfr_buf_ptr = (uint8_t*)0;
1595     g_xfr_buf_len = 0u;
1596     g_xfr_lba_addr = 0u;
1597 
1598     /*Lba address is in command block byte 2 to 4 with MSB first.*/
1599     lba = (g_bot_cbw.cmd_block[2u] << 24u) |
1600           (g_bot_cbw.cmd_block[3u] << 16u) |
1601           (g_bot_cbw.cmd_block[4u] << 8u) |
1602            g_bot_cbw.cmd_block[5u];
1603 
1604     /*Block size was received in USB_MSC_SCSI_READ_CAPACITY_10 command*/
1605     lba_addr = (lba * lun_capacity[g_bot_cbw.lun].blk_sz_len);
1606 
1607     /*
1608     Number of LBA to be written is provided in command block byte 7 to 8,
1609     calculate the total size to be written
1610     */
1611     dev_data_len = ((g_bot_cbw.cmd_block[7] << 8u) | g_bot_cbw.cmd_block[8u]) *
1612                                          lun_capacity[g_bot_cbw.lun].blk_sz_len;
1613 
1614     /*Data Direction must be H2D (OUT)*/
1615     if(g_bot_cbw.flags & 0x80u)
1616     {
1617         g_xfr_buf_len = dev_data_len;
1618         cb_res = CB_DATA_DIR_MISMATCH;
1619     }
1620     /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1621     if(dev_data_len != g_bot_cbw.xfr_length)
1622     {
1623         cb_res = CB_LENGTH_MISMATCH;
1624     }
1625 
1626     if(0 == g_usbd_msc_media_ops->media_acquire_write_buf)
1627     {
1628         cb_res = CB_INTERNAL_ERROR;
1629     }
1630 
1631     if(CB_PASS == cb_res)
1632     {
1633         write_buf = g_usbd_msc_media_ops->media_acquire_write_buf(g_bot_cbw.lun,
1634                                                                   lba_addr,
1635                                                                   &app_write_len);
1636         if(write_buf == (uint8_t*)0)
1637         {
1638             cb_res = CB_INTERNAL_ERROR;
1639         }
1640         else
1641         {
1642             cb_res = CB_PASS;
1643             /*
1644             Since App is not capable of handling all data at the moment.
1645             Store the current LBA address so that it will be used to calculate
1646             new LBA address when remaining data is received.
1647             */
1648             g_xfr_lba_addr = lba_addr;
1649             g_xfr_buf_ptr = write_buf;
1650             /*
1651             If application buffer is not big enough to handle all requested data
1652             from Host, then read the amount of data that the application can
1653             handle at the moment
1654             */
1655             if(app_write_len < dev_data_len)
1656             {
1657                 g_xfr_buf_len = app_write_len;
1658             }
1659             else
1660             {
1661                 g_xfr_buf_len = dev_data_len;
1662             }
1663         }
1664     }
1665 
1666     if(CB_PASS != cb_res)
1667     {
1668         g_xfr_buf_ptr = (uint8_t*)0;
1669         g_xfr_buf_len = 0u;
1670         g_xfr_lba_addr = 0u;
1671     }
1672 
1673     return (cb_res);
1674 }
1675 
usbd_msc_process_inquiry(void)1676 static uint8_t usbd_msc_process_inquiry(void)
1677 {
1678     uint32_t dev_data_len = 0u;
1679     uint8_t* buf = (uint8_t*)0;
1680     uint32_t app_data_len;
1681 
1682     g_req_type = SCSI_IN;
1683     g_xfr_buf_ptr = (uint8_t*)0;
1684     g_xfr_buf_len = 0u;
1685 
1686     dev_data_len = ((g_bot_cbw.cmd_block[3u] << 8u) | g_bot_cbw.cmd_block[4u]);
1687 
1688     /*Data Direction must be D2H (IN)*/
1689     if(!(g_bot_cbw.flags & 0x80u))
1690     {
1691         g_xfr_buf_len = dev_data_len;
1692         return(CB_DATA_DIR_MISMATCH);
1693     }
1694 
1695     /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1696     if(dev_data_len != g_bot_cbw.xfr_length)
1697     {
1698         return(CB_LENGTH_MISMATCH);
1699     }
1700 
1701     /*If EVPD is zero then Page code must be zero*/
1702     if((!(g_bot_cbw.cmd_block[1u] & 0x01u)) && (g_bot_cbw.cmd_block[1u]))
1703     {
1704         return(CB_INVALID_CDB_FIELD);
1705     }
1706 
1707     if(0 == g_usbd_msc_media_ops->media_inquiry)
1708     {
1709         return(CB_INTERNAL_ERROR);
1710     }
1711 
1712     if(0 != g_usbd_msc_media_ops->media_inquiry)
1713     {
1714         buf = g_usbd_msc_media_ops->media_inquiry(g_bot_cbw.lun, &app_data_len);
1715     }
1716 
1717     if((uint8_t*)0 == buf)
1718     {
1719         return(CB_INTERNAL_ERROR);
1720     }
1721     else
1722     {
1723         g_xfr_buf_ptr = buf;
1724 
1725         if(dev_data_len <= app_data_len)
1726         {
1727             g_xfr_buf_len = dev_data_len;
1728             return(CB_PASS);
1729         }
1730         else
1731         {
1732             g_xfr_buf_len = app_data_len;
1733             return(CB_LESSDATA);
1734         }
1735     }
1736 }
1737 
usbd_msc_process_read_capacity_10(void)1738 static uint8_t usbd_msc_process_read_capacity_10(void)
1739 {
1740     uint32_t no_of_blocks, block_size;
1741 
1742     /*
1743      Returns last block address and block size
1744      Last_blk_lba = no_of_blocks-1
1745     */
1746     g_xfr_buf_ptr = (uint8_t*)0;
1747     g_xfr_buf_len = 0u;
1748     g_req_type = SCSI_IN;
1749 
1750     /*Data Direction must be D2H (IN)*/
1751     if(!(g_bot_cbw.flags & 0x80u))
1752     {
1753         g_xfr_buf_len = 8u;
1754         return(CB_DATA_DIR_MISMATCH);
1755     }
1756 
1757     /*PMI bit set to one is not supported*/
1758     if(g_bot_cbw.cmd_block[8u] & 0x01u)
1759     {
1760         return(CB_INVALID_CDB_FIELD);
1761     }
1762 
1763     if(0 == g_usbd_msc_media_ops->media_get_capacity)
1764     {
1765         return(CB_INTERNAL_ERROR);
1766     }
1767 
1768     if(0 != g_usbd_msc_media_ops->media_get_capacity)
1769     {
1770         g_usbd_msc_media_ops->media_get_capacity(g_bot_cbw.lun,
1771                                                  (uint32_t*)&no_of_blocks,
1772                                                  (uint32_t*)&block_size);
1773     }
1774 
1775     lun_capacity[g_bot_cbw.lun].last_lba_msb = (uint8_t)((no_of_blocks - 1u) >> 24u);
1776     lun_capacity[g_bot_cbw.lun].last_lba_2 = (uint8_t)((no_of_blocks - 1u) >> 16u);
1777     lun_capacity[g_bot_cbw.lun].last_lba_1 = (uint8_t)((no_of_blocks - 1u) >> 8u);
1778     lun_capacity[g_bot_cbw.lun].last_lba_lsb = (uint8_t)((no_of_blocks - 1u));
1779 
1780     lun_capacity[g_bot_cbw.lun].blk_sz_len = block_size;
1781     lun_capacity[g_bot_cbw.lun].block_size_msb = (uint8_t)(block_size >> 24u);
1782     lun_capacity[g_bot_cbw.lun].block_size_2 = (uint8_t)(block_size >> 16u);
1783     lun_capacity[g_bot_cbw.lun].block_size_1 = (uint8_t)(block_size >> 8u);
1784     lun_capacity[g_bot_cbw.lun].block_size_lsb = (uint8_t)(block_size);
1785 
1786     g_xfr_buf_ptr = (uint8_t*)&lun_capacity[g_bot_cbw.lun];
1787     g_xfr_buf_len = 8u;
1788 
1789     return(CB_PASS);
1790 }
1791 
1792 #endif //MSS_USB_DEVICE_ENABLED
1793 
1794 #ifdef __cplusplus
1795 }
1796 #endif
1797