diff --git a/CI/utils/gen_wrapper.sh b/CI/utils/gen_wrapper.sh old mode 100755 new mode 100644 diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc.c b/cores/arduino/stm32/usb/cdc/usbd_cdc.c index eb3d681172..f0a4d81cd4 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.c @@ -52,6 +52,7 @@ #ifdef USBCON #ifdef USBD_USE_CDC +#ifndef USBD_USE_CDC_COMPOSITE /* Includes ------------------------------------------------------------------*/ #include "usbd_cdc.h" @@ -190,7 +191,7 @@ __ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = 0x01, /* bNumEndpoints: One endpoints used */ 0x02, /* bInterfaceClass: Communication Interface Class */ 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x00, /* bInterfaceProtocol: No specific protocol */ + 0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ /*Header Functional Descriptor*/ @@ -285,7 +286,7 @@ __ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = 0x01, /* bNumEndpoints: One endpoints used */ 0x02, /* bInterfaceClass: Communication Interface Class */ 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x00, /* bInterfaceProtocol: No specific protocol */ + 0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ /*Header Functional Descriptor*/ @@ -375,7 +376,7 @@ __ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIG 0x01, /* bNumEndpoints: One endpoints used */ 0x02, /* bInterfaceClass: Communication Interface Class */ 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x00, /* bInterfaceProtocol: No specific protocol */ + 0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ /*Header Functional Descriptor*/ @@ -651,9 +652,9 @@ static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) USBD_CDC_ItfTypeDef *ctrl = (USBD_CDC_ItfTypeDef *)pdev->pUserData; if (pdev->pClassData != NULL) { - if ((pdev->ep_in[epnum].total_length > 0U) && ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) { + if ((hcdc->TxLastLength > 0U) && ((hcdc->TxLastLength % hpcd->IN_ep[epnum].maxpacket) == 0U)) { /* Update the packet total length */ - pdev->ep_in[epnum].total_length = 0U; + hcdc->TxLastLength = 0U; /* Send ZLP */ USBD_LL_Transmit(pdev, epnum, NULL, 0U); @@ -835,7 +836,7 @@ uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) hcdc->TxState = 1U; /* Update the packet total length */ - pdev->ep_in[CDC_IN_EP & 0xFU].total_length = hcdc->TxLength; + hcdc->TxLastLength = hcdc->TxLength; /* Transmit next packet */ USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer, @@ -894,6 +895,8 @@ uint8_t USBD_CDC_ClearBuffer(USBD_HandleTypeDef *pdev) } } +#endif /* !USBD_USE_CDC_COMPOSITE */ #endif /* USBD_USE_CDC */ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc.h b/cores/arduino/stm32/usb/cdc/usbd_cdc.h index 1d9bd051e3..d4a9c42d9d 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.h @@ -27,7 +27,7 @@ extern "C" { /* Includes ------------------------------------------------------------------*/ #include "usbd_ioreq.h" -#include "usbd_ep_conf.h" +#include /** @addtogroup STM32_USB_DEVICE_LIBRARY * @{ @@ -38,18 +38,33 @@ extern "C" { * @{ */ + /** @defgroup usbd_cdc_Exported_Defines * @{ */ + +#ifdef USBD_USE_CDC_COMPOSITE +#define CDC_IN_EP 0x82U /* EP2 for data IN */ +#define CDC_OUT_EP 0x02U /* EP2 for data OUT */ +#define CDC_CMD_EP 0x83U /* EP3 for CDC commands */ +#else +#define CDC_IN_EP 0x82U /* EP1 for data IN */ +#define CDC_OUT_EP 0x01U /* EP1 for data OUT */ +#define CDC_CMD_EP 0x83U /* EP2 for CDC commands */ +#endif + #ifndef CDC_HS_BINTERVAL -#define CDC_HS_BINTERVAL 0x10U +#define CDC_HS_BINTERVAL 0x10U #endif /* CDC_HS_BINTERVAL */ #ifndef CDC_FS_BINTERVAL -#define CDC_FS_BINTERVAL 0x10U +#define CDC_FS_BINTERVAL 0x10U #endif /* CDC_FS_BINTERVAL */ -/* CDC Endpoints parameters */ +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ #define USB_CDC_CONFIG_DESC_SIZ 67U #define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE @@ -99,20 +114,23 @@ typedef struct _USBD_CDC_Itf { } USBD_CDC_ItfTypeDef; +#ifndef __IO +#define __IO volatile /*!< \brief Defines 'read / write' permissions */ +#endif -typedef struct { +typedef struct _USBD_CDC_HandleTypeDef { uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32bits alignment */ uint8_t CmdOpCode; uint8_t CmdLength; - uint8_t *RxBuffer; - uint8_t *TxBuffer; + uint8_t *RxBuffer; + uint8_t *TxBuffer; uint32_t RxLength; uint32_t TxLength; + uint32_t TxLastLength; __IO uint32_t TxState; __IO uint32_t RxState; -} -USBD_CDC_HandleTypeDef; +} USBD_CDC_HandleTypeDef; @@ -127,8 +145,8 @@ USBD_CDC_HandleTypeDef; /** @defgroup USBD_CORE_Exported_Variables * @{ */ - -extern USBD_ClassTypeDef USBD_CDC; +struct _Device_cb; // USBD_ClassTypeDef +extern struct _Device_cb USBD_CDC; #define USBD_CDC_CLASS &USBD_CDC /** * @} @@ -170,3 +188,4 @@ uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev); */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index 52011fd76e..026b020a7e 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -19,6 +19,7 @@ #ifdef USBCON #ifdef USBD_USE_CDC +#ifndef USBD_USE_CDC_COMPOSITE /* Includes ------------------------------------------------------------------*/ #include "usbd_desc.h" @@ -335,6 +336,7 @@ bool CDC_resume_receive(void) return false; } +#endif /* !USBD_USE_CDC_COMPOSITE */ #endif /* USBD_USE_CDC */ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.c b/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.c new file mode 100644 index 0000000000..bc994bbf37 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.c @@ -0,0 +1,315 @@ +#ifdef USBD_USE_CDC_COMPOSITE + +#include + +#include "usbd_msc_scsi.h" +#include "usbd_msc_composite.h" +#include "usbd_msc_cdc_composite.h" + +#include "usbd_msc_cdc_composite_bot.h" + +#if defined(STM32F103xE) || defined(STM32F103xG) +#include "stm32f1xx_hal_rcc_ex.h" +#elif defined(STM32F4xx) +#include "stm32f4xx_hal_rcc_ex.h" +#else +#error "ERROR - Only STM32F103xE, STM32F103xG or STM32F4xx CPUs supported" +#endif + +#define TIMEOUT_SD_ACCESS 0xFF // guess - don't know units +#define SD_RETRY_COUNT 3 + +SD_HandleTypeDef hsd; // create SDIO structure + +HAL_SD_CardCSDTypeDef pCSD; // create structure to hold decoded CSD data +HAL_SD_CardCIDTypeDef pCID; // create structure to hold decoded CID data +HAL_SD_CardStatusTypeDef pStatus; // create structure to hold card status data +HAL_SD_CardInfoTypeDef pCardInfo; // create structure to hold card info + +HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD); +HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID); +HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus); +HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode); + +HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo); +HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init); + +HAL_StatusTypeDef SD_SDIO_Init(); + +#define TRANSFER_CLOCK_DIV ((uint8_t)SDIO_INIT_CLK_DIV/40) + +void go_to_transfer_speed() +{ + + SD_InitTypeDef Init; + + /* Default SDIO peripheral configuration for SD card initialization */ + Init.ClockEdge = hsd.Init.ClockEdge; + Init.ClockBypass = hsd.Init.ClockBypass; + Init.ClockPowerSave = hsd.Init.ClockPowerSave; + Init.BusWide = hsd.Init.BusWide; + Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; + Init.ClockDiv = TRANSFER_CLOCK_DIV; + + /* Initialize SDIO peripheral interface with default configuration */ + SDIO_Init(hsd.Instance, Init); +} + +void SD_LowLevel_Init(void) +{ + + uint32_t tempreg; + + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks + __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks + + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = 1; //GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + // #if defined(SDIO_D1_PIN) && defined(SDIO_D2_PIN) && defined(SDIO_D3_PIN) // define D1-D3 only if have a four bit wide SDIO bus + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3 + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = 1; //GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + //#endif + + // Configure PD.02 CMD line + GPIO_InitStruct.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset + RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock + + // Enable the DMA2 Clock + + //Initialize the SDIO (with initial <400Khz Clock) + tempreg = 0; //Reset value + tempreg |= SDIO_CLKCR_CLKEN; //Clock is enabled + tempreg |= (uint32_t)0x76; //Clock Divider. Clock = 48000/(118+2) = 400Khz + //Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable + SDIO->CLKCR = tempreg; + + //Power up the SDIO + SDIO->POWER = 0x03; +} + + +void HAL_SD_MspInit(SD_HandleTypeDef *hsd) // application specific init +{ + UNUSED(hsd); /* Prevent unused argument(s) compilation warning */ + __HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock +} + +#define SD_RETRY_COUNT 3 + +HAL_StatusTypeDef SD_SDIO_Init() +{ + //init SDIO and get SD card info + + uint8_t retryCnt = SD_RETRY_COUNT; + + uint8_t status; + hsd.Instance = SDIO; + hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET + SD_LowLevel_Init(); + + uint8_t retry_Cnt = retryCnt; + for (;;) { + status = HAL_SD_Init(&hsd); // low level init, enable SDIO & populate some HSD fields, init SD card and get CID & CSD registers + if (!status) { + break; + } + if (!--retry_Cnt) { + return false; // return failing status if retries are exhausted + } + } + retry_Cnt = retryCnt; + for (;;) { + if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) { + break; // some cards are only 1 bit wide so a pass here is not required + } + if (!--retry_Cnt) { + break; + } + } + if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode + hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET + SD_LowLevel_Init(); + retry_Cnt = retryCnt; + for (;;) { + status = HAL_SD_Init(&hsd); + if (!status) { + break; + } + if (!--retry_Cnt) { + return false; // return failing status if retries are exhausted + } + } + } + return true; +} + + +#ifndef USBD_OK +#define USBD_OK 0 +#endif + + + +int8_t SD_MSC_Init(uint8_t lun); + +int8_t SD_MSC_GetCapacity(uint8_t lun, + uint32_t *block_num, + uint16_t *block_size); + +int8_t SD_MSC_IsReady(uint8_t lun); + +int8_t SD_MSC_IsWriteProtected(uint8_t lun); + +int8_t SD_MSC_Read(uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len); + +int8_t SD_MSC_Write(uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len); + +int8_t SD_MSC_GetMaxLun(void); + + + + +#define STANDARD_INQUIRY_DATA_LEN 0x24U + + +uint8_t SD_MSC_Inquirydata[] = {/* 36 */ + /* LUN 0 */ + 0x00, + 0x80, + 0x02, + 0x02, + (STANDARD_INQUIRY_DATA_LEN - 5), + 0x00, + 0x00, + 0x00, + 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */ + 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */ + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + '0', '.', '0', '1', /* Version : 4 Bytes */ +}; + + +USBD_StorageTypeDef SdMscDriver = { + SD_MSC_Init, + SD_MSC_GetCapacity, + SD_MSC_IsReady, + SD_MSC_IsWriteProtected, + SD_MSC_Read, + SD_MSC_Write, + SD_MSC_GetMaxLun, + (int8_t *)SD_MSC_Inquirydata +}; + + + +int8_t SD_MSC_Init(uint8_t lun) +{ + (void)lun; // Not used + + SD_SDIO_Init(); + return USBD_OK; +} + + +int8_t SD_MSC_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) +{ + (void)lun; // Not used + + *block_num = hsd.SdCard.BlockNbr; // Card Capacity in blocks + *block_size = hsd.SdCard.BlockSize; // number of bytes in a block + + return USBD_OK; +} + + +int8_t SD_MSC_IsReady(uint8_t lun) +{ + (void)lun; // Not used + if (hsd.State == HAL_SD_STATE_READY) { + return USBD_OK; + } + return USBD_FAIL; +} + +int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) +{ + (void)lun; // Not used + + int8_t status; + uint8_t retryCnt = SD_RETRY_COUNT; + + for (;;) { + status = HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, TIMEOUT_SD_ACCESS); // read 512 byte block(s) with 500mS timeout + status |= HAL_SD_GetCardState(&hsd); // make sure all is OK + if (!status) { + return USBD_OK; // return passing status + } + if (!--retryCnt) { + return USBD_FAIL; // return failing status if retries are exhausted + } + } +} + + +int8_t SD_MSC_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) +{ + (void)lun; // Not used + + + int8_t status; + uint8_t retryCnt = SD_RETRY_COUNT; + + for (;;) { + status = HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, TIMEOUT_SD_ACCESS); // write 512 byte block(s) with 500mS timeout + status |= HAL_SD_GetCardState(&hsd); // make sure all is OK + if (!status) { + return USBD_OK; // return passing status + } + if (!--retryCnt) { + return USBD_FAIL; // return failing status if retries are exhausted + } + } +} + + +int8_t SD_MSC_IsWriteProtected(uint8_t lun) +{ + (void)lun; // Not used + + return USBD_OK; // Never write protected +} + + +int8_t SD_MSC_GetMaxLun(void) +{ + + return 0; // We have just 1 Logic unit number (LUN) which is zero +} + +#endif /* USBD_USE_CDC_COMPOSITE */ + + diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.h b/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.h new file mode 100644 index 0000000000..903c316b52 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/SdMscDriver.h @@ -0,0 +1,13 @@ +#ifndef SDMSCDRIVER_H +#define SDMSCDRIVER_H + +//#include "usbd_msc.h" +#include "usbd_msc_cdc_composite.h" + +bool initSDIOThread(); +void xSDIOThread(void *pvParameters); +void xSDTestThread(void *pvParameters); + +extern USBD_StorageTypeDef SdMscDriver; + +#endif // SDMSCDRIVER_H diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_cdc.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_cdc.h new file mode 100644 index 0000000000..17a532c18e --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_cdc.h @@ -0,0 +1,190 @@ +/** + ****************************************************************************** + * @file usbd_cdc.h + * @author MCD Application Team + * @brief header file for the usbd_cdc.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" +#include + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for usbd_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ + +#ifdef USBD_USE_CDC_COMPOSITE +#define CDC_IN_EP 0x82U /* EP2 for data IN */ +#define CDC_OUT_EP 0x02U /* EP2 for data OUT */ +#define CDC_CMD_EP 0x83U /* EP3 for CDC commands */ +#else +#define CDC_IN_EP 0x82U /* EP1 for data IN */ +#define CDC_OUT_EP 0x01U /* EP1 for data OUT */ +#define CDC_CMD_EP 0x83U /* EP2 for CDC commands */ +#endif + +#ifndef CDC_HS_BINTERVAL +#define CDC_HS_BINTERVAL 0x10U +#endif /* CDC_HS_BINTERVAL */ + +#ifndef CDC_FS_BINTERVAL +#define CDC_FS_BINTERVAL 0x10U +#endif /* CDC_FS_BINTERVAL */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ + +#define USB_CDC_CONFIG_DESC_SIZ 67U +#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE +#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + +#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U +#define CDC_SET_COMM_FEATURE 0x02U +#define CDC_GET_COMM_FEATURE 0x03U +#define CDC_CLEAR_COMM_FEATURE 0x04U +#define CDC_SET_LINE_CODING 0x20U +#define CDC_GET_LINE_CODING 0x21U +#define CDC_SET_CONTROL_LINE_STATE 0x22U +#define CDC_SEND_BREAK 0x23U + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ +typedef struct { + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +} USBD_CDC_LineCodingTypeDef; + +typedef struct _USBD_CDC_Itf { + int8_t (* Init)(void); + int8_t (* DeInit)(void); + int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length); + int8_t (* Receive)(uint8_t *Buf, uint32_t *Len); + int8_t (* Transferred)(void); + +} USBD_CDC_ItfTypeDef; + +#ifndef __IO +#define __IO volatile /*!< \brief Defines 'read / write' permissions */ +#endif + +typedef struct _USBD_CDC_HandleTypeDef { + uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32bits alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + uint32_t TxLastLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} USBD_CDC_HandleTypeDef; + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ +struct _Device_cb; // USBD_ClassTypeDef +extern struct _Device_cb USBD_CDC; +#define USBD_CDC_CLASS &USBD_CDC +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops); + +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length); + +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff); + +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_ClearBuffer(USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_desc_msc_cdc_composite.c b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_desc_msc_cdc_composite.c new file mode 100644 index 0000000000..48c5d5445c --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_desc_msc_cdc_composite.c @@ -0,0 +1,1739 @@ +/** + ****************************************************************************** + * @file usbd_desc.c + * @author MCD Application Team + * @brief This file provides the USBD descriptors and string formatting method. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/** + ****************************************************************************** + * + * The composite MSC CDC USB device is mainly adapted from the GPSlogger + * repository https://github.com/grafalex82/GPSLogger/tree/master/Libs/USB + * + * See the article "CDC + MSC USB Composite Device for STM32 HAL" (URL: + * https://habr.com/en/post/335018/) for the theory behind the MSC CDC + * composite device as implemented in the above repository. + * + * The composite MSC CDC USB device requires a modified USBD_HandleTypeDef + * structure. The MSC and CDC classes require dedicated data structures. + * + ****************************************************************************** + */ + +#if defined(USBCON) && defined(USBD_USE_CDC_COMPOSITE) +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "utils.h" + +#include "usbd_cdc.h" +#include "usbd_ctlreq.h" +#include "usbd_msc_cdc_composite.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#if USBD_VID == 0x2341 +#define USBD_MANUFACTURER_STRING "Arduino LLC" +#elif USBD_VID == 0x2A03 +#define USBD_MANUFACTURER_STRING "Arduino srl" +#elif USBD_VID == 0x0483 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +#define USBD_MANUFACTURER_STRING "Unknown" +#else +#define USBD_MANUFACTURER_STRING USB_MANUFACTURER +#endif + +#define USBD_LANGID_STRING 0x409 /* 1033 US.S English */ + +#define USBD_CDC_PID 0x5740 // 22336 +#define USBD_CDC_PRODUCT_HS_STRING CONCATS(USB_PRODUCT, "MSC & CDC in HS Mode") +#define USBD_CDC_PRODUCT_FS_STRING CONCATS(USB_PRODUCT, "MSC & CDC in FS Mode") +#define USBD_CDC_CONFIGURATION_HS_STRING CONCATS(USB_PRODUCT, "CDC Config") +#define USBD_CDC_INTERFACE_HS_STRING CONCATS(USB_PRODUCT, "CDC Interface") +#define USBD_CDC_CONFIGURATION_FS_STRING CONCATS(USB_PRODUCT, "CDC Config") +#define USBD_CDC_INTERFACE_FS_STRING CONCATS(USB_PRODUCT, "CDC Interface") +#define USBD_MSC_INTERFACE_STRING CONCATS(USB_PRODUCT, "MSC Interface") + + +/** + * Possible values of class + */ + +#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class +#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface +#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface +#define CDC_CLASS_MULTI 0xEF //!< CDC Multi-interface Function + + +//USB CDC Subclass IDs + +#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model +#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model +#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model +#define CDC_SUBCLASS_MCCM 0x04 // Multi-Channel Control Model +#define CDC_SUBCLASS_CCM 0x05 // CAPI Control Model +#define CDC_SUBCLASS_ETH 0x06 // Ethernet Networking Control Model +#define CDC_SUBCLASS_ATM 0x07 // ATM Networking Control Model + +//USB CDC Communication Interface Protocol IDs + +#define CDC_PROTOCOL_V25TER 0x01 // Common AT commands + + +/* Private macro -------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Common function */ +uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +/* Class specific */ +uint8_t *USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t *USBD_Class_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +/* Private variables ---------------------------------------------------------*/ +USBD_DescriptorsTypeDef CDC_Desc = { + USBD_CDC_DeviceDescriptor, + USBD_LangIDStrDescriptor, + USBD_ManufacturerStrDescriptor, + USBD_CDC_ProductStrDescriptor, + USBD_SerialStrDescriptor, + USBD_CDC_ConfigStrDescriptor, + USBD_CDC_InterfaceStrDescriptor, +}; + + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_CDC_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { + 0x12, /* bLength */ + USB_DESC_TYPE_DEVICE, /* bDescriptorType */ + 0x00, /* bcdUSB (USB version, minor)*/ + 0x02, /* bcdUSB (USB version, major)*/ + CDC_CLASS_MULTI, /* bDeviceClass (MULTI 0xEF) */ + CDC_SUBCLASS_ACM, /* bDeviceSubClass */ + CDC_PROTOCOL_V25TER, /* bDeviceProtocol */ + USB_MAX_EP0_SIZE, /* bMaxPacketSize */ + LOBYTE(USBD_VID), /* idVendor */ + HIBYTE(USBD_VID), /* idVendor */ + LOBYTE(USBD_CDC_PID), /* idVendor */ + HIBYTE(USBD_CDC_PID), /* idVendor */ + 0x00, /* bcdDevice rel. 2.00 */ + 0x02, + USBD_IDX_MFC_STR, /* Index of manufacturer string */ + USBD_IDX_PRODUCT_STR, /* Index of product string */ + USBD_IDX_SERIAL_STR, /* Index of serial number string */ + USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */ +}; /* USB_DeviceDescriptor */ + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; + +uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] = { + USB_SIZ_STRING_SERIAL, + USB_DESC_TYPE_STRING, +}; + +__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +/* Private functions ---------------------------------------------------------*/ +static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len); +static void Get_SerialNum(void); + +/** + * @brief Returns the device descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + UNUSED(speed); + *length = sizeof(USBD_CDC_DeviceDesc); + return (uint8_t *)USBD_CDC_DeviceDesc; +} + +/** + * @brief Returns the LangID string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + UNUSED(speed); + *length = sizeof(USBD_LangIDDesc); + return (uint8_t *)USBD_LangIDDesc; +} + +/** + * @brief Returns the product string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if (speed == USBD_SPEED_HIGH) { + USBD_GetString((uint8_t *)USBD_CDC_PRODUCT_HS_STRING, USBD_StrDesc, length); + } else { + USBD_GetString((uint8_t *)USBD_CDC_PRODUCT_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the manufacturer string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + UNUSED(speed); + USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** + * @brief Returns the serial number string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + UNUSED(speed); + *length = USB_SIZ_STRING_SERIAL; + + /* Update the serial number string descriptor with the data from the unique ID*/ + Get_SerialNum(); + + return (uint8_t *)USBD_StringSerial; +} + +/** + * @brief Returns the configuration string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if (speed == USBD_SPEED_HIGH) { + USBD_GetString((uint8_t *)USBD_CDC_CONFIGURATION_HS_STRING, USBD_StrDesc, length); + } else { + USBD_GetString((uint8_t *)USBD_CDC_CONFIGURATION_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the interface string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if (speed == USBD_SPEED_HIGH) { + USBD_GetString((uint8_t *)USBD_CDC_INTERFACE_HS_STRING, USBD_StrDesc, length); + } else { + USBD_GetString((uint8_t *)USBD_CDC_INTERFACE_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the interface string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + USBD_GetString((uint8_t *)USBD_MSC_INTERFACE_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + + + +/** + * @brief Create the serial number string descriptor + * @param None + * @retval None + */ +static void Get_SerialNum(void) +{ + + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t *)DEVICE_ID1; + deviceserial1 = *(uint32_t *)DEVICE_ID2; + deviceserial2 = *(uint32_t *)DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) { + IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); + IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); + } +} + +/** + * @brief Convert Hex 32Bits value into char + * @param value: value to convert + * @param pbuf: pointer to the buffer + * @param len: buffer length + * @retval None + */ +static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + + for (idx = 0 ; idx < len ; idx ++) { + if (((value >> 28)) < 0xA) { + pbuf[ 2 * idx] = (value >> 28) + '0'; + } else { + pbuf[2 * idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[ 2 * idx + 1] = 0; + } +} + + + + + +/** + * Composite MSC CDC + * + * Source: + * https://github.com/grafalex82/GPSLogger/tree/master/Libs/USB/ + * file: usbd_msc_cdc.c + * + * Articles: + * https://weekly-geekly.github.io/articles/335018/index.html + * + * Copyright?? + * + * License?? + * + * AUTHOR + * + */ + +/* Includes ------------------------------------------------------------------*/ + + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_MSC_CDC + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_MSC_CDC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_MSC_CDC_Private_Defines + * @{ + */ + +/** @defgroup MSC_CORE_Private_FunctionPrototypes + * @{ + */ + + + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment = 4 +#endif + +#define USB_MSC_CDC_CONFIG_DESC_SIZ 98 + +///////////////////////////////////////////////////////////////////////////// +// MSC_CDC_HS +///////////////////////////////////////////////////////////////////////////// + +/* USB MSC+CDC device Configuration Descriptor */ +uint8_t USBD_MSC_CDC_HSCfgDesc[USB_MSC_CDC_CONFIG_DESC_SIZ] = { + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CDC_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x03, /*bNumInterfaces: 3 interface*/ + 0x01, /*bConfigurationValue: Configuration value*/ + 0x02, /*iConfiguration: Index of string descriptor describing the configuration*/ + 0xC0, /*bmAttributes: bus powered and Supports Remote Wakeup */ + 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ + /* 09 bytes */ + + + + /******** IAD should be positioned just before the CDC interfaces ****** + IAD to associate the two CDC interfaces */ + + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + 0x00, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x04, /* iFunction (Index of string descriptor describing this function) */ + /* 08 bytes */ + + /******************** CDC interfaces ********************/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + /* 05 bytes */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + /* 04 bytes */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + CDC_INTERFACE_IDX, /* bMasterInterface: Communication class interface */ + CDC_INTERFACE_IDX + 1, /* bSlaveInterface0: Data Class Interface */ + /* 05 bytes */ + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x03, + CDC_INTERFACE_IDX + 1, /* bDataInterface: 1 */ + /* 05 bytes */ + + + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /* 07 bytes */ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval */ + /* 07 bytes */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + /* 07 bytes */ + + + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x02, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent command set*/ + 0x50, /* nInterfaceProtocol */ + 0x00, /* iInterface: */ + /* 09 bytes */ + + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds */ + /* 07 bytes */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds*/ + /* 07 bytes */ + + + +}; + +///////////////////////////////////////////////////////////////////////////// +// MSC_CDC_FS +////////////////////////////////////////////////////////////////////////////// + +/* USB MSC+CDC device Configuration Descriptor */ +uint8_t USBD_MSC_CDC_FSCfgDesc[USB_MSC_CDC_CONFIG_DESC_SIZ] = { + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CDC_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x03, /*bNumInterfaces: 3 interface*/ + 0x01, /*bConfigurationValue: Configuration value*/ + 0x02, /*iConfiguration: Index of string descriptor describing the configuration*/ + 0xC0, /*bmAttributes: bus powered and Supports Remote Wakeup */ + 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ + /* 09 bytes */ + + + + /******************** CDC interface ********************/ + + /******** IAD should be positioned just before the CDC interfaces ****** + IAD to associate the two CDC interfaces */ + + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + 0x00, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x04, /* iFunction (Index of string descriptor describing this function) */ + /* 08 bytes */ + + /******************** CDC interfaces ********************/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + /* 05 bytes */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + /* 04 bytes */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + CDC_INTERFACE_IDX, /* bMasterInterface: Communication class interface */ + CDC_INTERFACE_IDX + 1, /* bSlaveInterface0: Data Class Interface */ + /* 05 bytes */ + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x03, + CDC_INTERFACE_IDX + 1, /* bDataInterface: 1 */ + /* 05 bytes */ + + + + /*CMD Endpoint Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /* 07 bytes */ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval */ + /* 07 bytes */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + /* 07 bytes */ + + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x02, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent command set*/ + 0x50, /* nInterfaceProtocol */ + 0x00, /* iInterface: */ + /* 09 bytes */ + + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds */ + /* 07 bytes */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds*/ + /* 07 bytes */ + +}; + +///////////////////////////////////////////////////////////////////////////// +// MSC_CDC_OtherSpeed +///////////////////////////////////////////////////////////////////////////// + +/* USB MSC+CDC device Configuration Descriptor */ +uint8_t USBD_MSC_CDC_OtherSpeedCfgDesc[USB_MSC_CDC_CONFIG_DESC_SIZ] = { + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CDC_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x03, /*bNumInterfaces: 3 interface*/ + 0x01, /*bConfigurationValue: Configuration value*/ + 0x02, /*iConfiguration: Index of string descriptor describing the configuration*/ + 0xC0, /*bmAttributes: bus powered and Supports Remote Wakeup */ + 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/ + /* 09 bytes */ + + + /******** IAD should be positioned just before the CDC interfaces ****** + IAD to associate the two CDC interfaces */ + + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + 0x00, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x04, /* iFunction (Index of string descriptor describing this function) */ + /* 08 bytes */ + + /******************** CDC interfaces ********************/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + /* 05 bytes */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + /* 04 bytes */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + CDC_INTERFACE_IDX, /* bMasterInterface: Communication class interface */ + CDC_INTERFACE_IDX + 1, /* bSlaveInterface0: Data Class Interface */ + /* 05 bytes */ + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x03, + CDC_INTERFACE_IDX + 1, /* bDataInterface: 1 */ + /* 05 bytes */ + + + + /*CMD Endpoint Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /* 07 bytes */ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x05, /* iInterface: */ + /* 09 bytes */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + /* 07 bytes */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + /* 07 bytes */ + + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x02, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent command set*/ + 0x50, /* nInterfaceProtocol */ + 0x00, /* iInterface: */ + /* 09 bytes */ + + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds */ + /* 07 bytes */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(USB_MSC_PACKET_SIZE), + HIBYTE(USB_MSC_PACKET_SIZE), + 0x00, /*Polling interval in milliseconds*/ + /* 07 bytes */ + +}; + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment = 4 +#endif +/* USB Standard Device Descriptor */ +uint8_t USBD_MSC_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + USB_MAX_PACKET_SIZE, + 0x01, + 0x00, +}; + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + +uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +/** + * @} + */ + + +/** @defgroup USBD_MSC_CDC_Private_Macros + * @{ + */ + +/** + * @} + */ + + + +/** @defgroup USBD_CDC_Private_FunctionPrototypes + * @{ + */ + + +uint8_t USBD_CDC_EP_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +uint8_t USBD_CDC_EP_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev); + + + +/** @defgroup USBD_MSC_CDC_Private_FunctionPrototypes + * @{ + */ + + +static uint8_t USBD_MSC_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +static uint8_t USBD_MSC_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +static uint8_t USBD_MSC_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +static uint8_t USBD_MSC_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t USBD_MSC_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t *USBD_MSC_CDC_GetFSCfgDesc(uint16_t *length); + +static uint8_t *USBD_MSC_CDC_GetHSCfgDesc(uint16_t *length); + +static uint8_t *USBD_MSC_CDC_GetOtherSpeedCfgDesc(uint16_t *length); + +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +/** + * @} + */ + +/** @defgroup USBD_MSC_CDC_Private_Variables + * @{ + */ + + +USBD_ClassTypeDef USBD_MSC_CDC_ClassDriver = { + USBD_MSC_CDC_Init, + USBD_MSC_CDC_DeInit, + USBD_MSC_CDC_Setup, + NULL, //USBD_MSC_CDC_EP0_TxReady, + USBD_CDC_EP0_RxReady, + USBD_MSC_CDC_DataIn, + USBD_MSC_CDC_DataOut, + NULL, //USBD_MSC_CDC_SOF, + NULL, //USBD_MSC_CDC_IsoINIncomplete, + NULL, //USBD_MSC_CDC_IsoOutIncomplete, + USBD_MSC_CDC_GetHSCfgDesc, + USBD_MSC_CDC_GetFSCfgDesc, + USBD_MSC_CDC_GetOtherSpeedCfgDesc, + USBD_CDC_GetDeviceQualifierDescriptor, +}; + + + + +/** @defgroup MSC_CORE_Private_Functions + * @{ + */ + +/** + * @brief USBD_MSC_Init + * Initialize the mass storage configuration + * @param pdev: device instance + * @param cfgidx: configuration index + * @retval status + */ +uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + if (pdev->dev_speed == USBD_SPEED_HIGH) { + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET); + pdev->ep_out[MSC_EPOUT_ADDR & 0xFU].is_used = 1U; + + /* Open EP IN */ + USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET); + pdev->ep_in[MSC_EPIN_ADDR & 0xFU].is_used = 1U; + } else { + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET); + pdev->ep_out[MSC_EPOUT_ADDR & 0xFU].is_used = 1U; + + /* Open EP IN */ + USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET); + pdev->ep_in[MSC_EPIN_ADDR & 0xFU].is_used = 1U; + } + pdev->pClassDataMSC = USBD_malloc(sizeof(USBD_MSC_BOT_HandleTypeDef)); + + if (pdev->pClassDataMSC == NULL) { + return USBD_FAIL; + } + + /* Init the BOT layer */ + MSC_BOT_Init(pdev); + + return USBD_OK; +} + +/** + * @brief USBD_MSC_DeInit + * DeInitilaize the mass storage configuration + * @param pdev: device instance + * @param cfgidx: configuration index + * @retval status + */ +uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* Close MSC EPs */ + USBD_LL_CloseEP(pdev, MSC_EPOUT_ADDR); + pdev->ep_out[MSC_EPOUT_ADDR & 0xFU].is_used = 0U; + + /* Close EP IN */ + USBD_LL_CloseEP(pdev, MSC_EPIN_ADDR); + pdev->ep_in[MSC_EPIN_ADDR & 0xFU].is_used = 0U; + + /* De-Init the BOT layer */ + MSC_BOT_DeInit(pdev); + + /* Free MSC Class Resources */ + if (pdev->pClassDataMSC != NULL) { + USBD_free(pdev->pClassDataMSC); + pdev->pClassDataMSC = NULL; + } + return USBD_OK; +} + + +/** +* @brief USBD_MSC_DataIn +* handle data IN Stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + MSC_BOT_DataIn(pdev, epnum); + return USBD_OK; +} + +/** +* @brief USBD_MSC_DataOut +* handle data OUT Stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + MSC_BOT_DataOut(pdev, epnum); + return USBD_OK; +} + +/** @defgroup USBD_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_Init + * Initialize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + uint8_t ret = 0U; + UNUSED(cfgidx); + USBD_CDC_HandleTypeDef *hcdc; + + if (pdev->dev_speed == USBD_SPEED_HIGH) { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK, + CDC_DATA_HS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK, + CDC_DATA_HS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U; + + } else { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK, + CDC_DATA_FS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK, + CDC_DATA_FS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U; + } + /* Open Command IN EP */ + USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE); + pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U; + + pdev->pClassDataCDC = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef)); + + if (pdev->pClassDataCDC == NULL) { + ret = 1U; + } else { + hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + /* Init physical Interface components */ + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->Init(); + + /* Init Xfer states */ + hcdc->TxState = 0U; + hcdc->RxState = 0U; + + if (pdev->dev_speed == USBD_SPEED_HIGH) { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } else { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + } + return ret; +} + +/** + * @brief USBD_CDC_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + uint8_t ret = 0U; + UNUSED(cfgidx); + + /* Close EP IN */ + USBD_LL_CloseEP(pdev, CDC_IN_EP); + pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 0U; + + /* Close EP OUT */ + USBD_LL_CloseEP(pdev, CDC_OUT_EP); + pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 0U; + + /* Close Command IN EP */ + USBD_LL_CloseEP(pdev, CDC_CMD_EP); + pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassDataCDC != NULL) { + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->DeInit(); + USBD_free(pdev->pClassDataCDC); + pdev->pClassDataCDC = NULL; + } + + return ret; +} + +/** + * @brief USBD_CDC_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + uint8_t ifalt = 0U; + uint16_t status_info = 0U; + uint8_t ret = USBD_OK; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) { + case USB_REQ_TYPE_CLASS : + if (req->wLength) { + if (req->bmRequest & 0x80U) { + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->Control(req->bRequest, + (uint8_t *)(void *)hcdc->data, + req->wLength); + + USBD_CtlSendData(pdev, (uint8_t *)(void *)hcdc->data, req->wLength); + } else { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)req->wLength; + + USBD_CtlPrepareRx(pdev, (uint8_t *)(void *)hcdc->data, req->wLength); + } + } else { + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->Control(req->bRequest, + (uint8_t *)(void *)req, 0U); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + USBD_CtlSendData(pdev, (uint8_t *)(void *)&status_info, 2U); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + USBD_CtlSendData(pdev, &ifalt, 1U); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return ret; +} + +/** + * @brief USBD_CDC_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCDC; + PCD_HandleTypeDef *hpcd = pdev->pPCDHandle; + USBD_CDC_ItfTypeDef *ctrl = (USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC; + + if (pdev->pClassDataCDC != NULL) { + if ((hcdc->TxLastLength > 0U) && ((hcdc->TxLastLength % hpcd->IN_ep[epnum].maxpacket) == 0U)) { + /* Update the packet total length */ + hcdc->TxLastLength = 0U; + + /* Send ZLP */ + USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } else { + hcdc->TxState = 0U; + if (ctrl->Transferred) { + ctrl->Transferred(); + } + } + return USBD_OK; + } else { + return USBD_FAIL; + } +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + /* Get the received data length */ + hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + if (pdev->pClassDataCDC != NULL) { + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + + return USBD_OK; + } else { + return USBD_FAIL; + } +} + +/** + * @brief USBD_CDC_EP0_RxReady + * Handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + if ((pdev->pClassSpecificInterfaceCDC != NULL) && (hcdc->CmdOpCode != 0xFFU)) { + ((USBD_CDC_ItfTypeDef *)pdev->pClassSpecificInterfaceCDC)->Control(hcdc->CmdOpCode, + (uint8_t *)(void *)hcdc->data, + (uint16_t)hcdc->CmdLength); + hcdc->CmdOpCode = 0xFFU; + + } + return USBD_OK; +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = sizeof(USBD_CDC_DeviceQualifierDesc); + return USBD_CDC_DeviceQualifierDesc; +} + +/** +* @brief USBD_CDC_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops) +{ + uint8_t ret = USBD_FAIL; + + if (fops != NULL) { + pdev->pClassSpecificInterfaceCDC = fops; + ret = USBD_OK; + } + + return ret; +} + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return USBD_OK; +} + + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + hcdc->RxBuffer = pbuff; + + return USBD_OK; +} + +/** + * @brief USBD_CDC_TransmitPacket + * Transmit packet on IN endpoint + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + if (pdev->pClassDataCDC != NULL) { + if (hcdc->TxState == 0U) { + /* Tx Transfer in progress */ + hcdc->TxState = 1U; + + /* Update the packet total length */ + hcdc->TxLastLength = hcdc->TxLength; + + /* Transmit next packet */ + USBD_LL_Transmit(pdev, CDC_IN_EP, hcdc->TxBuffer, + (uint16_t)hcdc->TxLength); + + return USBD_OK; + } else { + return USBD_BUSY; + } + } else { + return USBD_FAIL; + } +} + + +/** + * @brief USBD_CDC_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassDataCDC; + + /* Suspend or Resume USB Out process */ + if (pdev->pClassDataCDC != NULL) { + if (pdev->dev_speed == USBD_SPEED_HIGH) { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } else { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + return USBD_OK; + } else { + return USBD_FAIL; + } +} + +/** + * @} + */ + +/** @defgroup USBD_MSC_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_MSC_CDC_Init + * Initialize the MSC+CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_MSC_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* CDC initialization */ + uint8_t ret = USBD_CDC_Init(pdev, cfgidx); + if (ret != 0) { + return ret; + } + pdev->pClassDataMSC = USBD_malloc(sizeof(USBD_MSC_BOT_HandleTypeDef)); + + /* MSC initialization */ + ret = USBD_MSC_Init(pdev, cfgidx); + if (ret != 0) { + return ret; + } + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, USB_MAX_PACKET_SIZE); + + /* Open EP IN */ + USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, USB_MAX_PACKET_SIZE); + + + /* Init the BOT layer */ + MSC_BOT_Init(pdev); + ret = 0; + + return ret; +} + +/** + * @brief USBD_MSC_CDC_DeInit + * DeInitialize the MSC+CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_MSC_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* MSC De-initialization */ + USBD_MSC_DeInit(pdev, cfgidx); + + /* CDC De-initialization */ + USBD_CDC_DeInit(pdev, cfgidx); + + return USBD_OK; +} + + +/** +* @brief USBD_MSC_Setup +* Handle the MSC specific requests +* @param pdev: device instance +* @param req: USB request +* @retval status +*/ +uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) { + + /* Class request */ + case USB_REQ_TYPE_CLASS : + switch (req->bRequest) { + case BOT_GET_MAX_LUN : + + if ((req->wValue == 0) && + (req->wLength == 1) && + ((req->bmRequest & 0x80) == 0x80)) { + hmsc->max_lun = pdev->pClassSpecificInterfaceMSC->GetMaxLun(); + USBD_CtlSendData(pdev, (uint8_t *)&hmsc->max_lun, 1); + } else { + + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + break; + + case BOT_RESET : + if ((req->wValue == 0) && + (req->wLength == 0) && + ((req->bmRequest & 0x80) != 0x80)) { + MSC_BOT_Reset(pdev); + } else { + + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + break; + + default: + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + break; + /* Interface & Endpoint request */ + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) { + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData(pdev, (uint8_t *)&hmsc->interface, 1); + break; + + case USB_REQ_SET_INTERFACE : + hmsc->interface = (uint8_t)(req->wValue); + break; + + case USB_REQ_CLEAR_FEATURE: + + /* Flush the FIFO and Clear the stall status */ + USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex); + + /* Reactivate the EP */ + USBD_LL_CloseEP(pdev, (uint8_t)req->wIndex); + if ((((uint8_t)req->wIndex) & 0x80) == 0x80) { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, USB_MAX_PACKET_SIZE); + } else { + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, USB_MAX_PACKET_SIZE); + } + + /* Handle BOT error */ + MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); + break; + + } + break; + + default: + break; + } + return 0; +} + +/** + * @brief USBD_MSC_CDC_Setup + * Handle the MSC+CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +uint8_t USBD_MSC_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + // Route requests to MSC interface or its endpoints to MSC class implementaion + if (((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE && req->wIndex == MSC_INTERFACE_IDX) || + ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_ENDPOINT && ((req->wIndex & 0x7F) == MSC_EP_IDX))) { + return USBD_MSC_Setup(pdev, req); + } + + return USBD_CDC_Setup(pdev, req); +} + +/** + * @brief USBD_MSC_CDC_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_MSC_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + if (epnum == MSC_EP_IDX) { + return USBD_MSC_DataIn(pdev, epnum); + } + return USBD_CDC_DataIn(pdev, epnum); +} + +/** + * @brief USBD_MSC_CDC_DataOut + * handle data OUT Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_MSC_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + if (epnum == MSC_EPOUT_ADDR) { + return USBD_MSC_DataOut(pdev, epnum); + } + return USBD_CDC_DataOut(pdev, epnum); +} + +////////////////////////////////////////////////////////////// +// HS +////////////////////////////////////////////////////////////// + + + +/** + * @brief USBD_MSC_CDC_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_MSC_CDC_GetFSCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_MSC_CDC_FSCfgDesc); + return USBD_MSC_CDC_FSCfgDesc; +} + +/** + * @brief USBD_MSC_CDC_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_MSC_CDC_GetHSCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_MSC_CDC_HSCfgDesc); + return USBD_MSC_CDC_HSCfgDesc; +} + +/** + * @brief USBD_MSC_CDC_GetOtherSpeedCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_MSC_CDC_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_MSC_CDC_OtherSpeedCfgDesc); + return USBD_MSC_CDC_OtherSpeedCfgDesc; +} + +#endif /* USBCON && USBD_USE_CDC_COMPOSITE */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc.h new file mode 100644 index 0000000000..28341c57df --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc.h @@ -0,0 +1,133 @@ +/** + ****************************************************************************** + * @file usbd_msc.h + * @author MCD Application Team + * @brief Header for the usbd_msc.c file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_H +#define __USBD_MSC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_cdc_composite_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" +//#include "usbd_core.h" + +/** @addtogroup USBD_MSC_BOT + * @{ + */ + +/** @defgroup USBD_MSC + * @brief This file is the Header file for usbd_msc.c + * @{ + */ + + +/** @defgroup USBD_BOT_Exported_Defines + * @{ + */ +/* MSC Class Config */ +#ifndef MSC_MEDIA_PACKET +#define MSC_MEDIA_PACKET 64 // 512U +#endif /* MSC_MEDIA_PACKET */ + +#define MSC_MAX_FS_PACKET 0x40U +#define MSC_MAX_HS_PACKET 0x200U + +#define BOT_GET_MAX_LUN 0xFE +#define BOT_RESET 0xFF +#define USB_MSC_CONFIG_DESC_SIZ 32 + + +#define MSC_EPIN_ADDR 0x83U +#define MSC_EPOUT_ADDR 0x03U + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Types + * @{ + */ + +// forward declarations +struct _USBD_MSC_BOT_CBWTypeDef; +struct _USBD_MSC_BOT_CSWTypeDef; +struct _SENSE_ITEM; // USBD_SCSI_SenseTypeDef + +typedef struct _USBD_STORAGE { + int8_t (* Init)(uint8_t lun); + int8_t (* GetCapacity)(uint8_t lun, uint32_t *block_num, uint16_t *block_size); + int8_t (* IsReady)(uint8_t lun); + int8_t (* IsWriteProtected)(uint8_t lun); + int8_t (* Read)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* GetMaxLun)(void); + int8_t *pInquiry; + +} USBD_StorageTypeDef; + + +typedef struct _USBD_MSC_BOT_HandleTypeDef { + uint32_t max_lun; + uint32_t interface; + uint8_t bot_state; + uint8_t bot_status; + uint16_t bot_data_length; + uint8_t bot_data[MSC_MEDIA_PACKET]; + struct _USBD_MSC_BOT_CBWTypeDef cbw; + struct _USBD_MSC_BOT_CSWTypeDef csw; + + struct _SENSE_ITEM scsi_sense [SENSE_LIST_DEEPTH]; // USBD_SCSI_SenseTypeDef + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint16_t scsi_blk_size; + uint32_t scsi_blk_nbr; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +} USBD_MSC_BOT_HandleTypeDef; + +/* Structure for MSC process */ +extern USBD_ClassTypeDef USBD_MSC; +#define USBD_MSC_CLASS &USBD_MSC + +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, + USBD_StorageTypeDef *fops); +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_H */ +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_bot.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_bot.h new file mode 100644 index 0000000000..09158f668d --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_bot.h @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.h + * @author MCD Application Team + * @brief Header for the usbd_msc_bot.c file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_BOT_H +#define __USBD_MSC_BOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup MSC_BOT + * @brief This file is the Header file for usbd_msc_bot.c + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ +#define USBD_BOT_IDLE 0U /* Idle state */ +#define USBD_BOT_DATA_OUT 1U /* Data Out state */ +#define USBD_BOT_DATA_IN 2U /* Data In state */ +#define USBD_BOT_LAST_DATA_IN 3U /* Last Data In Last */ +#define USBD_BOT_SEND_DATA 4U /* Send Immediate data */ +#define USBD_BOT_NO_DATA 5U /* No data Stage */ + +#define USBD_BOT_CBW_SIGNATURE 0x43425355U +#define USBD_BOT_CSW_SIGNATURE 0x53425355U +#define USBD_BOT_CBW_LENGTH 31U +#define USBD_BOT_CSW_LENGTH 13U +#define USBD_BOT_MAX_DATA 256U + +/* CSW Status Definitions */ +#define USBD_CSW_CMD_PASSED 0x00U +#define USBD_CSW_CMD_FAILED 0x01U +#define USBD_CSW_PHASE_ERROR 0x02U + +/* BOT Status */ +#define USBD_BOT_STATUS_NORMAL 0U +#define USBD_BOT_STATUS_RECOVERY 1U +#define USBD_BOT_STATUS_ERROR 2U + + +#define USBD_DIR_IN 0U +#define USBD_DIR_OUT 1U +#define USBD_BOTH_DIR 2U + +/** + * @} + */ + +/** @defgroup MSC_CORE_Private_TypesDefinitions + * @{ + */ + +typedef struct { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; + uint8_t ReservedForAlign; +} USBD_MSC_BOT_CBWTypeDef; + + +typedef struct { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; + uint8_t ReservedForAlign[3]; +} USBD_MSC_BOT_CSWTypeDef; + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_Types + * @{ + */ + +/** + * @} + */ +/** @defgroup USBD_CORE_Exported_FunctionsPrototypes + * @{ + */ +void MSC_BOT_Init(USBD_HandleTypeDef *pdev); +void MSC_BOT_Reset(USBD_HandleTypeDef *pdev); +void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev); +void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, uint8_t CSW_Status); + +void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev, uint8_t epnum); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_BOT_H */ +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite.h new file mode 100644 index 0000000000..db73feca4d --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite.h @@ -0,0 +1,192 @@ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_MSC_CDC_COMPOSITE_H +#define __USB_MSC_CDC_COMPOSITE_H + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +//#include "usbd_ioreq.h" +#include "usbd_core.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_cdc_composite_bot.h" +#include "cdc_queue.h" +#include + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_MSC_CDC_Exported_Defines + * @{ + */ + +typedef enum { + MSC_UNLOCKED = 0U, + MSC_USB_LOCK = 1U, + MSC_BOOT_LOCK = 2U, + MSC_APP1_LOCK = 3U, + MSC_APP2_LOCK = 4U, + MSC_APP3_LOCK = 5U, + MSC_APP4_LOCK = 6U, +} MSC_lock_typedef; + +// endpoints numbers +#define MSC_EP_IDX 0x01 // only EP 0, EP 1 & EP 2 are bidirectional +#define CDC_CMD_EP_IDX 0x03 // unable to determine why EP 3 will not transmit + +//#define MSC_EP_IDX 0x03 // only EP 0, EP 1 & EP 2 are bidirectional +//#define CDC_CMD_EP_IDX 0x01 // unable to determine why EP 3 will not transmit +#define CDC_EP_IDX 0x02 // EP 3 can receive data from the host because there + +//#define MSC_INTERFACE_IDX 0x2 // Index of MSC interface +//#define CDC_INTERFACE_IDX 0x0 // Index of CDC interface +#define MSC_INTERFACE_IDX MSC_EP_IDX // Index of MSC interface +#define CDC_INTERFACE_IDX CDC_EP_IDX // Index of CDC interface + +#define IN_EP_DIR 0x80 // Adds a direction bit + +#define MSC_OUT_EP MSC_EP_IDX /* EP1 for BULK OUT */ +#define MSC_IN_EP (MSC_EP_IDX | IN_EP_DIR) /* EP1 for BULK IN */ + +#ifdef CDC_CMD_EP +#undef CDC_CMD_EP +#endif +#define CDC_CMD_EP (CDC_CMD_EP_IDX| IN_EP_DIR) /* EP3 for CDC commands */ + +#ifdef CDC_OUT_EP +#undef CDC_OUT_EP +#endif +#define CDC_OUT_EP CDC_EP_IDX /* EP2 for data OUT */ + +#ifdef CDC_IN_EP +#undef CDC_IN_EP +#endif +#define CDC_IN_EP (CDC_EP_IDX | IN_EP_DIR) /* EP2 for data IN */ + +#ifdef USB_MAX_PACKET_SIZE +#undef USB_MAX_PACKET_SIZE +#endif +#define USB_MAX_PACKET_SIZE USB_MAX_EP0_SIZE + +#ifdef CDC_CMD_PACKET_SIZE +#undef CDC_CMD_PACKET_SIZE +#endif +#define CDC_CMD_PACKET_SIZE 0x0010 // 8 /* Control Endpoint Packet size */ + +#ifdef CDC_DATA_PACKET_SIZE +#undef CDC_DATA_PACKET_SIZE +#endif +#define CDC_DATA_PACKET_SIZE USB_MAX_PACKET_SIZE + +#define USB_MSC_PACKET_SIZE 64 + + + +/** @addtogroup USBD_MSC_BOT + * @{ + */ + +/** @defgroup USBD_MSC + * @brief This file is the Header file for usbd_msc.c + * @{ + */ + + +/** @defgroup USBD_BOT_Exported_Defines + * @{ + */ +/* MSC Class Config */ +#ifndef MSC_MEDIA_PACKET +#define MSC_MEDIA_PACKET 8192 +#endif /* MSC_MEDIA_PACKET */ + +#define MSC_MAX_FS_PACKET 0x40U +#define MSC_MAX_HS_PACKET 0x200U + +#define BOT_GET_MAX_LUN 0xFE +#define BOT_RESET 0xFF +#define USB_MSC_CONFIG_DESC_SIZ 32 + + +#define MSC_EPIN_ADDR MSC_IN_EP +#define MSC_EPOUT_ADDR MSC_OUT_EP + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Types + * @{ + */ + +// forward declarations +//struct _USBD_MSC_BOT_CBWTypeDef; +//struct _USBD_MSC_BOT_CSWTypeDef; +struct _SENSE_ITEM; // USBD_SCSI_SenseTypeDef + +typedef struct _USBD_STORAGE { + int8_t (* Init)(uint8_t lun); + int8_t (* GetCapacity)(uint8_t lun, uint32_t *block_num, uint16_t *block_size); + int8_t (* IsReady)(uint8_t lun); + int8_t (* IsWriteProtected)(uint8_t lun); + int8_t (* Read)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* GetMaxLun)(void); + int8_t *pInquiry; + +} USBD_StorageTypeDef; + + +typedef struct _USBD_MSC_BOT_HandleTypeDef { + uint32_t max_lun; + uint32_t interface; + uint8_t bot_state; + uint8_t bot_status; + uint16_t bot_data_length; + uint8_t bot_data[MSC_MEDIA_PACKET]; + USBD_MSC_BOT_CBWTypeDef cbw; + USBD_MSC_BOT_CSWTypeDef csw; + + struct _SENSE_ITEM scsi_sense [SENSE_LIST_DEEPTH]; // USBD_SCSI_SenseTypeDef + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint16_t scsi_blk_size; + uint32_t scsi_blk_nbr; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +} USBD_MSC_BOT_HandleTypeDef; + +/* Structure for MSC process */ +extern USBD_ClassTypeDef USBD_MSC; +#define USBD_MSC_CLASS &USBD_MSC + +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, + USBD_StorageTypeDef *fops); +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_MSC_CDC_COMPOSITE_H */ +/** + * @} + */ + +/** + * @} + */ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_bot.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_bot.h new file mode 100644 index 0000000000..38def15ae7 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_bot.h @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.h + * @author MCD Application Team + * @brief Header for the usbd_msc_bot.c file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_BOT_H +#define __USBD_MSC_BOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup MSC_BOT + * @brief This file is the Header file for usbd_msc_bot.c + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ +#define USBD_BOT_IDLE 0U /* Idle state */ +#define USBD_BOT_DATA_OUT 1U /* Data Out state */ +#define USBD_BOT_DATA_IN 2U /* Data In state */ +#define USBD_BOT_LAST_DATA_IN 3U /* Last Data In Last */ +#define USBD_BOT_SEND_DATA 4U /* Send Immediate data */ +#define USBD_BOT_NO_DATA 5U /* No data Stage */ + +#define USBD_BOT_CBW_SIGNATURE 0x43425355U +#define USBD_BOT_CSW_SIGNATURE 0x53425355U +#define USBD_BOT_CBW_LENGTH 31U +#define USBD_BOT_CSW_LENGTH 13U +#define USBD_BOT_MAX_DATA 256U + +/* CSW Status Definitions */ +#define USBD_CSW_CMD_PASSED 0x00U +#define USBD_CSW_CMD_FAILED 0x01U +#define USBD_CSW_PHASE_ERROR 0x02U + +/* BOT Status */ +#define USBD_BOT_STATUS_NORMAL 0U +#define USBD_BOT_STATUS_RECOVERY 1U +#define USBD_BOT_STATUS_ERROR 2U + + +#define USBD_DIR_IN 0U +#define USBD_DIR_OUT 1U +#define USBD_BOTH_DIR 2U + +/** + * @} + */ + +/** @defgroup MSC_CORE_Private_TypesDefinitions + * @{ + */ + +typedef struct _USBD_MSC_BOT_CBWTypeDef { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; + uint8_t _ReservedForAlign; +} USBD_MSC_BOT_CBWTypeDef; + + +typedef struct _USBD_MSC_BOT_CSWTypeDef { + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; + uint8_t ReservedForAlign[3]; +} USBD_MSC_BOT_CSWTypeDef; + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_Types + * @{ + */ + +/** + * @} + */ +/** @defgroup USBD_CORE_Exported_FunctionsPrototypes + * @{ + */ +void MSC_BOT_Init(USBD_HandleTypeDef *pdev); +void MSC_BOT_Reset(USBD_HandleTypeDef *pdev); +void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev); +void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, uint8_t CSW_Status); + +void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev, uint8_t epnum); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_BOT_H */ +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_if.c b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_if.c new file mode 100644 index 0000000000..6ab7f50bcc --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_cdc_composite_if.c @@ -0,0 +1,381 @@ +/** + ****************************************************************************** + * @file usbd_cdc_if.c + * @author MCD Application Team + * @brief Generic media access Layer. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +#ifdef USBCON +#ifdef USBD_USE_CDC_COMPOSITE + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_desc.h" +#include "usbd_cdc_if.h" +#include "usbd_def.h" +#include "usbd_msc_cdc_composite.h" + + +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length); +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff); +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev); +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev); + + +#ifdef USE_USB_HS +#define CDC_MAX_PACKET_SIZE USB_OTG_HS_MAX_PACKET_SIZE +#elif defined(USB_OTG_FS) || defined(USB_OTG_FS_MAX_PACKET_SIZE) +#define CDC_MAX_PACKET_SIZE USB_OTG_FS_MAX_PACKET_SIZE +#else /* USB */ +#define CDC_MAX_PACKET_SIZE USB_MAX_EP0_SIZE +#endif + +/* USBD_CDC Private Variables */ +/* USB Device Core CDC handle declaration */ +USBD_HandleTypeDef hUSBD_Device_CDC; + +static bool CDC_initialized = false; +static uint32_t transmitStart = 0; + +/* Received Data over USB are stored in this buffer */ +CDC_TransmitQueue_TypeDef TransmitQueue; +CDC_ReceiveQueue_TypeDef ReceiveQueue; +__IO uint32_t lineState = 0; +__IO bool receivePended = true; + + +/** USBD_CDC Private Function Prototypes */ + +static int8_t USBD_CDC_Init(void); +static int8_t USBD_CDC_DeInit(void); +static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t USBD_CDC_Receive(uint8_t *pbuf, uint32_t *Len); +static int8_t USBD_CDC_Transferred(void); + +USBD_CDC_ItfTypeDef USBD_CDC_fops = { + USBD_CDC_Init, + USBD_CDC_DeInit, + USBD_CDC_Control, + USBD_CDC_Receive, + USBD_CDC_Transferred +}; + +USBD_CDC_LineCodingTypeDef linecoding = { + 250000, /* baud rate*/ + 0x00, /* stop bits-1*/ + 0x00, /* parity - none*/ + 0x08 /* nb. of bits 8*/ +}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief USBD_CDC_Init + * Initializes the CDC media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t USBD_CDC_Init(void) +{ + + /* Set Application Buffers */ + CDC_TransmitQueue_Init(&TransmitQueue); + CDC_ReceiveQueue_Init(&ReceiveQueue); + receivePended = true; + USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue)); + + return (USBD_OK); +} + +/** + * @brief USBD_CDC_DeInit + * DeInitializes the CDC media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t USBD_CDC_DeInit(void) +{ + + return (USBD_OK); +} + + +/** + * @brief USBD_CDC_Control + * Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + UNUSED(length); + switch (cmd) { + case CDC_SEND_ENCAPSULATED_COMMAND: + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + break; + + case CDC_SET_COMM_FEATURE: + break; + + case CDC_GET_COMM_FEATURE: + break; + + case CDC_CLEAR_COMM_FEATURE: + break; + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + case CDC_SET_LINE_CODING: + linecoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | \ + (pbuf[2] << 16) | (pbuf[3] << 24)); + linecoding.format = pbuf[4]; + linecoding.paritytype = pbuf[5]; + linecoding.datatype = pbuf[6]; + break; + + case CDC_GET_LINE_CODING: + pbuf[0] = (uint8_t)(linecoding.bitrate); + pbuf[1] = (uint8_t)(linecoding.bitrate >> 8); + pbuf[2] = (uint8_t)(linecoding.bitrate >> 16); + pbuf[3] = (uint8_t)(linecoding.bitrate >> 24); + pbuf[4] = linecoding.format; + pbuf[5] = linecoding.paritytype; + pbuf[6] = linecoding.datatype; + + break; + + case CDC_SET_CONTROL_LINE_STATE: + lineState = (((USBD_SetupReqTypedef *)pbuf)->wValue & 0x01) != 0; // Check DTR state + if (lineState) { // Reset the transmit timeout when the port is connected + transmitStart = 0; + } +#ifdef DTR_TOGGLING_SEQ + dtr_toggling++; /* Count DTR toggling */ +#endif + break; + + case CDC_SEND_BREAK: + break; + + default: + break; + } + + return (USBD_OK); +} + +/** + * @brief USBD_CDC_Receive + * Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will issue a NAK packet on any OUT packet received on + * USB endpoint untill exiting this function. If you exit this function + * before transfer is complete on CDC interface (ie. using DMA controller) + * it will result in receiving more data while previous ones are still + * not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) +{ + UNUSED(Buf); + /* It always contains required amount of free space for writing */ + CDC_ReceiveQueue_CommitBlock(&ReceiveQueue, (uint16_t)(*Len)); + receivePended = false; + /* If enough space in the queue for a full buffer then continue receive */ + CDC_resume_receive(); + return USBD_OK; +} + + +static int8_t USBD_CDC_Transferred(void) +{ + + CDC_TransmitQueue_CommitRead(&TransmitQueue); + CDC_continue_transmit(); + return (USBD_OK); +} + +#ifndef p_CDC_ClassData +#ifdef USBD_USE_CDC_COMPOSITE +#define p_CDC_ClassData pClassDataCDC +#else +#define p_CDC_ClassData pClassData +#endif +#endif + +/* + * The value USB_CDC_TRANSMIT_TIMEOUT is defined in terms of HAL_GetTick() units. + * Typically it is 1ms value. The timeout determines when we would consider the + * host "too slow" and threat the USB CDC port as disconnected. + */ +#ifndef USB_CDC_TRANSMIT_TIMEOUT +#define USB_CDC_TRANSMIT_TIMEOUT 0xffffffffll +#endif + +bool CDC_connected() +{ + /* Save the transmitStart value in a local variable to avoid twice reading - fix #478 */ + uint32_t transmitTime = transmitStart; + if (transmitTime) { + transmitTime = HAL_GetTick() - transmitTime; + } + + if (!(hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED)) { + return 0; + } + if (!(transmitTime < USB_CDC_TRANSMIT_TIMEOUT)) { + return 0; + } + if (!lineState) { + return 0; + } else { + return 1; + } +} + + +void CDC_continue_transmit(void) +{ + + uint16_t size; + uint8_t *buffer; + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) hUSBD_Device_CDC.p_CDC_ClassData; + /* + * TS: This method can be called both in the main thread + * (via USBSerial::write) and in the IRQ stream (via USBD_CDC_Transferred), + * BUT the main thread cannot pass this condition while waiting for a IRQ! + * This is not possible because TxState is not zero while waiting for data + * transfer ending! The IRQ thread is uninterrupted, since its priority + * is higher than that of the main thread. So this method is thread safe. + */ + if (hcdc->TxState == 0U) { + buffer = CDC_TransmitQueue_ReadBlock(&TransmitQueue, &size); + if (size > 0) { + transmitStart = HAL_GetTick(); + USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, buffer, size); + /* + * size never exceed PMA buffer and USBD_CDC_TransmitPacket make full + * copy of block in PMA, so no need to worry about buffer damage + */ + USBD_CDC_TransmitPacket(&hUSBD_Device_CDC); + } + } +} + +bool CDC_resume_receive(void) +{ + + /* + * TS: main and IRQ threads can't pass it at same time, because + * IRQ may occur only if receivePended is true. So it is thread-safe! + */ + if (!receivePended) { + uint8_t *block = CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue); + if (block != NULL) { + receivePended = true; + /* Set new buffer */ + USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, block); + USBD_CDC_ReceivePacket(&hUSBD_Device_CDC); + return true; + } + } + return false; +} + +uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +extern USBD_ClassTypeDef USBD_MSC_CDC_ClassDriver; + +extern USBD_CDC_ItfTypeDef USBD_MSC_CDC_fops; +extern USBD_StorageTypeDef SdMscDriver; +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops); +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id); +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass); +USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev); + +/** +* @brief USBD_MSC_RegisterStorage +* @param fops: storage callback +* @retval status +*/ +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, + USBD_StorageTypeDef *fops) +{ + if (fops != NULL) { + pdev->pClassSpecificInterfaceMSC = fops; + } + return USBD_OK; +} + +void CDC_init(void) +{ + + if (!CDC_initialized) { + /* Init Device Library */ + USBD_Init(&hUSBD_Device_CDC, &CDC_Desc, 0); + /* Add Supported Class */ + USBD_RegisterClass(&hUSBD_Device_CDC, &USBD_MSC_CDC_ClassDriver); + /* Add CDC Interface Class */ + USBD_CDC_RegisterInterface(&hUSBD_Device_CDC, &USBD_CDC_fops); + /* Start SD card interface */ + USBD_MSC_RegisterStorage(&hUSBD_Device_CDC, &SdMscDriver); + /* Start Device Process */ + USBD_Start(&hUSBD_Device_CDC); + CDC_initialized = true; + } +} + +void CDC_deInit(void) +{ + + if (CDC_initialized) { + USBD_Stop(&hUSBD_Device_CDC); + USBD_MSC_DeInit(&hUSBD_Device_CDC, 1); + USBD_CDC_DeInit(); + USBD_DeInit(&hUSBD_Device_CDC); + CDC_initialized = false; + } +} + + +#endif /* USBD_USE_CDC_COMPOSITE */ +#endif /* USBCON */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite.h new file mode 100644 index 0000000000..e0d50e4d1a --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite.h @@ -0,0 +1,73 @@ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_MSC_CDC_CORE_H +#define __USB_MSC_CDC_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_MSC_CDC_Exported_Defines + * @{ + */ + + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_MSC_CDC_ClassDriver; +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_MSC_CDC_CORE_H */ +/** + * @} + */ + +/** + * @} + */ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_bot.c b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_bot.c new file mode 100644 index 0000000000..714e66a485 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_bot.c @@ -0,0 +1,404 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides all the BOT protocol core functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#if defined(USBCON) && defined(USBD_USE_CDC_COMPOSITE) + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_msc_cdc_composite_bot.h" +#include "usbd_msc_cdc_composite.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" +#include "usbd_msc_cdc_composite.h" + +int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd); +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC); +USBD_StatusTypeDef USBD_CtlSendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); +USBD_StatusTypeDef USBD_CtlContinueSendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); +USBD_StatusTypeDef USBD_CtlPrepareRx(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); +USBD_StatusTypeDef USBD_CtlContinueRx(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t len); +USBD_StatusTypeDef USBD_CtlSendStatus(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_CtlReceiveStatus(USBD_HandleTypeDef *pdev); +uint32_t USBD_GetRxCount(USBD_HandleTypeDef *pdev, uint8_t ep_addr); + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_BOT + * @brief BOT protocol module + * @{ + */ + +/** @defgroup MSC_BOT_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_FunctionPrototypes + * @{ + */ +static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev); + +static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev); +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Functions + * @{ + */ + + + +/** +* @brief MSC_BOT_Init +* Initialize the BOT Process +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_Init(USBD_HandleTypeDef *pdev) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + hmsc->bot_state = USBD_BOT_IDLE; + hmsc->bot_status = USBD_BOT_STATUS_NORMAL; + + hmsc->scsi_sense_tail = 0; + hmsc->scsi_sense_head = 0; + + pdev->pClassSpecificInterfaceMSC->Init(0); + + USBD_LL_FlushEP(pdev, MSC_OUT_EP); + USBD_LL_FlushEP(pdev, MSC_IN_EP); + + /* Prapare EP to Receive First BOT Cmd */ + USBD_LL_PrepareReceive(pdev, + MSC_OUT_EP, + (uint8_t *)(void *)&hmsc->cbw, + USBD_BOT_CBW_LENGTH); +} + +/** +* @brief MSC_BOT_Reset +* Reset the BOT Machine +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_Reset(USBD_HandleTypeDef *pdev) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + hmsc->bot_state = USBD_BOT_IDLE; + hmsc->bot_status = USBD_BOT_STATUS_RECOVERY; + + /* Prapare EP to Receive First BOT Cmd */ + USBD_LL_PrepareReceive(pdev, + MSC_OUT_EP, + (uint8_t *)(void *)&hmsc->cbw, + USBD_BOT_CBW_LENGTH); +} + +/** +* @brief MSC_BOT_DeInit +* Deinitialize the BOT Machine +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_DeInit(USBD_HandleTypeDef *pdev) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + hmsc->bot_state = USBD_BOT_IDLE; +} + +/** +* @brief MSC_BOT_DataIn +* Handle BOT IN data stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ +void MSC_BOT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + switch (hmsc->bot_state) { + case USBD_BOT_DATA_IN: + if (SCSI_ProcessCmd(pdev, + hmsc->cbw.bLUN, + &hmsc->cbw.CB[0]) < 0) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED); + } + break; + + case USBD_BOT_SEND_DATA: + case USBD_BOT_LAST_DATA_IN: + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED); + + break; + + default: + break; + } +} +/** +* @brief MSC_BOT_DataOut +* Process MSC OUT data +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ +void MSC_BOT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + switch (hmsc->bot_state) { + case USBD_BOT_IDLE: + MSC_BOT_CBW_Decode(pdev); + break; + + case USBD_BOT_DATA_OUT: + + if (SCSI_ProcessCmd(pdev, + hmsc->cbw.bLUN, + &hmsc->cbw.CB[0]) < 0) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED); + } + + break; + + default: + break; + } +} + +/** +* @brief MSC_BOT_CBW_Decode +* Decode the CBW command and set the BOT state machine accordingly +* @param pdev: device instance +* @retval None +*/ +static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + hmsc->csw.dTag = hmsc->cbw.dTag; + hmsc->csw.dDataResidue = hmsc->cbw.dDataLength; + + if ((USBD_LL_GetRxDataSize(pdev, MSC_OUT_EP) != USBD_BOT_CBW_LENGTH) || + (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE) || + (hmsc->cbw.bLUN > 1) || + (hmsc->cbw.bCBLength < 1) || + (hmsc->cbw.bCBLength > 16)) { + + SCSI_SenseCode(pdev, + hmsc->cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + + hmsc->bot_status = USBD_BOT_STATUS_ERROR; + MSC_BOT_Abort(pdev); + + } else { + if (SCSI_ProcessCmd(pdev, + hmsc->cbw.bLUN, + &hmsc->cbw.CB[0]) < 0) { + if (hmsc->bot_state == USBD_BOT_NO_DATA) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED); + } else { + MSC_BOT_Abort(pdev); + } + } + /*Burst xfer handled internally*/ + else if ((hmsc->bot_state != USBD_BOT_DATA_IN) && + (hmsc->bot_state != USBD_BOT_DATA_OUT) && + (hmsc->bot_state != USBD_BOT_LAST_DATA_IN)) { + if (hmsc->bot_data_length > 0) { + MSC_BOT_SendData(pdev, + hmsc->bot_data, + hmsc->bot_data_length); + } else if (hmsc->bot_data_length == 0) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED); + } else { + MSC_BOT_Abort(pdev); + } + } else { + return; + } + } +} + +/** +* @brief MSC_BOT_SendData +* Send the requested data +* @param pdev: device instance +* @param buf: pointer to data buffer +* @param len: Data Length +* @retval None +*/ +static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + len = MIN(hmsc->cbw.dDataLength, len); + hmsc->csw.dDataResidue -= len; + hmsc->csw.bStatus = USBD_CSW_CMD_PASSED; + hmsc->bot_state = USBD_BOT_SEND_DATA; + + USBD_LL_Transmit(pdev, MSC_IN_EP, pbuf, len); +} + +/** +* @brief MSC_BOT_SendCSW +* Send the Command Status Wrapper +* @param pdev: device instance +* @param status : CSW status +* @retval None +*/ +void MSC_BOT_SendCSW(USBD_HandleTypeDef *pdev, + uint8_t CSW_Status) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE; + hmsc->csw.bStatus = CSW_Status; + hmsc->bot_state = USBD_BOT_IDLE; + + USBD_LL_Transmit(pdev, + MSC_IN_EP, + (uint8_t *)(void *)&hmsc->csw, + USBD_BOT_CSW_LENGTH); + + /* Prepare EP to Receive next Cmd */ + USBD_LL_PrepareReceive(pdev, + MSC_OUT_EP, + (uint8_t *)(void *)&hmsc->cbw, + USBD_BOT_CBW_LENGTH); + +} + +/** +* @brief MSC_BOT_Abort +* Abort the current transfer +* @param pdev: device instance +* @retval status +*/ + +static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + if ((hmsc->cbw.bmFlags == 0) && + (hmsc->cbw.dDataLength != 0) && + (hmsc->bot_status == USBD_BOT_STATUS_NORMAL)) { + USBD_LL_StallEP(pdev, MSC_OUT_EP); + } + USBD_LL_StallEP(pdev, MSC_IN_EP); + + if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) { + USBD_LL_PrepareReceive(pdev, + MSC_OUT_EP, + (uint8_t *)(void *)&hmsc->cbw, + USBD_BOT_CBW_LENGTH); + } +} + +/** +* @brief MSC_BOT_CplClrFeature +* Complete the clear feature request +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ + +void MSC_BOT_CplClrFeature(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassDataMSC; + + if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) { /* Bad CBW Signature */ + + USBD_LL_StallEP(pdev, MSC_IN_EP); + hmsc->bot_status = USBD_BOT_STATUS_NORMAL; + } else if (((epnum & 0x80) == 0x80) && (hmsc->bot_status != USBD_BOT_STATUS_RECOVERY)) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED); + } + +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +#endif // USBCON & USBD_USE_CDC_COMPOSITE + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_scsi.c b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_scsi.c new file mode 100644 index 0000000000..be843c31b9 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_composite_scsi.c @@ -0,0 +1,677 @@ +/** + ****************************************************************************** + * @file usbd_msc_scsi.c + * @author MCD Application Team + * @brief This file provides all the USBD SCSI layer functions. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#ifdef USBD_USE_CDC_COMPOSITE + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_msc_cdc_composite_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_cdc_composite.h" +#include "usbd_msc_data.h" + +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC); + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_SCSI + * @brief Mass storage SCSI layer module + * @{ + */ + +/** @defgroup MSC_SCSI_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_FunctionPrototypes + * @{ + */ +static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t blk_offset, uint32_t blk_nbr); + +static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun); +static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun); +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Functions + * @{ + */ + + +/** +* @brief SCSI_ProcessCmd +* Process SCSI commands +* @param pdev: device instance +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd) +{ + + switch (cmd[0]) { + case SCSI_TEST_UNIT_READY: // 0x00 + SCSI_TestUnitReady(pdev, lun, cmd); + break; + + case SCSI_REQUEST_SENSE: // 0x03 + SCSI_RequestSense(pdev, lun, cmd); + break; + + case SCSI_INQUIRY: // 0x12U 18 + SCSI_Inquiry(pdev, lun, cmd); + break; + + case SCSI_START_STOP_UNIT: // 0x1BU 27 + SCSI_StartStopUnit(pdev, lun, cmd); + break; + + case SCSI_ALLOW_MEDIUM_REMOVAL: // 0x1EU 30 + SCSI_StartStopUnit(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE6: // 0x1AU 26 + SCSI_ModeSense6(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE10: // 0x5AU 90 + SCSI_ModeSense10(pdev, lun, cmd); + break; + + case SCSI_READ_FORMAT_CAPACITIES: // 0x23U 35 + SCSI_ReadFormatCapacity(pdev, lun, cmd); + break; + + case SCSI_READ_CAPACITY10: // 0x25U 37 + SCSI_ReadCapacity10(pdev, lun, cmd); + break; + + case SCSI_READ10: // 0x28U 40 + SCSI_Read10(pdev, lun, cmd); + break; + + case SCSI_WRITE10: // 0x2AU 42 + SCSI_Write10(pdev, lun, cmd); + break; + + case SCSI_VERIFY10: // 0x2FU 47 + SCSI_Verify10(pdev, lun, cmd); + break; + + default: + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + return 0; +} + + +/** +* @brief SCSI_TestUnitReady +* Process SCSI Test Unit Ready Command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + /* case 9 : Hi > D0 */ + if (hmsc->cbw.dDataLength != 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + + return -1; + } + hmsc->bot_data_length = 0U; + + return 0; +} + +/** +* @brief SCSI_Inquiry +* Process Inquiry command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint8_t *pPage; + uint16_t len; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + if (params[1] & 0x01U) {/*Evpd is set*/ + len = LENGTH_INQUIRY_PAGE00; + hmsc->bot_data_length = len; + + while (len) { + len--; + hmsc->bot_data[len] = MSC_Page00_Inquiry_Data[len]; + } + } else { + pPage = (uint8_t *)(void *) & ((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN]; + len = (uint16_t)pPage[4] + 5U; + + if (params[4] <= len) { + len = params[4]; + } + hmsc->bot_data_length = len; + + while (len) { + len--; + hmsc->bot_data[len] = pPage[len]; + } + } + + return 0; +} + +/** +* @brief SCSI_ReadCapacity10 +* Process Read Capacity 10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } else { + + hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24); + hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16); + hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 8); + hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1U); + + hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24); + hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16); + hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8); + hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size); + + hmsc->bot_data_length = 8U; + return 0; + } +} +/** +* @brief SCSI_ReadFormatCapacity +* Process Read Format Capacity command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + uint16_t blk_size; + uint32_t blk_nbr; + uint16_t i; + + for (i = 0U; i < 12U ; i++) { + hmsc->bot_data[i] = 0U; + } + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->GetCapacity(lun, &blk_nbr, &blk_size) != 0U) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } else { + hmsc->bot_data[3] = 0x08U; + hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1U) >> 24); + hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1U) >> 16); + hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1U) >> 8); + hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1U); + + hmsc->bot_data[8] = 0x02U; + hmsc->bot_data[9] = (uint8_t)(blk_size >> 16); + hmsc->bot_data[10] = (uint8_t)(blk_size >> 8); + hmsc->bot_data[11] = (uint8_t)(blk_size); + + hmsc->bot_data_length = 12U; + return 0; + } +} +/** +* @brief SCSI_ModeSense6 +* Process Mode Sense6 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + uint16_t len = 8U; + hmsc->bot_data_length = len; + + while (len) { + len--; + hmsc->bot_data[len] = MSC_Mode_Sense6_data[len]; + } + return 0; +} + +/** +* @brief SCSI_ModeSense10 +* Process Mode Sense10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + hmsc->bot_data_length = len; + + while (len) { + len--; + hmsc->bot_data[len] = MSC_Mode_Sense10_data[len]; + } + + return 0; +} + +/** +* @brief SCSI_RequestSense +* Process Request Sense command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint8_t i; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + for (i = 0U ; i < REQUEST_SENSE_DATA_LEN; i++) { + hmsc->bot_data[i] = 0U; + } + + hmsc->bot_data[0] = 0x70U; + hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) { + + hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey; + hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ; + hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC; + hmsc->scsi_sense_head++; + + if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH) { + hmsc->scsi_sense_head = 0U; + } + } + hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN; + + if (params[4] <= REQUEST_SENSE_DATA_LEN) { + hmsc->bot_data_length = params[4]; + } + return 0; +} + +/** +* @brief SCSI_SenseCode +* Load the last error code in the error list +* @param lun: Logical unit number +* @param sKey: Sense Key +* @param ASC: Additional Sense Key +* @retval none + +*/ +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + + hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey; + hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8; + hmsc->scsi_sense_tail++; + if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH) { + hmsc->scsi_sense_tail = 0U; + } +} +/** +* @brief SCSI_StartStopUnit +* Process Start Stop Unit command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + hmsc->bot_data_length = 0U; + return 0; +} + +/** +* @brief SCSI_Read10 +* Process Read10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + + if (hmsc->bot_state == USBD_BOT_IDLE) { /* Idle */ + /* case 10 : Ho <> Di */ + if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | + ((uint32_t)params[3] << 16) | + ((uint32_t)params[4] << 8) | + (uint32_t)params[5]; + + hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | (uint32_t)params[8]; + + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + hmsc->bot_state = USBD_BOT_DATA_IN; + + /* cases 4, 5 : Hi <> Dn */ + if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size)) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + } + hmsc->bot_data_length = MSC_MEDIA_PACKET; + + return SCSI_ProcessRead(pdev, lun); +} + +/** +* @brief SCSI_Write10 +* Process Write10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + uint32_t len; + + if (hmsc->bot_state == USBD_BOT_IDLE) { /* Idle */ + /* case 8 : Hi <> Do */ + if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + /* Check whether Media is ready */ + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + /* Check If media is write-protected */ + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsWriteProtected(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); + return -1; + } + + hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | + ((uint32_t)params[3] << 16) | + ((uint32_t)params[4] << 8) | + (uint32_t)params[5]; + + hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | + (uint32_t)params[8]; + + /* check if LBA address is in the right range */ + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + /* cases 3, 11, 13 : Hn,Ho <> D0 */ + if (hmsc->cbw.dDataLength != len) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + len = MIN(len, MSC_MEDIA_PACKET); + + /* Prepare EP to receive first data packet */ + hmsc->bot_state = USBD_BOT_DATA_OUT; + USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } else { /* Write Process ongoing */ + return SCSI_ProcessWrite(pdev, lun); + } + return 0; +} + + +/** +* @brief SCSI_Verify10 +* Process Verify10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + + if ((params[1] & 0x02U) == 0x02U) { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + return -1; /* Error, Verify Mode Not supported*/ + } + + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) { + return -1; /* error */ + } + hmsc->bot_data_length = 0U; + return 0; +} + +/** +* @brief SCSI_CheckAddressRange +* Check address range +* @param lun: Logical unit number +* @param blk_offset: first block address +* @param blk_nbr: number of block to be processed +* @retval status +*/ +static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t blk_offset, uint32_t blk_nbr) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + + if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr) { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + return -1; + } + return 0; +} + +/** +* @brief SCSI_ProcessRead +* Handle Read Process +* @param lun: Logical unit number +* @retval status +*/ +static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->Read(lun, + hmsc->bot_data, + hmsc->scsi_blk_addr, + (len / hmsc->scsi_blk_size)) < 0) { + SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + return -1; + } + + USBD_LL_Transmit(pdev, MSC_EPIN_ADDR, hmsc->bot_data, len); + + hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size); + hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size); + + /* case 6 : Hi = Di */ + hmsc->csw.dDataResidue -= len; + + if (hmsc->scsi_blk_len == 0U) { + hmsc->bot_state = USBD_BOT_LAST_DATA_IN; + } + return 0; +} + +/** +* @brief SCSI_ProcessWrite +* Handle Write Process +* @param lun: Logical unit number +* @retval status +*/ + +static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassDataMSC; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->Write(lun, hmsc->bot_data, + hmsc->scsi_blk_addr, + (len / hmsc->scsi_blk_size)) < 0) { + SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size); + hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size); + + /* case 12 : Ho = Do */ + hmsc->csw.dDataResidue -= len; + + if (hmsc->scsi_blk_len == 0U) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED); + } else { + len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), MSC_MEDIA_PACKET); + /* Prepare EP to Receive next packet */ + USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } + + return 0; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +#endif // USBD_USE_CDC_COMPOSITE + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.c b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.c new file mode 100644 index 0000000000..13a85f52c3 --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.c @@ -0,0 +1,132 @@ +/** + ****************************************************************************** + * @file usbd_msc_data.c + * @author MCD Application Team + * @brief This file provides all the vital inquiry pages and sense data. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_data.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_DATA + * @brief Mass storage info/data module + * @{ + */ + +/** @defgroup MSC_DATA_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Variables + * @{ + */ + + +/* USB Mass storage Page 0 Inquiry Data */ +const uint8_t MSC_Page00_Inquiry_Data[] = { + 0x00, + 0x00, + 0x00, + (LENGTH_INQUIRY_PAGE00 - 4U), + 0x00, + 0x80, + 0x83 +}; +/* USB Mass storage sense 6 Data */ +const uint8_t MSC_Mode_Sense6_data[] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; +/* USB Mass storage sense 10 Data */ +const uint8_t MSC_Mode_Sense10_data[] = { + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Functions + * @{ + */ + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.h new file mode 100644 index 0000000000..578749b2cb --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_data.h @@ -0,0 +1,104 @@ +/** + ****************************************************************************** + * @file usbd_msc_data.h + * @author MCD Application Team + * @brief Header for the usbd_msc_data.c file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_DATA_H +#define __USBD_MSC_DATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" +#include + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_INFO + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_INFO_Exported_Defines + * @{ + */ +#define MODE_SENSE6_LEN 8U +#define MODE_SENSE10_LEN 8U +#define LENGTH_INQUIRY_PAGE00 7U +#define LENGTH_FORMAT_CAPACITIES 20U + +/** + * @} + */ + + +/** @defgroup USBD_INFO_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_INFO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_INFO_Exported_Variables + * @{ + */ +extern const uint8_t MSC_Page00_Inquiry_Data[]; +extern const uint8_t MSC_Mode_Sense6_data[]; +extern const uint8_t MSC_Mode_Sense10_data[] ; + +/** + * @} + */ + +/** @defgroup USBD_INFO_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_DATA_H */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_scsi.h b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_scsi.h new file mode 100644 index 0000000000..8531e88d4a --- /dev/null +++ b/cores/arduino/stm32/usb/msc_cdc_composite/usbd_msc_scsi.h @@ -0,0 +1,189 @@ +/** + ****************************************************************************** + * @file usbd_msc_scsi.h + * @author MCD Application Team + * @brief Header for the usbd_msc_scsi.c file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_SCSI + * @brief header file for the storage disk file + * @{ + */ + +/** @defgroup USBD_SCSI_Exported_Defines + * @{ + */ + +#define SENSE_LIST_DEEPTH 4U + +/* SCSI Commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define NO_SENSE 0U +#define RECOVERED_ERROR 1U +#define NOT_READY 2U +#define MEDIUM_ERROR 3U +#define HARDWARE_ERROR 4U +#define ILLEGAL_REQUEST 5U +#define UNIT_ATTENTION 6U +#define DATA_PROTECT 7U +#define BLANK_CHECK 8U +#define VENDOR_SPECIFIC 9U +#define COPY_ABORTED 10U +#define ABORTED_COMMAND 11U +#define VOLUME_OVERFLOW 13U +#define MISCOMPARE 14U + + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +extern uint8_t Page00_Inquiry_Data[]; +extern uint8_t Standard_Inquiry_Data[]; +extern uint8_t Standard_Inquiry_Data2[]; +extern uint8_t Mode_Sense6_data[]; +extern uint8_t Mode_Sense10_data[]; +extern uint8_t Scsi_Sense_Data[]; +extern uint8_t ReadCapacity10_Data[]; +extern uint8_t ReadFormatCapacity_Data []; +/** + * @} + */ + + +/** @defgroup USBD_SCSI_Exported_TypesDefinitions + * @{ + */ + +typedef struct _SENSE_ITEM { + char Skey; + union { + struct _ASCs { + char ASC; + char ASCQ; + } b; + uint8_t ASC; + char *pData; + } w; +} USBD_SCSI_SenseTypeDef; +/** + * @} + */ + +/** @defgroup USBD_SCSI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_SCSI_Exported_Variables + * @{ + */ + +/** + * @} + */ +/** @defgroup USBD_SCSI_Exported_FunctionsPrototype + * @{ + */ +int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd); + +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, + uint8_t ASC); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_SCSI_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/usbd_conf.c b/cores/arduino/stm32/usb/usbd_conf.c index 9fda970199..f5998ff2d5 100644 --- a/cores/arduino/stm32/usb/usbd_conf.c +++ b/cores/arduino/stm32/usb/usbd_conf.c @@ -12,7 +12,7 @@ * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 + * http://www.st.com/SLA0044 * ****************************************************************************** */ @@ -26,14 +26,25 @@ #ifndef HAL_PCD_MODULE_ENABLED #error "HAL_PCD_MODULE_ENABLED is required" #else -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -#if !defined(USBD_VBUS_DETECTION_ENABLE) -#define VBUS_SENSING DISABLE + +#ifndef p_Data +#ifdef USBD_USE_CDC_COMPOSITE +#define p_Data pPCDHandle #else -#define VBUS_SENSING ENABLE +#define p_Data pData +#endif #endif +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Size in words, byte size divided by 2 */ +#define PMA_EP0_OUT_ADDR (8 * 4) +#define PMA_EP0_IN_ADDR (PMA_EP0_OUT_ADDR + USB_MAX_EP0_SIZE) +#define PMA_CDC_OUT_BASE (PMA_EP0_IN_ADDR + USB_MAX_EP0_SIZE) +#define PMA_CDC_OUT_ADDR ((PMA_CDC_OUT_BASE + USB_FS_MAX_PACKET_SIZE) | \ + (PMA_CDC_OUT_BASE << 16U)) +#define PMA_CDC_IN_ADDR (PMA_CDC_OUT_BASE + USB_FS_MAX_PACKET_SIZE * 2) +#define PMA_CDC_CMD_ADDR (PMA_CDC_IN_ADDR + USB_FS_MAX_PACKET_SIZE) /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ PCD_HandleTypeDef g_hpcd; @@ -484,14 +495,14 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) g_hpcd.Init.phy_itface = PCD_PHY_ULPI; #endif g_hpcd.Init.speed = PCD_SPEED_HIGH; - g_hpcd.Init.vbus_sensing_enable = VBUS_SENSING; + g_hpcd.Init.vbus_sensing_enable = ENABLE; g_hpcd.Init.use_external_vbus = DISABLE; #else /* USE_USB_FS */ #ifdef USB_OTG_FS g_hpcd.Instance = USB_OTG_FS; g_hpcd.Init.use_dedicated_ep1 = DISABLE; g_hpcd.Init.dma_enable = DISABLE; - g_hpcd.Init.vbus_sensing_enable = VBUS_SENSING; + g_hpcd.Init.vbus_sensing_enable = DISABLE; g_hpcd.Init.use_external_vbus = DISABLE; #else g_hpcd.Instance = USB; @@ -502,7 +513,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) /* Link The driver to the stack */ g_hpcd.pData = pdev; - pdev->pData = &g_hpcd; + pdev->p_Data = &g_hpcd; /* Initialize LL Driver */ if (HAL_PCD_Init(&g_hpcd) != HAL_OK) { @@ -510,16 +521,29 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) } -#if !defined (USB) +#ifdef USE_USB_HS /* configure EPs FIFOs */ - HAL_PCDEx_SetRxFiFo(&g_hpcd, ep_def[0].ep_size); - for (uint32_t i = 1; i < (DEV_NUM_EP + 1); i++) { - HAL_PCDEx_SetTxFiFo(&g_hpcd, ep_def[i].ep_adress & 0xF, ep_def[i].ep_size); - } + HAL_PCDEx_SetRxFiFo(&g_hpcd, 0x200); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 0, 0x80); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 1, 0x40); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 2, 0x160); +#else /* USE_USB_FS */ +#ifdef USB_OTG_FS + /* configure EPs FIFOs */ + HAL_PCDEx_SetRxFiFo(&g_hpcd, 0x80); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 1, 0x40); + HAL_PCDEx_SetTxFiFo(&g_hpcd, 2, 0x40); +#ifdef USBD_USE_CDC_COMPOSITE + HAL_PCDEx_SetTxFiFo(&g_hpcd, 3, 0x40); +#endif #else - for (uint32_t i = 0; i < (DEV_NUM_EP + 1); i++) { - HAL_PCDEx_PMAConfig(&g_hpcd, ep_def[i].ep_adress, ep_def[i].ep_kind, ep_def[i].ep_size); - } + HAL_PCDEx_PMAConfig(&g_hpcd, 0x00, PCD_SNG_BUF, PMA_EP0_OUT_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x80, PCD_SNG_BUF, PMA_EP0_IN_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x01, PCD_DBL_BUF, PMA_CDC_OUT_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x82, PCD_SNG_BUF, PMA_CDC_IN_ADDR); + HAL_PCDEx_PMAConfig(&g_hpcd, 0x83, PCD_SNG_BUF, PMA_CDC_CMD_ADDR); +#endif #endif /* USE_USB_HS */ return USBD_OK; } @@ -531,7 +555,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) */ USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { - HAL_PCD_DeInit(pdev->pData); + HAL_PCD_DeInit(pdev->p_Data); return USBD_OK; } @@ -542,7 +566,7 @@ USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) */ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { - HAL_PCD_Start(pdev->pData); + HAL_PCD_Start(pdev->p_Data); return USBD_OK; } @@ -553,7 +577,7 @@ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) */ USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { - HAL_PCD_Stop(pdev->pData); + HAL_PCD_Stop(pdev->p_Data); return USBD_OK; } @@ -570,7 +594,7 @@ USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_type, uint16_t ep_mps) { - HAL_PCD_EP_Open(pdev->pData, + HAL_PCD_EP_Open(pdev->p_Data, ep_addr, ep_mps, ep_type); @@ -585,7 +609,7 @@ USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, */ USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - HAL_PCD_EP_Close(pdev->pData, ep_addr); + HAL_PCD_EP_Close(pdev->p_Data, ep_addr); return USBD_OK; } @@ -597,7 +621,7 @@ USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) */ USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - HAL_PCD_EP_Flush(pdev->pData, ep_addr); + HAL_PCD_EP_Flush(pdev->p_Data, ep_addr); return USBD_OK; } @@ -609,7 +633,7 @@ USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) */ USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - HAL_PCD_EP_SetStall(pdev->pData, ep_addr); + HAL_PCD_EP_SetStall(pdev->p_Data, ep_addr); return USBD_OK; } @@ -621,7 +645,7 @@ USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) */ USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + HAL_PCD_EP_ClrStall(pdev->p_Data, ep_addr); return USBD_OK; } @@ -633,7 +657,7 @@ USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_add */ uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - PCD_HandleTypeDef *hpcd = pdev->pData; + PCD_HandleTypeDef *hpcd = pdev->p_Data; if ((ep_addr & 0x80) == 0x80) { return hpcd->IN_ep[ep_addr & 0x7F].is_stall; @@ -650,7 +674,7 @@ uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) */ USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { - HAL_PCD_SetAddress(pdev->pData, dev_addr); + HAL_PCD_SetAddress(pdev->p_Data, dev_addr); return USBD_OK; } @@ -667,7 +691,7 @@ USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t size) { - HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); + HAL_PCD_EP_Transmit(pdev->p_Data, ep_addr, pbuf, size); return USBD_OK; } @@ -684,7 +708,7 @@ USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint16_t size) { - HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); + HAL_PCD_EP_Receive(pdev->p_Data, ep_addr, pbuf, size); return USBD_OK; } @@ -696,7 +720,7 @@ USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, */ uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); + return HAL_PCD_EP_GetRxCount(pdev->p_Data, ep_addr); } /** diff --git a/cores/arduino/stm32/usb/usbd_def.h b/cores/arduino/stm32/usb/usbd_def.h new file mode 100644 index 0000000000..077dc457d9 --- /dev/null +++ b/cores/arduino/stm32/usb/usbd_def.h @@ -0,0 +1,377 @@ +/** + ****************************************************************************** + * @file usbd_def.h + * @author MCD Application Team + * @brief General defines for the usb device library + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/** + ****************************************************************************** + * + * The composite MSC CDC USB device requires a modified USBD_HandleTypeDef + * structure. The MSC and CDC classes require dedicated data structures. + * + * The modified USBD_HandleTypeDef structure is copied from the GPSlogger + * repository https://github.com/grafalex82/GPSLogger/tree/master/Libs/USB + * + * See the article "CDC + MSC USB Composite Device for STM32 HAL" (URL: + * https://habr.com/en/post/335018/) for the theory behind the MSC CDC + * composite device as implemented in the above repository. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DEF_H +#define __USBD_DEF_H +#define bobwashere +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DEF + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DEF_Exported_Defines + * @{ + */ + +#ifndef NULL +#define NULL 0U +#endif /* NULL */ + +#ifndef USBD_MAX_NUM_INTERFACES +#define USBD_MAX_NUM_INTERFACES 1U +#endif /* USBD_MAX_NUM_CONFIGURATION */ + +#ifndef USBD_MAX_NUM_CONFIGURATION +#define USBD_MAX_NUM_CONFIGURATION 1U +#endif /* USBD_MAX_NUM_CONFIGURATION */ + +#ifndef USBD_LPM_ENABLED +#define USBD_LPM_ENABLED 0U +#endif /* USBD_LPM_ENABLED */ + +#ifndef USBD_SELF_POWERED +#define USBD_SELF_POWERED 1U +#endif /*USBD_SELF_POWERED */ + +#ifndef USBD_SUPPORT_USER_STRING_DESC +#define USBD_SUPPORT_USER_STRING_DESC 0U +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU +#define USB_LEN_DEV_DESC 0x12U +#define USB_LEN_CFG_DESC 0x09U +#define USB_LEN_IF_DESC 0x09U +#define USB_LEN_EP_DESC 0x07U +#define USB_LEN_OTG_DESC 0x03U +#define USB_LEN_LANGID_STR_DESC 0x04U +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U + +#define USBD_IDX_LANGID_STR 0x00U +#define USBD_IDX_MFC_STR 0x01U +#define USBD_IDX_PRODUCT_STR 0x02U +#define USBD_IDX_SERIAL_STR 0x03U +#define USBD_IDX_CONFIG_STR 0x04U +#define USBD_IDX_INTERFACE_STR 0x05U + +#define USB_REQ_TYPE_STANDARD 0x00U +#define USB_REQ_TYPE_CLASS 0x20U +#define USB_REQ_TYPE_VENDOR 0x40U +#define USB_REQ_TYPE_MASK 0x60U + +#define USB_REQ_RECIPIENT_DEVICE 0x00U +#define USB_REQ_RECIPIENT_INTERFACE 0x01U +#define USB_REQ_RECIPIENT_ENDPOINT 0x02U +#define USB_REQ_RECIPIENT_MASK 0x03U + +#define USB_REQ_GET_STATUS 0x00U +#define USB_REQ_CLEAR_FEATURE 0x01U +#define USB_REQ_SET_FEATURE 0x03U +#define USB_REQ_SET_ADDRESS 0x05U +#define USB_REQ_GET_DESCRIPTOR 0x06U +#define USB_REQ_SET_DESCRIPTOR 0x07U +#define USB_REQ_GET_CONFIGURATION 0x08U +#define USB_REQ_SET_CONFIGURATION 0x09U +#define USB_REQ_GET_INTERFACE 0x0AU +#define USB_REQ_SET_INTERFACE 0x0BU +#define USB_REQ_SYNCH_FRAME 0x0CU + +#define USB_DESC_TYPE_DEVICE 0x01U +#define USB_DESC_TYPE_CONFIGURATION 0x02U +#define USB_DESC_TYPE_STRING 0x03U +#define USB_DESC_TYPE_INTERFACE 0x04U +#define USB_DESC_TYPE_ENDPOINT 0x05U +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U +#define USB_DESC_TYPE_BOS 0x0FU + +#define USB_CONFIG_REMOTE_WAKEUP 0x02U +#define USB_CONFIG_SELF_POWERED 0x01U + +#define USB_FEATURE_EP_HALT 0x00U +#define USB_FEATURE_REMOTE_WAKEUP 0x01U +#define USB_FEATURE_TEST_MODE 0x02U + +#define USB_DEVICE_CAPABITY_TYPE 0x10U + +#define USB_HS_MAX_PACKET_SIZE 512U +#define USB_FS_MAX_PACKET_SIZE 64U +#define USB_MAX_EP0_SIZE 64U + +/* Device Status */ +#define USBD_STATE_DEFAULT 0x01U +#define USBD_STATE_ADDRESSED 0x02U +#define USBD_STATE_CONFIGURED 0x03U +#define USBD_STATE_SUSPENDED 0x04U + + +/* EP0 State */ +#define USBD_EP0_IDLE 0x00U +#define USBD_EP0_SETUP 0x01U +#define USBD_EP0_DATA_IN 0x02U +#define USBD_EP0_DATA_OUT 0x03U +#define USBD_EP0_STATUS_IN 0x04U +#define USBD_EP0_STATUS_OUT 0x05U +#define USBD_EP0_STALL 0x06U + +#define USBD_EP_TYPE_CTRL 0x00U +#define USBD_EP_TYPE_ISOC 0x01U +#define USBD_EP_TYPE_BULK 0x02U +#define USBD_EP_TYPE_INTR 0x03U + + +/** + * @} + */ + + +/** @defgroup USBD_DEF_Exported_TypesDefinitions + * @{ + */ + +// forward declarations +#ifdef USBD_USE_CDC_COMPOSITE +struct _USBD_MSC_BOT_HandleTypeDef; +struct _USBD_STORAGE; //USBD_StorageTypeDef +struct _USBD_CDC_HandleTypeDef; +struct _USBD_CDC_Itf; +#endif + +typedef struct usb_setup_req { + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USBD_SetupReqTypedef; + +struct _USBD_HandleTypeDef; + +typedef struct _Device_cb { + uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx); + uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev); + uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev); + /* Class Specific Endpoints*/ + uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev); + uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum); + + uint8_t *(*GetHSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetFSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length); + uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length); +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length); +#endif + +} USBD_ClassTypeDef; + +/* Following USB Device Speed */ +typedef enum { + USBD_SPEED_HIGH = 0U, + USBD_SPEED_FULL = 1U, + USBD_SPEED_LOW = 2U, +} USBD_SpeedTypeDef; + +/* Following USB Device status */ +typedef enum { + USBD_OK = 0U, + USBD_BUSY, + USBD_FAIL, +} USBD_StatusTypeDef; + +/* USB Device descriptors structure */ +typedef struct { + uint8_t *(*GetDeviceDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetProductStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); +#if (USBD_LPM_ENABLED == 1U) + uint8_t *(*GetBOSDescriptor)(USBD_SpeedTypeDef speed, uint16_t *length); +#endif +} USBD_DescriptorsTypeDef; + +/* USB Device handle structure */ +typedef struct { + uint32_t status; + uint32_t is_used; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; +} USBD_EndpointTypeDef; + +/* USB Device handle structure */ +typedef struct _USBD_HandleTypeDef { + uint8_t id; + uint32_t dev_config; + uint32_t dev_default_config; + uint32_t dev_config_status; + USBD_SpeedTypeDef dev_speed; + USBD_EndpointTypeDef ep_in[16]; + USBD_EndpointTypeDef ep_out[16]; + uint32_t ep0_state; + uint32_t ep0_data_len; + uint32_t ep0_rem_len; + uint32_t ep0_total_len; + uint8_t dev_state; + uint8_t dev_old_state; + uint8_t dev_address; + uint8_t dev_connection_status; + uint8_t dev_test_mode; + uint32_t dev_remote_wakeup; + + USBD_SetupReqTypedef request; + USBD_DescriptorsTypeDef *pDesc; + USBD_ClassTypeDef *pClass; + +#ifdef USBD_USE_CDC_COMPOSITE // MSC & CDC need separate variable structures + struct _USBD_MSC_BOT_HandleTypeDef *pClassDataMSC; + struct _USBD_STORAGE *pClassSpecificInterfaceMSC; // USBD_StorageTypeDef + struct _USBD_CDC_HandleTypeDef *pClassDataCDC; + struct _USBD_CDC_Itf *pClassSpecificInterfaceCDC; // USBD_CDC_ItfTypeDef + PCD_HandleTypeDef *pPCDHandle; +#else + void *pClassData; + void *pUserData; + void *pData; +#endif + +} USBD_HandleTypeDef; + +/** + * @} + */ + + + +/** @defgroup USBD_DEF_Exported_Macros + * @{ + */ +#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define LOBYTE(x) ((uint8_t)((x) & 0x00FFU)) +#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + +#if defined (__GNUC__) +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif /* __packed */ +#endif /* __GNUC__ */ + + +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ +#ifndef __ALIGN_END +#define __ALIGN_END __attribute__ ((aligned (4U))) +#endif /* __ALIGN_END */ +#ifndef __ALIGN_BEGIN +#define __ALIGN_BEGIN +#endif /* __ALIGN_BEGIN */ +#else +#ifndef __ALIGN_END +#define __ALIGN_END +#endif /* __ALIGN_END */ +#ifndef __ALIGN_BEGIN +#if defined (__CC_ARM) /* ARM Compiler */ +#define __ALIGN_BEGIN __align(4U) +#elif defined (__ICCARM__) /* IAR Compiler */ +#define __ALIGN_BEGIN +#endif /* __CC_ARM */ +#endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DEF_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/usbd_desc.c b/cores/arduino/stm32/usb/usbd_desc.c index 97896e3876..9c691a0740 100644 --- a/cores/arduino/stm32/usb/usbd_desc.c +++ b/cores/arduino/stm32/usb/usbd_desc.c @@ -17,6 +17,7 @@ ****************************************************************************** */ #ifdef USBCON +#ifndef USBD_USE_CDC_COMPOSITE /* Includes ------------------------------------------------------------------*/ #include "usbd_core.h" #include "usbd_desc.h" @@ -25,71 +26,38 @@ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ - -/* USB VID and PID: Either both or neither must be specified. If not - * specified, default to the ST VID, with a PID assigned to HID or a PID - * assigned to CDC devices. */ -#if !USBD_PID && !USBD_VID -// Undef the default zero values -#undef USBD_PID -#undef USBD_VID -// Define default values, based on the USB class used -#define USBD_VID 0x0483 -#if defined(USBD_USE_HID_COMPOSITE) -#define USBD_PID 0x5711 -#elif defined(USBD_USE_CDC) -#define USBD_PID 0x5740 -#endif -#endif /* !USBD_PID && !USBD_VID */ - -#if !USBD_VID || !USBD_PID -#error "USB VID or PID not specified" -#endif - -/* Manufacturer string: Use the specified string if specified, guess - based on VID otherwise */ -#if defined(USB_MANUFACTURER_STRING) -#define USBD_MANUFACTURER_STRING USB_MANUFACTURER_STRING -#elif USBD_VID == 0x2341 +#if USBD_VID == 0x2341 #define USBD_MANUFACTURER_STRING "Arduino LLC" #elif USBD_VID == 0x2A03 #define USBD_MANUFACTURER_STRING "Arduino srl" #elif USBD_VID == 0x0483 #define USBD_MANUFACTURER_STRING "STMicroelectronics" -#else +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro #define USBD_MANUFACTURER_STRING "Unknown" -#endif - -#define USBD_LANGID_STRING 0x409 /* 1033 US.S English */ - -/* Product string: Use the specified string if specified, construct - based on BOARD_NAME and class otherwise. */ -#if defined(USB_PRODUCT_STRING) -#define USBD_CLASS_PRODUCT_HS_STRING USB_PRODUCT_STRING -#define USBD_CLASS_PRODUCT_FS_STRING USB_PRODUCT_STRING -#elif defined(USBD_USE_HID_COMPOSITE) -#define USBD_CLASS_PRODUCT_HS_STRING CONCATS(BOARD_NAME, "HID in HS Mode") -#define USBD_CLASS_PRODUCT_FS_STRING CONCATS(BOARD_NAME, "HID in FS Mode") -#elif defined(USBD_USE_CDC) -#define USBD_CLASS_PRODUCT_HS_STRING CONCATS(BOARD_NAME, "CDC in HS Mode") -#define USBD_CLASS_PRODUCT_FS_STRING CONCATS(BOARD_NAME, "CDC in FS Mode") #else -#define USBD_CLASS_PRODUCT_HS_STRING CONCATS(BOARD_NAME, "in HS Mode") -#define USBD_CLASS_PRODUCT_FS_STRING CONCATS(BOARD_NAME, "in FS Mode") +#define USBD_MANUFACTURER_STRING USB_MANUFACTURER #endif +#define USBD_LANGID_STRING 0x409 /* 1033 US.S English */ #ifdef USBD_USE_HID_COMPOSITE -#define USBD_CLASS_CONFIGURATION_HS_STRING CONCATS(BOARD_NAME, "HID Config") -#define USBD_CLASS_INTERFACE_HS_STRING CONCATS(BOARD_NAME, "HID Interface") -#define USBD_CLASS_CONFIGURATION_FS_STRING CONCATS(BOARD_NAME, "HID Config") -#define USBD_CLASS_INTERFACE_FS_STRING CONCATS(BOARD_NAME, "HID Interface") +#define USBD_CLASS_PID 0x5711 +#define USBD_CLASS_PRODUCT_HS_STRING CONCATS(USB_PRODUCT, "HID in HS Mode") +#define USBD_CLASS_PRODUCT_FS_STRING CONCATS(USB_PRODUCT, "HID in FS Mode") +#define USBD_CLASS_CONFIGURATION_HS_STRING CONCATS(USB_PRODUCT, "HID Config") +#define USBD_CLASS_INTERFACE_HS_STRING CONCATS(USB_PRODUCT, "HID Interface") +#define USBD_CLASS_CONFIGURATION_FS_STRING CONCATS(USB_PRODUCT, "HID Config") +#define USBD_CLASS_INTERFACE_FS_STRING CONCATS(USB_PRODUCT, "HID Interface") #endif /* USBD_USE_HID_COMPOSITE */ #ifdef USBD_USE_CDC -#define USBD_CLASS_CONFIGURATION_HS_STRING CONCATS(BOARD_NAME, "CDC Config") -#define USBD_CLASS_INTERFACE_HS_STRING CONCATS(BOARD_NAME, "CDC Interface") -#define USBD_CLASS_CONFIGURATION_FS_STRING CONCATS(BOARD_NAME, "CDC Config") -#define USBD_CLASS_INTERFACE_FS_STRING CONCATS(BOARD_NAME, "CDC Interface") +#define USBD_CLASS_PID 0x5740 +#define USBD_CLASS_PRODUCT_HS_STRING CONCATS(USB_PRODUCT, "CDC in HS Mode") +#define USBD_CLASS_PRODUCT_FS_STRING CONCATS(USB_PRODUCT, "CDC in FS Mode") +#define USBD_CLASS_CONFIGURATION_HS_STRING CONCATS(USB_PRODUCT, "CDC Config") +#define USBD_CLASS_INTERFACE_HS_STRING CONCATS(USB_PRODUCT, "CDC Interface") +#define USBD_CLASS_CONFIGURATION_FS_STRING CONCATS(USB_PRODUCT, "CDC Config") +#define USBD_CLASS_INTERFACE_FS_STRING CONCATS(USB_PRODUCT, "CDC Interface") #endif /* USBD_USE_CDC */ /* Private macro -------------------------------------------------------------*/ @@ -133,10 +101,10 @@ __ALIGN_BEGIN uint8_t USBD_Class_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { USB_MAX_EP0_SIZE, /* bMaxPacketSize */ LOBYTE(USBD_VID), /* idVendor */ HIBYTE(USBD_VID), /* idVendor */ - LOBYTE(USBD_PID), /* idProduct */ - HIBYTE(USBD_PID), /* idProduct */ - 0x00, /* bcdDevice rel. 0.00 */ - 0x00, + LOBYTE(USBD_CLASS_PID), /* idVendor */ + HIBYTE(USBD_CLASS_PID), /* idVendor */ + 0x00, /* bcdDevice rel. 2.00 */ + 0x02, USBD_IDX_MFC_STR, /* Index of manufacturer string */ USBD_IDX_PRODUCT_STR, /* Index of product string */ USBD_IDX_SERIAL_STR, /* Index of serial number string */ @@ -157,10 +125,10 @@ __ALIGN_BEGIN uint8_t USBD_Class_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { USB_MAX_EP0_SIZE, /* bMaxPacketSize */ LOBYTE(USBD_VID), /* idVendor */ HIBYTE(USBD_VID), /* idVendor */ - LOBYTE(USBD_PID), /* idProduct */ - HIBYTE(USBD_PID), /* idProduct */ - 0x00, /* bcdDevice rel. 0.00 */ - 0x00, + LOBYTE(USBD_CLASS_PID), /* idVendor */ + HIBYTE(USBD_CLASS_PID), /* idVendor */ + 0x00, /* bcdDevice rel. 2.00 */ + 0x02, USBD_IDX_MFC_STR, /* Index of manufacturer string */ USBD_IDX_PRODUCT_STR, /* Index of product string */ USBD_IDX_SERIAL_STR, /* Index of serial number string */ @@ -306,9 +274,9 @@ static void Get_SerialNum(void) deviceserial0 += deviceserial2; - if (deviceserial0 != 0U) { - IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8U); - IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4U); + if (deviceserial0 != 0) { + IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); + IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); } } @@ -321,19 +289,21 @@ static void Get_SerialNum(void) */ static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len) { - uint8_t idx = 0U; + uint8_t idx = 0; - for (idx = 0U ; idx < len ; idx ++) { - if (((value >> 28)) < 0xAU) { - pbuf[ 2U * idx] = (value >> 28) + '0'; + for (idx = 0 ; idx < len ; idx ++) { + if (((value >> 28)) < 0xA) { + pbuf[ 2 * idx] = (value >> 28) + '0'; } else { - pbuf[2U * idx] = (value >> 28) + 'A' - 10U; + pbuf[2 * idx] = (value >> 28) + 'A' - 10; } value = value << 4; - pbuf[2U * idx + 1] = 0U; + pbuf[ 2 * idx + 1] = 0; } } +#endif /* !USBD_USE_CDC_COMPOSITE*/ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/cores/arduino/stm32/usb/usbd_desc.h b/cores/arduino/stm32/usb/usbd_desc.h index 17c8ffe999..309d7c5345 100644 --- a/cores/arduino/stm32/usb/usbd_desc.h +++ b/cores/arduino/stm32/usb/usbd_desc.h @@ -12,7 +12,7 @@ * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 + * http://www.st.com/SLA0044 * ****************************************************************************** */ @@ -36,7 +36,14 @@ /* Exported functions ------------------------------------------------------- */ extern USBD_DescriptorsTypeDef USBD_Desc; +#ifdef USBD_USE_HID_COMPOSITE +extern USBD_DescriptorsTypeDef HID_Desc; +#endif +#ifdef USBD_USE_CDC +extern USBD_DescriptorsTypeDef CDC_Desc; +#endif #endif /* USBCON */ #endif /* __USBD_DESC_H*/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_qspi.h b/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_qspi.h old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_sd.h b/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_sd.h old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_sd_ex.h b/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_hal_sd_ex.h old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_ll_sdmmc.h b/system/Drivers/STM32MP1xx_HAL_Driver/Inc/stm32mp1xx_ll_sdmmc.h old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c b/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_qspi.c old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c b/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd.c old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c b/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_hal_sd_ex.c old mode 100755 new mode 100644 diff --git a/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c b/system/Drivers/STM32MP1xx_HAL_Driver/Src/stm32mp1xx_ll_sdmmc.c old mode 100755 new mode 100644 diff --git a/system/Middlewares/OpenAMP/open-amp/apps/examples/rpc_demo/rpc_demo.c b/system/Middlewares/OpenAMP/open-amp/apps/examples/rpc_demo/rpc_demo.c old mode 100755 new mode 100644 diff --git a/system/Middlewares/OpenAMP/open-amp/apps/examples/rpc_demo/rpc_demod.c b/system/Middlewares/OpenAMP/open-amp/apps/examples/rpc_demo/rpc_demod.c old mode 100755 new mode 100644 diff --git a/system/Middlewares/OpenAMP/open-amp/docs/openamp_ref.pdf b/system/Middlewares/OpenAMP/open-amp/docs/openamp_ref.pdf old mode 100755 new mode 100644 diff --git a/system/extras/prebuild.sh b/system/extras/prebuild.sh old mode 100755 new mode 100644 diff --git a/variants/Generic_F412Rx/PeripheralPins.c b/variants/Generic_F412Rx/PeripheralPins.c old mode 100755 new mode 100644 diff --git a/variants/Generic_F412Rx/PinNamesVar.h b/variants/Generic_F412Rx/PinNamesVar.h old mode 100755 new mode 100644