2 ******************************************************************************
4 * @author MCD Application Team
5 * @brief This file provides all the MSC core functions.
9 * ===================================================================
10 * MSC Class Description
11 * ===================================================================
12 * This module manages the MSC class V1.0 following the "Universal
13 * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
15 * This driver implements the following aspects of the specification:
16 * - Bulk-Only Transport protocol
17 * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
21 ******************************************************************************
24 * <h2><center>© Copyright (c) 2015 STMicroelectronics.
25 * All rights reserved.</center></h2>
27 * This software component is licensed by ST under Ultimate Liberty license
28 * SLA0044, the "License"; You may not use this file except in compliance with
29 * the License. You may obtain a copy of the License at:
30 * http://www.st.com/SLA0044
32 ******************************************************************************
36 - "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
37 - "stm32xxxxx_{eval}{discovery}_io.c"
38 - "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c"
41 /* Includes ------------------------------------------------------------------*/
45 /** @addtogroup STM32_USB_DEVICE_LIBRARY
50 /** @defgroup MSC_CORE
51 * @brief Mass storage core module
55 /** @defgroup MSC_CORE_Private_TypesDefinitions
63 /** @defgroup MSC_CORE_Private_Defines
72 /** @defgroup MSC_CORE_Private_Macros
80 /** @defgroup MSC_CORE_Private_FunctionPrototypes
83 uint8_t USBD_MSC_Init (USBD_HandleTypeDef
*pdev
,
86 uint8_t USBD_MSC_DeInit (USBD_HandleTypeDef
*pdev
,
89 uint8_t USBD_MSC_Setup (USBD_HandleTypeDef
*pdev
,
90 USBD_SetupReqTypedef
*req
);
92 uint8_t USBD_MSC_DataIn (USBD_HandleTypeDef
*pdev
,
96 uint8_t USBD_MSC_DataOut (USBD_HandleTypeDef
*pdev
,
99 uint8_t *USBD_MSC_GetHSCfgDesc (uint16_t *length
);
101 uint8_t *USBD_MSC_GetFSCfgDesc (uint16_t *length
);
103 uint8_t *USBD_MSC_GetOtherSpeedCfgDesc (uint16_t *length
);
105 uint8_t *USBD_MSC_GetDeviceQualifierDescriptor (uint16_t *length
);
113 /** @defgroup MSC_CORE_Private_Variables
118 USBD_ClassTypeDef USBD_MSC
=
124 NULL
, /*EP0_RxReady*/
130 USBD_MSC_GetHSCfgDesc
,
131 USBD_MSC_GetFSCfgDesc
,
132 USBD_MSC_GetOtherSpeedCfgDesc
,
133 USBD_MSC_GetDeviceQualifierDescriptor
,
136 /* USB Mass storage device Configuration Descriptor */
137 /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
138 __ALIGN_BEGIN
uint8_t USBD_MSC_CfgHSDesc
[USB_MSC_CONFIG_DESC_SIZ
] __ALIGN_END
=
141 0x09, /* bLength: Configuation Descriptor size */
142 USB_DESC_TYPE_CONFIGURATION
, /* bDescriptorType: Configuration */
143 USB_MSC_CONFIG_DESC_SIZ
,
146 0x01, /* bNumInterfaces: 1 interface */
147 0x01, /* bConfigurationValue: */
148 0x04, /* iConfiguration: */
149 0xC0, /* bmAttributes: */
150 0x32, /* MaxPower 100 mA */
152 /******************** Mass Storage interface ********************/
153 0x09, /* bLength: Interface Descriptor size */
154 0x04, /* bDescriptorType: */
155 0x00, /* bInterfaceNumber: Number of Interface */
156 0x00, /* bAlternateSetting: Alternate setting */
157 0x02, /* bNumEndpoints*/
158 0x08, /* bInterfaceClass: MSC Class */
159 0x06, /* bInterfaceSubClass : SCSI transparent*/
160 0x50, /* nInterfaceProtocol */
161 0x05, /* iInterface: */
162 /******************** Mass Storage Endpoints ********************/
163 0x07, /*Endpoint descriptor length = 7*/
164 0x05, /*Endpoint descriptor type */
165 MSC_EPIN_ADDR
, /*Endpoint address (IN, address 1) */
166 0x02, /*Bulk endpoint type */
167 LOBYTE(MSC_MAX_HS_PACKET
),
168 HIBYTE(MSC_MAX_HS_PACKET
),
169 0x00, /*Polling interval in milliseconds */
171 0x07, /*Endpoint descriptor length = 7 */
172 0x05, /*Endpoint descriptor type */
173 MSC_EPOUT_ADDR
, /*Endpoint address (OUT, address 1) */
174 0x02, /*Bulk endpoint type */
175 LOBYTE(MSC_MAX_HS_PACKET
),
176 HIBYTE(MSC_MAX_HS_PACKET
),
177 0x00 /*Polling interval in milliseconds*/
180 /* USB Mass storage device Configuration Descriptor */
181 /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
182 uint8_t USBD_MSC_CfgFSDesc
[USB_MSC_CONFIG_DESC_SIZ
] __ALIGN_END
=
185 0x09, /* bLength: Configuation Descriptor size */
186 USB_DESC_TYPE_CONFIGURATION
, /* bDescriptorType: Configuration */
187 USB_MSC_CONFIG_DESC_SIZ
,
190 0x01, /* bNumInterfaces: 1 interface */
191 0x01, /* bConfigurationValue: */
192 0x04, /* iConfiguration: */
193 0xC0, /* bmAttributes: */
194 0x32, /* MaxPower 100 mA */
196 /******************** Mass Storage interface ********************/
197 0x09, /* bLength: Interface Descriptor size */
198 0x04, /* bDescriptorType: */
199 0x00, /* bInterfaceNumber: Number of Interface */
200 0x00, /* bAlternateSetting: Alternate setting */
201 0x02, /* bNumEndpoints*/
202 0x08, /* bInterfaceClass: MSC Class */
203 0x06, /* bInterfaceSubClass : SCSI transparent*/
204 0x50, /* nInterfaceProtocol */
205 0x05, /* iInterface: */
206 /******************** Mass Storage Endpoints ********************/
207 0x07, /*Endpoint descriptor length = 7*/
208 0x05, /*Endpoint descriptor type */
209 MSC_EPIN_ADDR
, /*Endpoint address (IN, address 1) */
210 0x02, /*Bulk endpoint type */
211 LOBYTE(MSC_MAX_FS_PACKET
),
212 HIBYTE(MSC_MAX_FS_PACKET
),
213 0x00, /*Polling interval in milliseconds */
215 0x07, /*Endpoint descriptor length = 7 */
216 0x05, /*Endpoint descriptor type */
217 MSC_EPOUT_ADDR
, /*Endpoint address (OUT, address 1) */
218 0x02, /*Bulk endpoint type */
219 LOBYTE(MSC_MAX_FS_PACKET
),
220 HIBYTE(MSC_MAX_FS_PACKET
),
221 0x00 /*Polling interval in milliseconds*/
224 __ALIGN_BEGIN
uint8_t USBD_MSC_OtherSpeedCfgDesc
[USB_MSC_CONFIG_DESC_SIZ
] __ALIGN_END
=
227 0x09, /* bLength: Configuation Descriptor size */
228 USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION
,
229 USB_MSC_CONFIG_DESC_SIZ
,
232 0x01, /* bNumInterfaces: 1 interface */
233 0x01, /* bConfigurationValue: */
234 0x04, /* iConfiguration: */
235 0xC0, /* bmAttributes: */
236 0x32, /* MaxPower 100 mA */
238 /******************** Mass Storage interface ********************/
239 0x09, /* bLength: Interface Descriptor size */
240 0x04, /* bDescriptorType: */
241 0x00, /* bInterfaceNumber: Number of Interface */
242 0x00, /* bAlternateSetting: Alternate setting */
243 0x02, /* bNumEndpoints*/
244 0x08, /* bInterfaceClass: MSC Class */
245 0x06, /* bInterfaceSubClass : SCSI transparent command set*/
246 0x50, /* nInterfaceProtocol */
247 0x05, /* iInterface: */
248 /******************** Mass Storage Endpoints ********************/
249 0x07, /*Endpoint descriptor length = 7*/
250 0x05, /*Endpoint descriptor type */
251 MSC_EPIN_ADDR
, /*Endpoint address (IN, address 1) */
252 0x02, /*Bulk endpoint type */
255 0x00, /*Polling interval in milliseconds */
257 0x07, /*Endpoint descriptor length = 7 */
258 0x05, /*Endpoint descriptor type */
259 MSC_EPOUT_ADDR
, /*Endpoint address (OUT, address 1) */
260 0x02, /*Bulk endpoint type */
263 0x00 /*Polling interval in milliseconds*/
266 /* USB Standard Device Descriptor */
267 __ALIGN_BEGIN
uint8_t USBD_MSC_DeviceQualifierDesc
[USB_LEN_DEV_QUALIFIER_DESC
] __ALIGN_END
=
269 USB_LEN_DEV_QUALIFIER_DESC
,
270 USB_DESC_TYPE_DEVICE_QUALIFIER
,
284 static DMA_DATA_ZERO_INIT USBD_MSC_BOT_HandleTypeDef ClassData
;
286 /** @defgroup MSC_CORE_Private_Functions
291 * @brief USBD_MSC_Init
292 * Initialize the mass storage configuration
293 * @param pdev: device instance
294 * @param cfgidx: configuration index
297 uint8_t USBD_MSC_Init (USBD_HandleTypeDef
*pdev
, uint8_t cfgidx
)
301 pdev
->pMSC_ClassData
= (void *)&ClassData
;
303 if(pdev
->dev_speed
== USBD_SPEED_HIGH
)
306 USBD_LL_OpenEP(pdev
, MSC_EPOUT_ADDR
, USBD_EP_TYPE_BULK
, MSC_MAX_HS_PACKET
);
307 pdev
->ep_out
[MSC_EPOUT_ADDR
& 0xFU
].is_used
= 1U;
310 USBD_LL_OpenEP(pdev
, MSC_EPIN_ADDR
, USBD_EP_TYPE_BULK
, MSC_MAX_HS_PACKET
);
311 pdev
->ep_in
[MSC_EPIN_ADDR
& 0xFU
].is_used
= 1U;
316 USBD_LL_OpenEP(pdev
, MSC_EPOUT_ADDR
, USBD_EP_TYPE_BULK
, MSC_MAX_FS_PACKET
);
317 pdev
->ep_out
[MSC_EPOUT_ADDR
& 0xFU
].is_used
= 1U;
320 USBD_LL_OpenEP(pdev
, MSC_EPIN_ADDR
, USBD_EP_TYPE_BULK
, MSC_MAX_FS_PACKET
);
321 pdev
->ep_in
[MSC_EPIN_ADDR
& 0xFU
].is_used
= 1U;
324 /* Init the BOT layer */
331 * @brief USBD_MSC_DeInit
332 * DeInitilaize the mass storage configuration
333 * @param pdev: device instance
334 * @param cfgidx: configuration index
337 uint8_t USBD_MSC_DeInit (USBD_HandleTypeDef
*pdev
,
343 USBD_LL_CloseEP(pdev
, MSC_EPOUT_ADDR
);
344 pdev
->ep_out
[MSC_EPOUT_ADDR
& 0xFU
].is_used
= 0U;
347 USBD_LL_CloseEP(pdev
, MSC_EPIN_ADDR
);
348 pdev
->ep_in
[MSC_EPIN_ADDR
& 0xFU
].is_used
= 0U;
350 /* De-Init the BOT layer */
351 MSC_BOT_DeInit(pdev
);
353 /* Free MSC Class Resources */
354 if(pdev
->pMSC_ClassData
!= NULL
)
356 USBD_free(pdev
->pMSC_ClassData
);
357 pdev
->pMSC_ClassData
= NULL
;
362 * @brief USBD_MSC_Setup
363 * Handle the MSC specific requests
364 * @param pdev: device instance
365 * @param req: USB request
368 uint8_t USBD_MSC_Setup (USBD_HandleTypeDef
*pdev
, USBD_SetupReqTypedef
*req
)
370 USBD_MSC_BOT_HandleTypeDef
*hmsc
= (USBD_MSC_BOT_HandleTypeDef
*) pdev
->pMSC_ClassData
;
371 uint8_t ret
= USBD_OK
;
372 uint16_t status_info
= 0U;
374 switch (req
->bmRequest
& USB_REQ_TYPE_MASK
)
378 case USB_REQ_TYPE_CLASS
:
379 switch (req
->bRequest
)
381 case BOT_GET_MAX_LUN
:
382 if((req
->wValue
== 0U) && (req
->wLength
== 1U) &&
383 ((req
->bmRequest
& 0x80U
) == 0x80U
))
385 hmsc
->max_lun
= (uint32_t)((USBD_StorageTypeDef
*)pdev
->pMSC_UserData
)->GetMaxLun();
386 USBD_CtlSendData (pdev
, (uint8_t *)(void *)&hmsc
->max_lun
, 1U);
390 USBD_CtlError(pdev
, req
);
396 if((req
->wValue
== 0U) && (req
->wLength
== 0U) &&
397 ((req
->bmRequest
& 0x80U
) != 0x80U
))
403 USBD_CtlError(pdev
, req
);
409 USBD_CtlError(pdev
, req
);
414 /* Interface & Endpoint request */
415 case USB_REQ_TYPE_STANDARD
:
416 switch (req
->bRequest
)
418 case USB_REQ_GET_STATUS
:
419 if (pdev
->dev_state
== USBD_STATE_CONFIGURED
)
421 USBD_CtlSendData (pdev
, (uint8_t *)(void *)&status_info
, 2U);
425 USBD_CtlError (pdev
, req
);
430 case USB_REQ_GET_INTERFACE
:
431 if (pdev
->dev_state
== USBD_STATE_CONFIGURED
)
433 USBD_CtlSendData (pdev
, (uint8_t *)(void *)&hmsc
->interface
, 1U);
437 USBD_CtlError (pdev
, req
);
442 case USB_REQ_SET_INTERFACE
:
443 if (pdev
->dev_state
== USBD_STATE_CONFIGURED
)
445 hmsc
->interface
= (uint8_t)(req
->wValue
);
449 USBD_CtlError (pdev
, req
);
454 case USB_REQ_CLEAR_FEATURE
:
456 /* Flush the FIFO and Clear the stall status */
457 USBD_LL_FlushEP(pdev
, (uint8_t)req
->wIndex
);
459 /* Reactivate the EP */
460 USBD_LL_CloseEP (pdev
, (uint8_t)req
->wIndex
);
461 if((((uint8_t)req
->wIndex
) & 0x80U
) == 0x80U
)
463 pdev
->ep_in
[(uint8_t)req
->wIndex
& 0xFU
].is_used
= 0U;
464 if(pdev
->dev_speed
== USBD_SPEED_HIGH
)
467 USBD_LL_OpenEP(pdev
, MSC_EPIN_ADDR
, USBD_EP_TYPE_BULK
,
473 USBD_LL_OpenEP(pdev
, MSC_EPIN_ADDR
, USBD_EP_TYPE_BULK
,
476 pdev
->ep_in
[MSC_EPIN_ADDR
& 0xFU
].is_used
= 1U;
480 pdev
->ep_out
[(uint8_t)req
->wIndex
& 0xFU
].is_used
= 0U;
481 if(pdev
->dev_speed
== USBD_SPEED_HIGH
)
484 USBD_LL_OpenEP(pdev
, MSC_EPOUT_ADDR
, USBD_EP_TYPE_BULK
,
490 USBD_LL_OpenEP(pdev
, MSC_EPOUT_ADDR
, USBD_EP_TYPE_BULK
,
493 pdev
->ep_out
[MSC_EPOUT_ADDR
& 0xFU
].is_used
= 1U;
496 /* Handle BOT error */
497 MSC_BOT_CplClrFeature(pdev
, (uint8_t)req
->wIndex
);
501 USBD_CtlError (pdev
, req
);
508 USBD_CtlError (pdev
, req
);
517 * @brief USBD_MSC_DataIn
518 * handle data IN Stage
519 * @param pdev: device instance
520 * @param epnum: endpoint index
523 uint8_t USBD_MSC_DataIn (USBD_HandleTypeDef
*pdev
,
526 MSC_BOT_DataIn(pdev
, epnum
);
531 * @brief USBD_MSC_DataOut
532 * handle data OUT Stage
533 * @param pdev: device instance
534 * @param epnum: endpoint index
537 uint8_t USBD_MSC_DataOut (USBD_HandleTypeDef
*pdev
,
540 MSC_BOT_DataOut(pdev
, epnum
);
545 * @brief USBD_MSC_GetHSCfgDesc
546 * return configuration descriptor
547 * @param length : pointer data length
548 * @retval pointer to descriptor buffer
550 uint8_t *USBD_MSC_GetHSCfgDesc (uint16_t *length
)
552 *length
= sizeof (USBD_MSC_CfgHSDesc
);
553 return USBD_MSC_CfgHSDesc
;
557 * @brief USBD_MSC_GetFSCfgDesc
558 * return configuration descriptor
559 * @param length : pointer data length
560 * @retval pointer to descriptor buffer
562 uint8_t *USBD_MSC_GetFSCfgDesc (uint16_t *length
)
564 *length
= sizeof (USBD_MSC_CfgFSDesc
);
565 return USBD_MSC_CfgFSDesc
;
569 * @brief USBD_MSC_GetOtherSpeedCfgDesc
570 * return other speed configuration descriptor
571 * @param length : pointer data length
572 * @retval pointer to descriptor buffer
574 uint8_t *USBD_MSC_GetOtherSpeedCfgDesc (uint16_t *length
)
576 *length
= sizeof (USBD_MSC_OtherSpeedCfgDesc
);
577 return USBD_MSC_OtherSpeedCfgDesc
;
580 * @brief DeviceQualifierDescriptor
581 * return Device Qualifier descriptor
582 * @param length : pointer data length
583 * @retval pointer to descriptor buffer
585 uint8_t *USBD_MSC_GetDeviceQualifierDescriptor (uint16_t *length
)
587 *length
= sizeof (USBD_MSC_DeviceQualifierDesc
);
588 return USBD_MSC_DeviceQualifierDesc
;
592 * @brief USBD_MSC_RegisterStorage
593 * @param fops: storage callback
596 uint8_t USBD_MSC_RegisterStorage (USBD_HandleTypeDef
*pdev
,
597 USBD_StorageTypeDef
*fops
)
601 pdev
->pMSC_UserData
= fops
;
620 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/