diff --git a/boards.txt b/boards.txt index 65074d3a9f..a91fa61206 100644 --- a/boards.txt +++ b/boards.txt @@ -2325,6 +2325,8 @@ Nucleo_144.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Nucleo_144.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Nucleo_144.menu.usb.CDC=CDC (no generic 'Serial') Nucleo_144.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Nucleo_144.menu.usb.CDC_MSC=CDC + MSC +Nucleo_144.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Nucleo_144.menu.usb.HID=HID (keyboard and mouse) Nucleo_144.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Nucleo_144.menu.xusb.FS=Low/Full Speed @@ -2338,6 +2340,8 @@ Nucleo_64.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Nucleo_64.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Nucleo_64.menu.usb.CDC=CDC (no generic 'Serial') Nucleo_64.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Nucleo_64.menu.usb.CDC_MSC=CDC + MSC +Nucleo_64.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Nucleo_64.menu.usb.HID=HID (keyboard and mouse) Nucleo_64.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Nucleo_64.menu.xusb.FS=Low/Full Speed @@ -2351,6 +2355,8 @@ Nucleo_32.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Nucleo_32.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Nucleo_32.menu.usb.CDC=CDC (no generic 'Serial') Nucleo_32.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Nucleo_32.menu.usb.CDC_MSC=CDC + MSC +Nucleo_32.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Nucleo_32.menu.usb.HID=HID (keyboard and mouse) Nucleo_32.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Nucleo_32.menu.xusb.FS=Low/Full Speed @@ -2364,6 +2370,8 @@ Disco.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Disco.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Disco.menu.usb.CDC=CDC (no generic 'Serial') Disco.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Disco.menu.usb.CDC_MSC=CDC + MSC +Disco.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Disco.menu.usb.HID=HID (keyboard and mouse) Disco.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Disco.menu.xusb.FS=Low/Full Speed @@ -2377,6 +2385,8 @@ Eval.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Eval.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Eval.menu.usb.CDC=CDC (no generic 'Serial') Eval.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Eval.menu.usb.CDC_MSC=CDC + MSC +Eval.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Eval.menu.usb.HID=HID (keyboard and mouse) Eval.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Eval.menu.xusb.FS=Low/Full Speed @@ -2390,6 +2400,8 @@ GenF1.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) GenF1.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC GenF1.menu.usb.CDC=CDC (no generic 'Serial') GenF1.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +GenF1.menu.usb.CDC_MSC=CDC + MSC +GenF1.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC GenF1.menu.usb.HID=HID (keyboard and mouse) GenF1.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE GenF1.menu.xusb.FS=Low/Full Speed @@ -2403,6 +2415,8 @@ GenF3.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) GenF3.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC GenF3.menu.usb.CDC=CDC (no generic 'Serial') GenF3.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +GenF3.menu.usb.CDC_MSC=CDC + MSC +GenF3.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC GenF3.menu.usb.HID=HID (keyboard and mouse) GenF3.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE GenF3.menu.xusb.FS=Low/Full Speed @@ -2416,6 +2430,8 @@ GenF4.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) GenF4.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC GenF4.menu.usb.CDC=CDC (no generic 'Serial') GenF4.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +GenF4.menu.usb.CDC_MSC=CDC + MSC +GenF4.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC GenF4.menu.usb.HID=HID (keyboard and mouse) GenF4.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE GenF4.menu.xusb.FS=Low/Full Speed @@ -2429,6 +2445,8 @@ GenH7.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) GenH7.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC GenH7.menu.usb.CDC=CDC (no generic 'Serial') GenH7.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +GenH7.menu.usb.CDC_MSC=CDC + MSC +GenH7.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC GenH7.menu.usb.HID=HID (keyboard and mouse) GenH7.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE GenH7.menu.xusb.FS=Low/Full Speed @@ -2440,6 +2458,8 @@ GenL0.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) GenL0.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC GenL0.menu.usb.CDC=CDC (no generic 'Serial') GenL0.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +GenL0.menu.usb.CDC_MSC=CDC + MSC +GenL0.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC GenL0.menu.usb.HID=HID (keyboard and mouse) GenL0.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE @@ -2448,6 +2468,8 @@ GenL0.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE 3dprinter.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC 3dprinter.menu.usb.CDC=CDC (no generic 'Serial') 3dprinter.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +3dprinter.menu.usb.CDC_MSC=CDC + MSC +3dprinter.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC 3dprinter.menu.xusb.FS=Low/Full Speed 3dprinter.menu.xusb.HS=High Speed 3dprinter.menu.xusb.HS.build.usb_speed=-DUSE_USB_HS @@ -2459,6 +2481,8 @@ Genericflight.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Genericflight.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Genericflight.menu.usb.CDC=CDC (no generic 'Serial') Genericflight.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Genericflight.menu.usb.CDC_MSC=CDC + MSC +Genericflight.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Genericflight.menu.usb.HID=HID (keyboard and mouse) Genericflight.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Genericflight.menu.xusb.FS=Low/Full Speed @@ -2472,6 +2496,8 @@ Garatronic.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Garatronic.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Garatronic.menu.usb.CDC=CDC (no generic 'Serial') Garatronic.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Garatronic.menu.usb.CDC_MSC=CDC + MSC +Garatronic.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Garatronic.menu.usb.HID=HID (keyboard and mouse) Garatronic.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE @@ -2480,6 +2506,8 @@ Midatronics.menu.usb.CDCgen=CDC (generic 'Serial' supersede U(S)ART) Midatronics.menu.usb.CDCgen.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC Midatronics.menu.usb.CDC=CDC (no generic 'Serial') Midatronics.menu.usb.CDC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC -DDISABLE_GENERIC_SERIALUSB +Midatronics.menu.usb.CDC_MSC=CDC + MSC +Midatronics.menu.usb.CDC_MSC.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC_MSC Midatronics.menu.usb.HID=HID (keyboard and mouse) Midatronics.menu.usb.HID.build.enable_usb={build.usb_flags} -DUSBD_USE_HID_COMPOSITE Midatronics.menu.xusb.FS=Low/Full Speed diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp new file mode 100644 index 0000000000..1b2dfaca24 --- /dev/null +++ b/cores/arduino/USB.cpp @@ -0,0 +1,126 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef USBCON + +#include "usbd_desc.h" +#include "USB.h" +#include "wiring.h" + +#ifdef USBD_USE_CDC_CLASS + #include "usbd_cdc.h" + #include "usbd_cdc_msc.h" + #include "usbd_cdc_if.h" +#endif + +#ifdef USBD_USE_MSC_CLASS + #include "usbd_msc.h" + #include "usbd_msc_storage_if.h" +#endif + +USB USBDevice; + +void USB::begin() +{ + if (!initialized) { + initialize(); + } +} + +#ifdef USBD_USE_MSC_CLASS +DummyUSBMscHandler dummyHandler; + +void USB::registerMscHandler(USBMscHandler &handler) +{ + pSingleMscHandler = &handler; + registerMscHandlers(1, &pSingleMscHandler, USBD_MSC_fops.pInquiry); +} + +void USB::registerMscHandlers(uint8_t count, USBMscHandler **ppHandlers, uint8_t *pInquiryData) +{ + if (count == 0) { + registerMscHandler(dummyHandler); + } else { + ppUsbMscHandlers = ppHandlers; + usbMscMaxLun = count - 1; + USBD_MSC_fops.pInquiry = pInquiryData; + } +} +#endif + +void USB::initialize() +{ + hUSBD_Device_CDC = &hUSBD_Device; + + + /* Init Device Library */ + if (USBD_Init(&hUSBD_Device, &USBD_Desc, 0) != USBD_OK) { + return; + } + + /* Add Supported Class and register interface */ +#ifdef USBD_USE_CDC + if (USBD_RegisterClass(&hUSBD_Device, &USBD_CDC) != USBD_OK) { + return; + } +#elif USBD_USE_CDC_MSC + if (USBD_RegisterClass(&hUSBD_Device, &USBD_CDC_MSC) != USBD_OK) { + return; + } +#elif USBD_USE_MSC + if (USBD_RegisterClass(&hUSBD_Device, &USBD_CDC_MSC) != USBD_OK) { + return; + } +#endif + +#ifdef USBD_USE_CDC_CLASS + hUSBD_Device_CDC = &hUSBD_Device; + if (USBD_CDC_RegisterInterface(&hUSBD_Device, &USBD_CDC_fops) != USBD_OK) { + return; + } +#endif + +#ifdef USBD_USE_MSC_CLASS + if (ppUsbMscHandlers == nullptr) { + registerMscHandler(dummyHandler); + } + if (USBD_MSC_RegisterStorage(&hUSBD_Device, &USBD_MSC_fops) != USBD_OK) { + return; + } +#endif + + /* Start Device Process */ + USBD_Start(&hUSBD_Device); + initialized = true; +} + +void USB::end() +{ + if (initialized) { + deinitialize(); + } +} + +void USB::deinitialize() +{ + USBD_Stop(&hUSBD_Device); + USBD_DeInit(&hUSBD_Device); + initialized = false; +} + +#endif // USBCON diff --git a/cores/arduino/USB.h b/cores/arduino/USB.h new file mode 100644 index 0000000000..1c06240d27 --- /dev/null +++ b/cores/arduino/USB.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _USB_H_ +#define _USB_H_ + +#ifdef USBCON + +#include "usbd_core.h" +#include "usbd_ep_conf.h" + +#ifdef USBD_USE_MSC_CLASS + #include "USBMscHandler.h" +#endif + +class USB { + public: +#ifdef USBD_USE_MSC_CLASS + void registerMscHandler(USBMscHandler &pHandler); + void registerMscHandlers(uint8_t count, USBMscHandler **pHandlers, uint8_t *pInquiryData); +#endif + + void begin(void); + + void end(void); + + protected: + void initialize(); + void deinitialize(); + + bool initialized; + + USBD_HandleTypeDef hUSBD_Device; + +#ifdef USBD_USE_MSC_CLASS + USBMscHandler *pSingleMscHandler; +#endif +}; + +extern USB USBDevice; + +#endif // USBCON +#endif // _USB_H_ \ No newline at end of file diff --git a/cores/arduino/USBMscHandler.h b/cores/arduino/USBMscHandler.h new file mode 100644 index 0000000000..9f8afea1e1 --- /dev/null +++ b/cores/arduino/USBMscHandler.h @@ -0,0 +1,89 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef _USB_MSC_HANDLER_H_ +#define _USB_MSC_HANDLER_H_ + +#if defined(USBCON) && defined(USBD_USE_MSC_CLASS) + +#include "usbd_core.h" +#include "usbd_msc.h" + +/* Handler for mass storage devices */ +class USBMscHandler { + public: + // Example: A 128 MB SD card has 245760 blocks, at a block size of 512 bytes + // Returns true if successful, otherwise false. + virtual bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) = 0; + + // Read [blk_len] blocks, starting at [blk_addr] into [buf]. + // Returns true if successful, otherwise false. + virtual bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) = 0; + + // Write [blk_len] blocks, starting at [blk_addr] into [buf]. + // Returns true if successful, otherwise false. + virtual bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) = 0; + + /** Optional functions **/ + + virtual bool Init() + { + return true; + } + + // Return false if the mass storage device has not been connected or initialized yet. + virtual bool IsReady() + { + return true; + } + + // If the device should be read-only then this function should return true. + virtual bool IsWriteProtected() + { + return false; + } +}; + +class DummyUSBMscHandler : public USBMscHandler { + public: + // Any call to one of these functions always fails. + bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) + { + return false; + } + + bool Read(uint8_t *pBuf, uint32_t blockAddr, uint16_t blkLen) + { + return false; + } + + bool Write(uint8_t *pBuf, uint32_t blockAddr, uint16_t blkLen) + { + return false; + } + + // The dummy handler is never ready. + bool IsReady() + { + return false; + } +}; + +#endif +#endif \ No newline at end of file diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 256b5a1df8..741f57ce9c 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -16,8 +16,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#if defined (USBCON) && defined(USBD_USE_CDC) +#include "usbd_ep_conf.h" +#if defined (USBCON) && defined(USBD_USE_CDC_CLASS) + +#include "USB.h" #include "USBSerial.h" #include "usbd_cdc.h" #include "usbd_cdc_if.h" @@ -31,7 +34,7 @@ void serialEventUSB() __attribute__((weak)); void USBSerial::begin(void) { - CDC_init(); + USBDevice.begin(); } void USBSerial::begin(uint32_t /* baud_count */) @@ -48,7 +51,7 @@ void USBSerial::begin(uint32_t /* baud_count */, uint8_t /* config */) void USBSerial::end() { - CDC_deInit(); + USBDevice.end(); } int USBSerial::availableForWrite() diff --git a/cores/arduino/USBSerial.h b/cores/arduino/USBSerial.h index 1628eef358..6ff78af907 100644 --- a/cores/arduino/USBSerial.h +++ b/cores/arduino/USBSerial.h @@ -19,9 +19,11 @@ #ifndef _USBSERIAL_H_ #define _USBSERIAL_H_ -#if defined (USBCON) && defined(USBD_USE_CDC) -#include "Stream.h" +#include "usbd_ep_conf.h" + +#if defined (USBCON) && defined(USBD_USE_CDC_CLASS) #include "usbd_core.h" +#include "Stream.h" //================================================================================ // Serial over CDC diff --git a/cores/arduino/stm32/usb/cdc/cdc_queue.c b/cores/arduino/stm32/usb/cdc/cdc_queue.c index 2d2330c195..3209341d42 100644 --- a/cores/arduino/stm32/usb/cdc/cdc_queue.c +++ b/cores/arduino/stm32/usb/cdc/cdc_queue.c @@ -35,8 +35,10 @@ ****************************************************************************** */ +#include "usbd_ep_conf.h" + #ifdef USBCON -#ifdef USBD_USE_CDC +#ifdef USBD_USE_CDC_CLASS #include "cdc_queue.h" diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc.c b/cores/arduino/stm32/usb/cdc/usbd_cdc.c index 9ee0d7885a..f76e248bb4 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.c @@ -50,8 +50,10 @@ ****************************************************************************** */ +#include "usbd_ep_conf.h" + #ifdef USBCON -#ifdef USBD_USE_CDC +#ifdef USBD_USE_CDC_CLASS /* Includes ------------------------------------------------------------------*/ #include "usbd_cdc.h" @@ -108,7 +110,7 @@ static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length); static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length); static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length); static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length); -uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(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 = { @@ -402,6 +404,15 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] 0x00 /* bInterval */ }; + + +USBD_CDC_HandleTypeDef cdc_handle_dat; +USBD_CDC_HandleTypeDef *cdc_handle = &cdc_handle_dat; + +USBD_CDC_ItfTypeDef *cdc_itf = NULL; /* TODO */ + +int cdcInitialized; + /** * @} */ @@ -417,19 +428,13 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] * @param cfgidx: Configuration index * @retval status */ -static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { UNUSED(cfgidx); - USBD_CDC_HandleTypeDef *hcdc; - hcdc = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef)); + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; - if (hcdc == NULL) { - pdev->pClassData = NULL; - return (uint8_t)USBD_EMEM; - } - - pdev->pClassData = (void *)hcdc; + pdev->pClassData = &cdcInitialized; if (pdev->dev_speed == USBD_SPEED_HIGH) { /* Open EP IN */ @@ -468,7 +473,7 @@ static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U; /* Init physical Interface components */ - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init(); + cdc_itf->Init(); /* Init Xfer states */ hcdc->TxState = 0U; @@ -494,7 +499,7 @@ static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) * @param cfgidx: Configuration index * @retval status */ -static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { UNUSED(cfgidx); uint8_t ret = 0U; @@ -514,8 +519,12 @@ static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) /* DeInit physical Interface components */ if (pdev->pClassData != NULL) { - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->DeInit(); - (void)USBD_free(pdev->pClassData); + /* DeInit physical Interface components */ + cdc_itf->DeInit(); + } + + if (pdev->pClassData == &cdcInitialized) { + // only mark as uninitialised if we own the initialisation pdev->pClassData = NULL; } @@ -529,10 +538,10 @@ static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) * @param req: usb requests * @retval status */ -static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, - USBD_SetupReqTypedef *req) +static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; uint8_t ifalt = 0U; uint16_t status_info = 0U; USBD_StatusTypeDef ret = USBD_OK; @@ -541,9 +550,9 @@ static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, case USB_REQ_TYPE_CLASS: if (req->wLength != 0U) { if ((req->bmRequest & 0x80U) != 0U) { - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, - (uint8_t *)hcdc->data, - req->wLength); + cdc_itf->Control(req->bRequest, + (uint8_t *)hcdc->data, + req->wLength); (void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, req->wLength); } else { @@ -553,8 +562,8 @@ static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, req->wLength); } } else { - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, - (uint8_t *)req, 0U); + cdc_itf->Control(req->bRequest, + (uint8_t *)req, 0U); } break; @@ -611,17 +620,18 @@ static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, * @param epnum: endpoint number * @retval status */ -static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { - USBD_CDC_HandleTypeDef *hcdc; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; PCD_HandleTypeDef *hpcd = pdev->pData; + USBD_CDC_ItfTypeDef *ctrl = cdc_itf; if (pdev->pClassData == NULL) { return (uint8_t)USBD_FAIL; } - hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; - if ((pdev->ep_in[epnum].total_length > 0U) && ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) { + if ((pdev->ep_in[epnum].total_length > 0U) && + ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) { /* Update the packet total length */ pdev->ep_in[epnum].total_length = 0U; @@ -629,7 +639,7 @@ static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); } else { hcdc->TxState = 0U; - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum); + ctrl->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum); } return (uint8_t)USBD_OK; @@ -642,10 +652,9 @@ static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) * @param epnum: endpoint number * @retval status */ -static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; - + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; if (pdev->pClassData == NULL) { return (uint8_t)USBD_FAIL; } @@ -656,7 +665,7 @@ static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) /* USB data will be immediately processed, this allow next USB traffic being NAKed till the end of the application Xfer */ - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + cdc_itf->Receive(hcdc->RxBuffer, &hcdc->RxLength); return (uint8_t)USBD_OK; } @@ -667,14 +676,14 @@ static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) * @param pdev: device instance * @retval status */ -static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) +static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; - if ((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFFU)) { - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(hcdc->CmdOpCode, - (uint8_t *)hcdc->data, - (uint16_t)hcdc->CmdLength); + if ((hcdc->CmdOpCode != 0xFFU)) { + cdc_itf->Control(hcdc->CmdOpCode, + (uint8_t *)hcdc->data, + (uint16_t)hcdc->CmdLength); hcdc->CmdOpCode = 0xFFU; } @@ -689,7 +698,7 @@ static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) * @param length : pointer data length * @retval pointer to descriptor buffer */ -static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length) +static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length) { *length = (uint16_t)sizeof(USBD_CDC_CfgFSDesc); @@ -703,7 +712,7 @@ static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length) * @param length : pointer data length * @retval pointer to descriptor buffer */ -static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length) +static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length) { *length = (uint16_t)sizeof(USBD_CDC_CfgHSDesc); @@ -717,7 +726,7 @@ static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length) * @param length : pointer data length * @retval pointer to descriptor buffer */ -static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length) +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length) { *length = (uint16_t)sizeof(USBD_CDC_OtherSpeedCfgDesc); @@ -730,7 +739,7 @@ static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length) * @param length : pointer data length * @retval pointer to descriptor buffer */ -uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) { *length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc); @@ -743,14 +752,14 @@ uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) * @param fops: CD Interface callback * @retval status */ -uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, - USBD_CDC_ItfTypeDef *fops) +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops) { if (fops == NULL) { return (uint8_t)USBD_FAIL; } - pdev->pUserData = fops; + cdc_itf = fops; return (uint8_t)USBD_OK; } @@ -761,10 +770,10 @@ uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, * @param pbuff: Tx Buffer * @retval status */ -uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, - uint8_t *pbuff, uint32_t length) +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, uint32_t length) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; hcdc->TxBuffer = pbuff; hcdc->TxLength = length; @@ -779,9 +788,9 @@ uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, * @param pbuff: Rx Buffer * @retval status */ -uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) +uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; hcdc->RxBuffer = pbuff; @@ -794,9 +803,9 @@ uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) * @param pdev: device instance * @retval status */ -uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; USBD_StatusTypeDef ret = USBD_BUSY; if (pdev->pClassData == NULL) { @@ -826,9 +835,9 @@ uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) * @param pdev: device instance * @retval status */ -uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) { - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; if (pdev->pClassData == NULL) { return (uint8_t)USBD_FAIL; @@ -859,6 +868,6 @@ uint8_t USBD_CDC_ClearBuffer(USBD_HandleTypeDef *pdev) } } -#endif /* USBD_USE_CDC */ +#endif /* USBD_USE_CDC_CLASS */ #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 5395708c06..5a9bce8606 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc.h @@ -38,6 +38,7 @@ extern "C" { * @{ */ + /** @defgroup usbd_cdc_Exported_Defines * @{ */ @@ -126,8 +127,13 @@ typedef struct { * @{ */ + extern USBD_ClassTypeDef USBD_CDC; -#define USBD_CDC_CLASS &USBD_CDC + +extern USBD_CDC_HandleTypeDef *cdc_handle; + +extern USBD_CDC_ItfTypeDef *cdc_itf; + /** * @} */ @@ -135,16 +141,17 @@ extern USBD_ClassTypeDef USBD_CDC; /** @defgroup USB_CORE_Exported_Functions * @{ */ -uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, - USBD_CDC_ItfTypeDef *fops); +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops); + +uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, + uint32_t length); -uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, - uint32_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); +uint8_t USBD_CDC_ClearBuffer(USBD_HandleTypeDef *pdev); -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); /** * @} */ diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index c09675f95e..6b731641b4 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -17,8 +17,10 @@ ****************************************************************************** */ +#include "usbd_ep_conf.h" + #ifdef USBCON -#ifdef USBD_USE_CDC +#ifdef USBD_USE_CDC_CLASS /* Includes ------------------------------------------------------------------*/ #include "usbd_desc.h" @@ -44,9 +46,7 @@ /* USBD_CDC Private Variables */ /* USB Device Core CDC handle declaration */ -USBD_HandleTypeDef hUSBD_Device_CDC; - -static bool CDC_initialized = false; +USBD_HandleTypeDef *hUSBD_Device_CDC; /* Received Data over USB are stored in this buffer */ CDC_TransmitQueue_TypeDef TransmitQueue; @@ -98,7 +98,7 @@ static int8_t USBD_CDC_Init(void) CDC_TransmitQueue_Init(&TransmitQueue); CDC_ReceiveQueue_Init(&ReceiveQueue); receivePended = true; - USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue)); + USBD_CDC_SetRxBuffer(hUSBD_Device_CDC, CDC_ReceiveQueue_ReserveBlock(&ReceiveQueue)); return ((int8_t)USBD_OK); } @@ -235,7 +235,7 @@ static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) receivePended = false; /* If enough space in the queue for a full buffer then continue receive */ if (!CDC_resume_receive()) { - USBD_CDC_ClearBuffer(&hUSBD_Device_CDC); + USBD_CDC_ClearBuffer(hUSBD_Device_CDC); } return ((int8_t)USBD_OK); } @@ -264,34 +264,6 @@ static int8_t USBD_CDC_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) return ((int8_t)USBD_OK); } -void CDC_init(void) -{ - if (!CDC_initialized) { - /* Init Device Library */ - if (USBD_Init(&hUSBD_Device_CDC, &USBD_Desc, 0) == USBD_OK) { - /* Add Supported Class */ - if (USBD_RegisterClass(&hUSBD_Device_CDC, USBD_CDC_CLASS) == USBD_OK) { - /* Add CDC Interface Class */ - if (USBD_CDC_RegisterInterface(&hUSBD_Device_CDC, &USBD_CDC_fops) == USBD_OK) { - /* Start Device Process */ - USBD_Start(&hUSBD_Device_CDC); - CDC_initialized = true; - } - } - } - } -} - -void CDC_deInit(void) -{ - if (CDC_initialized) { - USBD_Stop(&hUSBD_Device_CDC); - USBD_CDC_DeInit(); - USBD_DeInit(&hUSBD_Device_CDC); - CDC_initialized = false; - } -} - bool CDC_connected() { /* Save the transmitStart value in a local variable to avoid twice reading - fix #478 */ @@ -299,16 +271,16 @@ bool CDC_connected() if (transmitTime) { transmitTime = HAL_GetTick() - transmitTime; } - return ((hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED) - && (transmitTime < USB_CDC_TRANSMIT_TIMEOUT) - && lineState); + return hUSBD_Device_CDC->dev_state == USBD_STATE_CONFIGURED + && transmitTime < USB_CDC_TRANSMIT_TIMEOUT + && lineState; } void CDC_continue_transmit(void) { uint16_t size; uint8_t *buffer; - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *) hUSBD_Device_CDC.pClassData; + USBD_CDC_HandleTypeDef *hcdc = cdc_handle; /* * TS: This method can be called both in the main thread * (via USBSerial::write) and in the IRQ stream (via USBD_CDC_TransmistCplt), @@ -321,12 +293,12 @@ void CDC_continue_transmit(void) buffer = CDC_TransmitQueue_ReadBlock(&TransmitQueue, &size); if (size > 0) { transmitStart = HAL_GetTick(); - USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, buffer, size); + 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); + USBD_CDC_TransmitPacket(hUSBD_Device_CDC); } } } @@ -342,8 +314,8 @@ bool CDC_resume_receive(void) if (block != NULL) { receivePended = true; /* Set new buffer */ - USBD_CDC_SetRxBuffer(&hUSBD_Device_CDC, block); - USBD_CDC_ReceivePacket(&hUSBD_Device_CDC); + USBD_CDC_SetRxBuffer(hUSBD_Device_CDC, block); + USBD_CDC_ReceivePacket(hUSBD_Device_CDC); return true; } } diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index b415ac16de..1f2e311471 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -22,7 +22,7 @@ #define __USBD_CDC_IF_H #ifdef USBCON -#ifdef USBD_USE_CDC +#ifdef USBD_USE_CDC_CLASS #ifdef __cplusplus extern "C" { @@ -39,6 +39,7 @@ extern "C" { /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ +extern USBD_HandleTypeDef *hUSBD_Device_CDC; extern USBD_CDC_ItfTypeDef USBD_CDC_fops; extern CDC_TransmitQueue_TypeDef TransmitQueue; extern CDC_ReceiveQueue_TypeDef ReceiveQueue; @@ -48,8 +49,6 @@ extern CDC_ReceiveQueue_TypeDef ReceiveQueue; /* Exported functions ------------------------------------------------------- */ void CDC_continue_transmit(void); bool CDC_resume_receive(void); -void CDC_init(void); -void CDC_deInit(void); bool CDC_connected(void); #ifdef __cplusplus diff --git a/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.cpp b/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.cpp new file mode 100644 index 0000000000..d846a4a965 --- /dev/null +++ b/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.cpp @@ -0,0 +1,514 @@ +/** + ****************************************************************************** + * @file usbd_template.c + * @author MCD Application Team + * @brief This file provides the HID core functions. + * + * @verbatim + * + * =================================================================== + * COMPOSITE Class Description + * =================================================================== + * + * + * + * + * + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_CDC_MSC + +#include "usbd_cdc_msc.h" +#include "usbd_ctlreq.h" + +static uint8_t USBD_COMPOSITE_Init(USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_COMPOSITE_DeInit(USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_COMPOSITE_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req); + +static uint8_t *USBD_COMPOSITE_GetHSCfgDesc(uint16_t *length); + +static uint8_t *USBD_COMPOSITE_GetFSCfgDesc(uint16_t *length); + +static uint8_t *USBD_COMPOSITE_GetOtherSpeedCfgDesc(uint16_t *length); + +static uint8_t *USBD_COMPOSITE_GetDeviceQualifierDesc(uint16_t *length); + +static uint8_t USBD_COMPOSITE_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t USBD_COMPOSITE_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t USBD_COMPOSITE_EP0_RxReady(USBD_HandleTypeDef *pdev); + + +USBD_ClassTypeDef USBD_CDC_MSC = { + USBD_COMPOSITE_Init, + USBD_COMPOSITE_DeInit, + USBD_COMPOSITE_Setup, + nullptr, + USBD_COMPOSITE_EP0_RxReady, + USBD_COMPOSITE_DataIn, + USBD_COMPOSITE_DataOut, + nullptr, + nullptr, + nullptr, + USBD_COMPOSITE_GetHSCfgDesc, + USBD_COMPOSITE_GetFSCfgDesc, + USBD_COMPOSITE_GetOtherSpeedCfgDesc, + USBD_COMPOSITE_GetDeviceQualifierDesc, +}; + + +#define EP_ATTR_BULK 0x02 +#define EP_ATTR_INTERRUPT 0x03 + +#define IF_CLASS_COMM 0x02 +#define IF_CLASS_CDC 0x0A +#define IF_CLASS_MSC 0x08 + +#define IF_SUBCLASS_NONE 0x00 +#define IF_SUBCLASS_ACM 0x02 +#define IF_SUBCLASS_SCSI_TRANSPARENT 0x06 + +#define ENDPOINT_DESCRIPTOR(_EP_ADDR, _ATTR, _PACKET_SIZE, _BINTERVAL) \ + 0x07, /* bLength: Endpoint Descriptor size */ \ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ \ + _EP_ADDR, /* bEndpointAddress */ \ + _ATTR, /* bmAttributes: Interrupt */ \ + LOBYTE(_PACKET_SIZE), /* wMaxPacketSize: */ \ + HIBYTE(_PACKET_SIZE), \ + _BINTERVAL /* bInterval: */ + + +/* ACM Interface Descriptor */ +#define INTERFACE_DESCRIPTOR(_IF_NUM, _EP_COUNT, _CLASS, _SUBCLASS, _PROT) \ + 0x09, /* bLength: Interface Descriptor size */ \ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ \ + /* Interface descriptor type */ \ + _IF_NUM, /* bInterfaceNumber: Number of Interface */ \ + 0x00, /* bAlternateSetting: Alternate setting */ \ + _EP_COUNT, /* bNumEndpoints: One endpoints used */ \ + _CLASS, /* bInterfaceClass: Communication Interface Class */ \ + _SUBCLASS, /* bInterfaceSubClass: Abstract Control Model */ \ + _PROT, /* bInterfaceProtocol: Common AT commands */ \ + 0x05 /* iInterface: */ + + + +#define USB_DESC_TYPE_INTERFACE_ASSOC_DESC 0x0B + +#define CONFIGURATION_DESCRIPTOR() \ + 0x09, /* bLength: Configuation Descriptor size */ \ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ \ + USB_CDC_MSC_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 */ + +/******** IAD should be positioned just before the CDC interfaces ****** + IAD to associate the two CDC interfaces */ +#define IAD_DESCRIPTOR() \ + 0x08, /* bLength: Interface Descriptor size */ \ + USB_DESC_TYPE_INTERFACE_ASSOC_DESC, /* bDescriptorType: Interface */ \ + 0x00, /* bFirstInterface */ \ + 0x02, /* bInterfaceCount */ \ + 0x02, /* bFunctionClass */ \ + 0x02, /* bFunctionSubClass */ \ + 0x01, /* bFunctionProtocol */ \ + 0x04 /* iFunction (Index of string descriptor describing this function) */ +/* 08 */ + +/* ACM Interface Descriptor */ +#define ACM_INTERFACE_DESCRIPTOR() INTERFACE_DESCRIPTOR(CDC_ACM_INTERFACE, 0x01, IF_CLASS_COMM, IF_SUBCLASS_ACM, 0x01) + +/* Header Functional Descriptor */ +#define ACM_HEADER_FUNCTIONAL_DESCRIPTOR() \ + 0x05, /* bLength: Endpoint Descriptor size */ \ + 0x24, /* bDescriptorType: CS_INTERFACE */ \ + 0x00, /* bDescriptorSubtype: Header Func Desc */ \ + 0x10, /* bcdCDC: spec release number */ \ + 0x01 + +/* ACM Call Management Functional Descriptor */ +#define ACM_CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR() \ + 0x05, /* bFunctionLength */ \ + 0x24, /* bDescriptorType: CS_INTERFACE */ \ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ \ + 0x00, /* bmCapabilities: D0+D1 */ \ + CDC_COM_INTERFACE /* bDataInterface: 1 */ \ + +/* ACM Functional Descriptor */ +#define ACM_FUNCTIONAL_DESCRIPTOR() \ + 0x04, /* bFunctionLength */ \ + 0x24, /* bDescriptorType: CS_INTERFACE */ \ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ \ + 0x02 /* bmCapabilities */ + +#define ACM_UNION_FUNCTIONAL_DESCRIPTOR() \ + 0x05, /* bFunctionLength */ \ + 0x24, /* bDescriptorType: CS_INTERFACE */ \ + 0x06, /* bDescriptorSubtype: Union func desc */ \ + CDC_ACM_INTERFACE, /* bMasterInterface: Communication class interface */ \ + CDC_COM_INTERFACE /* bSlaveInterface0: Data Class Interface */ + +#define ACM_EP_DESCRIPTOR(_BINTERVAL) ENDPOINT_DESCRIPTOR(CDC_CMD_EP, EP_ATTR_INTERRUPT, CDC_CMD_PACKET_SIZE, _BINTERVAL) + +#define CDC_INTERFACE_DESCRIPTOR() INTERFACE_DESCRIPTOR(CDC_COM_INTERFACE, 0x02, IF_CLASS_CDC, IF_SUBCLASS_NONE, 0x00) +#define CDC_EP_OUT_DESCRIPTOR(_PACKET_SIZE) ENDPOINT_DESCRIPTOR(CDC_OUT_EP, EP_ATTR_BULK, _PACKET_SIZE, 0x00) +#define CDC_EP_IN_DESCRIPTOR(_PACKET_SIZE) ENDPOINT_DESCRIPTOR(CDC_IN_EP, EP_ATTR_BULK, _PACKET_SIZE, 0x00) + +#define MSC_INTERFACE_DESCRIPTOR() INTERFACE_DESCRIPTOR(MSC_INTERFACE, 0x02, IF_CLASS_MSC, IF_SUBCLASS_SCSI_TRANSPARENT, 0x50) +#define MSC_EP_IN_DESCRIPTOR(_PACKET_SIZE) ENDPOINT_DESCRIPTOR(MSC_EPIN_ADDR, EP_ATTR_BULK, _PACKET_SIZE, 0x00) +#define MSC_EP_OUT_DESCRIPTOR(_PACKET_SIZE) ENDPOINT_DESCRIPTOR(MSC_EPOUT_ADDR, EP_ATTR_BULK, _PACKET_SIZE, 0x00) + + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif + + +/* USB COMPOSITE device Configuration Descriptor */ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +static uint8_t USBD_COMPOSITE_HSCfgDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] = { + CONFIGURATION_DESCRIPTOR(), + IAD_DESCRIPTOR(), + + ACM_INTERFACE_DESCRIPTOR(), + ACM_HEADER_FUNCTIONAL_DESCRIPTOR(), + ACM_CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR(), + ACM_FUNCTIONAL_DESCRIPTOR(), + ACM_UNION_FUNCTIONAL_DESCRIPTOR(), + ACM_EP_DESCRIPTOR(CDC_HS_BINTERVAL), + + CDC_INTERFACE_DESCRIPTOR(), + CDC_EP_OUT_DESCRIPTOR(CDC_DATA_HS_MAX_PACKET_SIZE), + CDC_EP_IN_DESCRIPTOR(CDC_DATA_HS_MAX_PACKET_SIZE), + + MSC_INTERFACE_DESCRIPTOR(), + MSC_EP_IN_DESCRIPTOR(MSC_MAX_HS_PACKET), + MSC_EP_OUT_DESCRIPTOR(MSC_MAX_HS_PACKET) +}; + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +/* USB COMPOSITE device Configuration Descriptor */ +static uint8_t USBD_COMPOSITE_FSCfgDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] = { + CONFIGURATION_DESCRIPTOR(), + IAD_DESCRIPTOR(), + + ACM_INTERFACE_DESCRIPTOR(), + ACM_HEADER_FUNCTIONAL_DESCRIPTOR(), + ACM_CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR(), + ACM_FUNCTIONAL_DESCRIPTOR(), + ACM_UNION_FUNCTIONAL_DESCRIPTOR(), + ACM_EP_DESCRIPTOR(CDC_FS_BINTERVAL), + + CDC_INTERFACE_DESCRIPTOR(), + CDC_EP_OUT_DESCRIPTOR(CDC_DATA_FS_MAX_PACKET_SIZE), + CDC_EP_IN_DESCRIPTOR(CDC_DATA_FS_MAX_PACKET_SIZE), + + MSC_INTERFACE_DESCRIPTOR(), + MSC_EP_IN_DESCRIPTOR(MSC_MAX_FS_PACKET), + MSC_EP_OUT_DESCRIPTOR(MSC_MAX_FS_PACKET) +}; + + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +/* USB COMPOSITE device Configuration Descriptor */ +static uint8_t USBD_COMPOSITE_OtherSpeedCfgDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] = { + CONFIGURATION_DESCRIPTOR(), + IAD_DESCRIPTOR(), + + ACM_INTERFACE_DESCRIPTOR(), + ACM_HEADER_FUNCTIONAL_DESCRIPTOR(), + ACM_CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR(), + ACM_FUNCTIONAL_DESCRIPTOR(), + ACM_UNION_FUNCTIONAL_DESCRIPTOR(), + ACM_EP_DESCRIPTOR(CDC_FS_BINTERVAL), + + CDC_INTERFACE_DESCRIPTOR(), + CDC_EP_OUT_DESCRIPTOR(CDC_DATA_FS_MAX_PACKET_SIZE), + CDC_EP_IN_DESCRIPTOR(CDC_DATA_FS_MAX_PACKET_SIZE), + + MSC_INTERFACE_DESCRIPTOR(), + MSC_EP_IN_DESCRIPTOR(MSC_MAX_FS_PACKET), + MSC_EP_OUT_DESCRIPTOR(MSC_MAX_FS_PACKET) +}; + + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +/* USB Standard Device Descriptor */ +static uint8_t USBD_COMPOSITE_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +int cdcMscInitialised; + +/** + * @brief USBD_COMPOSITE_Init + * Initialize the COMPOSITE interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_COMPOSITE_Init(USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + USBD_MSC.Init(pdev, cfgidx); + + USBD_CDC.Init(pdev, cfgidx); + + pdev->pClassData = &cdcMscInitialised; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_COMPOSITE_Init + * DeInitialize the COMPOSITE layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_COMPOSITE_DeInit(USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + USBD_MSC.DeInit(pdev, cfgidx); + + USBD_CDC.DeInit(pdev, cfgidx); + + if (pdev->pClassData == &cdcMscInitialised) { + pdev->pClassData = nullptr; + } + + return USBD_OK; +} + +/** + * @brief USBD_COMPOSITE_Setup + * Handle the COMPOSITE specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_COMPOSITE_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { + case USB_REQ_RECIPIENT_INTERFACE: + switch (req->wIndex) { + case CDC_ACM_INTERFACE: + case CDC_COM_INTERFACE: + return USBD_CDC.Setup(pdev, req); + break; + + case MSC_INTERFACE: + return USBD_MSC.Setup(pdev, req); + break; + + // invalid interface + default: + return USBD_FAIL; + } + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + switch (req->wIndex) { + case CDC_IN_EP: + case CDC_OUT_EP: + case CDC_CMD_EP: + return USBD_CDC.Setup(pdev, req); + + case MSC_EPIN_ADDR: + case MSC_EPOUT_ADDR: + return USBD_MSC.Setup(pdev, req); + + // invalid endpoint + default: + return USBD_FAIL; + } + break; + + default: + break; + } + + return USBD_OK; +} + + +/** + * @brief USBD_COMPOSITE_GetHSCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_COMPOSITE_GetHSCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_COMPOSITE_HSCfgDesc); + return USBD_COMPOSITE_HSCfgDesc; +} + +/** + * @brief USBD_COMPOSITE_GetFSCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_COMPOSITE_GetFSCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_COMPOSITE_FSCfgDesc); + return USBD_COMPOSITE_FSCfgDesc; +} + +/** + * @brief USBD_COMPOSITE_GetOtherSpeedCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_COMPOSITE_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = sizeof(USBD_COMPOSITE_OtherSpeedCfgDesc); + return USBD_COMPOSITE_OtherSpeedCfgDesc; +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_COMPOSITE_DeviceQualifierDescriptor(uint16_t *length) +{ + *length = sizeof(USBD_COMPOSITE_DeviceQualifierDesc); + return USBD_COMPOSITE_DeviceQualifierDesc; +} + + +/** + * @brief USBD_COMPOSITE_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_COMPOSITE_DataIn(USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + switch (epnum) { + case CDC_IN_EP: + case CDC_CMD_EP: + case CDC_OUT_EP: + return USBD_CDC.DataIn(pdev, epnum); + + case MSC_EPIN_ADDR: + case MSC_EPOUT_ADDR: + return USBD_MSC.DataIn(pdev, epnum); + + // invalid endpoint + default: + return USBD_FAIL; + } +} + +/** + * @brief USBD_COMPOSITE_EP0_RxReady + * handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_COMPOSITE_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + // only needed by CDC + return USBD_CDC.EP0_RxReady(pdev); +} + +/** + * @brief USBD_COMPOSITE_DataOut + * handle data OUT Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_COMPOSITE_DataOut(USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + switch (epnum) { + case CDC_IN_EP: + case CDC_CMD_EP: + case CDC_OUT_EP: + return USBD_CDC.DataOut(pdev, epnum); + + case MSC_EPIN_ADDR: + case MSC_EPOUT_ADDR: + return USBD_MSC.DataOut(pdev, epnum); + + // invalid endpoint + default: + return USBD_FAIL; + } +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_COMPOSITE_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = sizeof(USBD_COMPOSITE_DeviceQualifierDesc); + return USBD_COMPOSITE_DeviceQualifierDesc; +} + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.h b/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.h new file mode 100644 index 0000000000..e8110535d8 --- /dev/null +++ b/cores/arduino/stm32/usb/cdc_msc/usbd_cdc_msc.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * @file usbd_cdc_msc_core.h + * @author MCD Application Team + * @version V1.2.1 + * @date 17-March-2018 + * @brief header file for the usbd_cdc_msc_core.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: + * + * + ****************************************************************************** + */ + +#ifndef __USB_CDC_MSC_CORE_H_ +#define __USB_CDC_MSC_CORE_H_ + +#include "usbd_cdc.h" +#include "usbd_msc.h" +#include "usbd_ioreq.h" + +#define CDC_ACM_INTERFACE 0x0 +#define CDC_COM_INTERFACE 0x1 +#define MSC_INTERFACE 0x2 + +#define USB_CDC_MSC_CONFIG_DESC_SIZ (USB_CDC_CONFIG_DESC_SIZ - 9 + 8 + USB_MSC_CONFIG_DESC_SIZ) + +extern USBD_ClassTypeDef USBD_CDC_MSC; + +#endif /* __USB_CDC_MSC_CORE_H_ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc.c b/cores/arduino/stm32/usb/msc/usbd_msc.c new file mode 100644 index 0000000000..742d747c30 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc.c @@ -0,0 +1,494 @@ +/** + ****************************************************************************** + * @file usbd_msc.c + * @author MCD Application Team + * @brief This file provides all the MSC core functions. + * + * @verbatim + * + * =================================================================== + * MSC Class Description + * =================================================================== + * This module manages the MSC class V1.0 following the "Universal + * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 + * Sep. 31, 1999". + * This driver implements the following aspects of the specification: + * - Bulk-Only Transport protocol + * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3)) + * + * @endverbatim + * + ****************************************************************************** + * @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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_MSC_CLASS + +#include "usbd_msc.h" +#include "usbd_msc_storage_if.h" + + +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); + +uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length); +uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length); +uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length); +uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length); + + +USBD_ClassTypeDef USBD_MSC = { + USBD_MSC_Init, + USBD_MSC_DeInit, + USBD_MSC_Setup, + NULL, /*EP0_TxSent*/ + NULL, /*EP0_RxReady*/ + USBD_MSC_DataIn, + USBD_MSC_DataOut, + NULL, /*SOF */ + NULL, + NULL, + USBD_MSC_GetHSCfgDesc, + USBD_MSC_GetFSCfgDesc, + USBD_MSC_GetOtherSpeedCfgDesc, + USBD_MSC_GetDeviceQualifierDescriptor, +}; + +/* USB Mass storage device Configuration Descriptor */ +/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ +__ALIGN_BEGIN static uint8_t USBD_MSC_CfgHSDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = { + + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CONFIG_DESC_SIZ, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent*/ + 0x50, /* nInterfaceProtocol */ + 0x05, /* iInterface: */ + /******************** 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(MSC_MAX_HS_PACKET), + HIBYTE(MSC_MAX_HS_PACKET), + 0x00, /*Polling interval in milliseconds */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(MSC_MAX_HS_PACKET), + HIBYTE(MSC_MAX_HS_PACKET), + 0x00 /*Polling interval in milliseconds*/ +}; + +/* USB Mass storage device Configuration Descriptor */ +/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ +__ALIGN_BEGIN static uint8_t USBD_MSC_CfgFSDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = { + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CONFIG_DESC_SIZ, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent*/ + 0x50, /* nInterfaceProtocol */ + 0x05, /* iInterface: */ + /******************** 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(MSC_MAX_FS_PACKET), + HIBYTE(MSC_MAX_FS_PACKET), + 0x00, /*Polling interval in milliseconds */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(MSC_MAX_FS_PACKET), + HIBYTE(MSC_MAX_FS_PACKET), + 0x00 /*Polling interval in milliseconds*/ +}; + +__ALIGN_BEGIN static uint8_t USBD_MSC_OtherSpeedCfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = { + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, + USB_MSC_CONFIG_DESC_SIZ, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent command set*/ + 0x50, /* nInterfaceProtocol */ + 0x05, /* iInterface: */ + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + 0x40, + 0x00, + 0x00, /*Polling interval in milliseconds */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + 0x40, + 0x00, + 0x00 /*Polling interval in milliseconds*/ +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + MSC_MAX_FS_PACKET, + 0x01, + 0x00, +}; +/** + * @} + */ + +USBD_MSC_BOT_HandleTypeDef msc_handle_dat; +USBD_MSC_BOT_HandleTypeDef *msc_handle = &msc_handle_dat; + +USBD_StorageTypeDef *msc_storage = &USBD_MSC_fops; + +int mscInitialized; + +/** + * @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) +{ + UNUSED(cfgidx); + pdev->pClassData = &mscInitialized; + + if (pdev->dev_speed == USBD_SPEED_HIGH) { + /* Open EP OUT */ + (void)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 */ + (void)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 */ + (void)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 */ + (void)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; + } + + /* Init the BOT layer */ + MSC_BOT_Init(pdev); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_MSC_DeInit + * DeInitialize 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) +{ + UNUSED(cfgidx); + + /* Close MSC EPs */ + (void)USBD_LL_CloseEP(pdev, MSC_EPOUT_ADDR); + pdev->ep_out[MSC_EPOUT_ADDR & 0xFU].is_used = 0U; + + /* Close EP IN */ + (void)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); + + if (pdev->pClassData == &mscInitialized) { + // only mark as uninitialised if we own the initialisation + pdev->pClassData = NULL; + } + + return (uint8_t)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 = msc_handle; + uint8_t ret = USBD_OK; + uint16_t status_info = 0U; + + 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 == 0U) && (req->wLength == 1U) && + ((req->bmRequest & 0x80U) == 0x80U)) { + hmsc->max_lun = (uint32_t)msc_storage->GetMaxLun(); + (void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->max_lun, 1U); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case BOT_RESET: + if ((req->wValue == 0U) && (req->wLength == 0U) && + ((req->bmRequest & 0x80U) != 0x80U)) { + MSC_BOT_Reset(pdev); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + /* Interface & Endpoint request */ + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->interface, 1U); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + hmsc->interface = (uint8_t)(req->wValue); + } else { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + if (req->wValue == USB_FEATURE_EP_HALT) { + /* Flush the FIFO */ + (void)USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex); + + /* Handle BOT error */ + MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); + } + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** +* @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 (uint8_t)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 (uint8_t)USBD_OK; +} + +/** +* @brief USBD_MSC_GetHSCfgDesc +* return configuration descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_MSC_CfgHSDesc); + + return USBD_MSC_CfgHSDesc; +} + +/** +* @brief USBD_MSC_GetFSCfgDesc +* return configuration descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_MSC_CfgFSDesc); + + return USBD_MSC_CfgFSDesc; +} + +/** +* @brief USBD_MSC_GetOtherSpeedCfgDesc +* return other speed configuration descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_MSC_OtherSpeedCfgDesc); + + return USBD_MSC_OtherSpeedCfgDesc; +} +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_MSC_DeviceQualifierDesc); + + return USBD_MSC_DeviceQualifierDesc; +} + +/** +* @brief USBD_MSC_RegisterStorage +* @param fops: storage callback +* @retval status +*/ +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops) +{ + if (fops == NULL) { + return (uint8_t)USBD_FAIL; + } + + msc_storage = fops; + + return (uint8_t)USBD_OK; +} + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc.h b/cores/arduino/stm32/usb/msc/usbd_msc.h new file mode 100644 index 0000000000..a3001d570c --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc.h @@ -0,0 +1,100 @@ +/** + ****************************************************************************** + * @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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_H +#define __USBD_MSC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" + +/* MSC Class Config */ +#ifndef MSC_MEDIA_PACKET +#define MSC_MEDIA_PACKET 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 + +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); + uint8_t *pInquiry; + +} USBD_StorageTypeDef; + + +typedef struct { + uint32_t max_lun; + uint32_t interface; + uint8_t bot_state; + uint8_t bot_status; + uint32_t bot_data_length; + uint8_t bot_data[MSC_MEDIA_PACKET]; + USBD_MSC_BOT_CBWTypeDef cbw; + USBD_MSC_BOT_CSWTypeDef csw; + + USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH]; + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + uint8_t scsi_medium_state; + + 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 + +/* Handle */ +extern USBD_MSC_BOT_HandleTypeDef *msc_handle; +extern USBD_StorageTypeDef *msc_storage; + +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/usbd_msc_bot.c b/cores/arduino/stm32/usb/msc/usbd_msc_bot.c new file mode 100644 index 0000000000..d3338d2292 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_bot.c @@ -0,0 +1,301 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.c + * @author MCD Application Team + * @brief This file provides all the BOT protocol core 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_MSC_CLASS + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_bot.h" +#include "usbd_msc.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" + +static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev, uint8_t *pbuf, uint32_t len); +static void MSC_BOT_CBW_Decode(USBD_HandleTypeDef *pdev); +static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev); + + +/** +* @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 = msc_handle; + + hmsc->bot_state = USBD_BOT_IDLE; + hmsc->bot_status = USBD_BOT_STATUS_NORMAL; + + hmsc->scsi_sense_tail = 0U; + hmsc->scsi_sense_head = 0U; + hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED; + + msc_storage->Init(0U); + + (void)USBD_LL_FlushEP(pdev, MSC_EPOUT_ADDR); + (void)USBD_LL_FlushEP(pdev, MSC_EPIN_ADDR); + + /* Prapare EP to Receive First BOT Cmd */ + (void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, (uint8_t *)&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 = msc_handle; + + hmsc->bot_state = USBD_BOT_IDLE; + hmsc->bot_status = USBD_BOT_STATUS_RECOVERY; + + (void)USBD_LL_ClearStallEP(pdev, MSC_EPIN_ADDR); + (void)USBD_LL_ClearStallEP(pdev, MSC_EPOUT_ADDR); + + /* Prapare EP to Receive First BOT Cmd */ + (void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, (uint8_t *)&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 = msc_handle; + 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) +{ + UNUSED(epnum); + + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + 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) +{ + UNUSED(epnum); + + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + 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 = msc_handle; + + hmsc->csw.dTag = hmsc->cbw.dTag; + hmsc->csw.dDataResidue = hmsc->cbw.dDataLength; + + if ((USBD_LL_GetRxDataSize(pdev, MSC_EPOUT_ADDR) != USBD_BOT_CBW_LENGTH) || + (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE) || + (hmsc->cbw.bLUN > 1U) || (hmsc->cbw.bCBLength < 1U) || + (hmsc->cbw.bCBLength > 16U)) { + 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 > 0U) { + MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length); + } else if (hmsc->bot_data_length == 0U) { + 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, uint32_t len) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + uint32_t length = MIN(hmsc->cbw.dDataLength, len); + + hmsc->csw.dDataResidue -= len; + hmsc->csw.bStatus = USBD_CSW_CMD_PASSED; + hmsc->bot_state = USBD_BOT_SEND_DATA; + + (void)USBD_LL_Transmit(pdev, MSC_EPIN_ADDR, pbuf, length); +} + +/** +* @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 = msc_handle; + + hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE; + hmsc->csw.bStatus = CSW_Status; + hmsc->bot_state = USBD_BOT_IDLE; + + (void)USBD_LL_Transmit(pdev, MSC_EPIN_ADDR, (uint8_t *)&hmsc->csw, + USBD_BOT_CSW_LENGTH); + + /* Prepare EP to Receive next Cmd */ + (void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, (uint8_t *)&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 = msc_handle; + + if ((hmsc->cbw.bmFlags == 0U) && + (hmsc->cbw.dDataLength != 0U) && + (hmsc->bot_status == USBD_BOT_STATUS_NORMAL)) { + (void)USBD_LL_StallEP(pdev, MSC_EPOUT_ADDR); + } + + (void)USBD_LL_StallEP(pdev, MSC_EPIN_ADDR); + + if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) { + (void)USBD_LL_StallEP(pdev, MSC_EPIN_ADDR); + (void)USBD_LL_StallEP(pdev, MSC_EPOUT_ADDR); + } +} + +/** +* @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 = msc_handle; + + if (hmsc->bot_status == USBD_BOT_STATUS_ERROR) { + /* Bad CBW Signature */ + (void)USBD_LL_StallEP(pdev, MSC_EPIN_ADDR); + (void)USBD_LL_StallEP(pdev, MSC_EPOUT_ADDR); + } else if (((epnum & 0x80U) == 0x80U) && (hmsc->bot_status != USBD_BOT_STATUS_RECOVERY)) { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_FAILED); + } else { + return; + } +} + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc_bot.h b/cores/arduino/stm32/usb/msc/usbd_msc_bot.h new file mode 100644 index 0000000000..de1af53223 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_bot.h @@ -0,0 +1,104 @@ +/** + ****************************************************************************** + * @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: + * 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" + +#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 + + +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; + +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/usbd_msc_data.c b/cores/arduino/stm32/usb/msc/usbd_msc_data.c new file mode 100644 index 0000000000..a2ae3c0f31 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_data.c @@ -0,0 +1,120 @@ +/** + ****************************************************************************** + * @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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_MSC_CLASS + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_data.h" + + +/* USB Mass storage Page 0 Inquiry Data */ +uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00] = { + 0x00, + 0x00, + 0x00, + (LENGTH_INQUIRY_PAGE00 - 4U), + 0x00, + 0x80 +}; + +/* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */ +uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80] = { + 0x00, + 0x80, + 0x00, + LENGTH_INQUIRY_PAGE80, + 0x20, /* Put Product Serial number */ + 0x20, + 0x20, + 0x20 +}; + +/* USB Mass storage sense 6 Data */ +uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN] = { + 0x22, + 0x00, + 0x00, + 0x00, + 0x08, + 0x12, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + + +/* USB Mass storage sense 10 Data */ +uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN] = { + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, + 0x12, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc_data.h b/cores/arduino/stm32/usb/msc/usbd_msc_data.h new file mode 100644 index 0000000000..24ab8cf1a2 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_data.h @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * @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: + * 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" + + +#define MODE_SENSE6_LEN 0x17U +#define MODE_SENSE10_LEN 0x1BU +#define LENGTH_INQUIRY_PAGE00 0x06U +#define LENGTH_INQUIRY_PAGE80 0x08U +#define LENGTH_FORMAT_CAPACITIES 0x14U + + +extern uint8_t MSC_Page00_Inquiry_Data[LENGTH_INQUIRY_PAGE00]; +extern uint8_t MSC_Page80_Inquiry_Data[LENGTH_INQUIRY_PAGE80]; +extern uint8_t MSC_Mode_Sense6_data[MODE_SENSE6_LEN]; +extern uint8_t MSC_Mode_Sense10_data[MODE_SENSE10_LEN]; + + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_DATA_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc_scsi.c b/cores/arduino/stm32/usb/msc/usbd_msc_scsi.c new file mode 100644 index 0000000000..269bc30ff4 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_scsi.c @@ -0,0 +1,953 @@ +/** + ****************************************************************************** + * @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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_MSC_CLASS + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc.h" +#include "usbd_msc_data.h" + + + +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_ReadCapacity16(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_AllowPreventRemovable(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_Write12(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_Read12(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); + +static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc, + uint8_t *pBuff, uint16_t length); + +/** +* @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) +{ + int8_t ret; + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + switch (cmd[0]) { + case SCSI_TEST_UNIT_READY: + ret = SCSI_TestUnitReady(pdev, lun, cmd); + break; + + case SCSI_REQUEST_SENSE: + ret = SCSI_RequestSense(pdev, lun, cmd); + break; + + case SCSI_INQUIRY: + ret = SCSI_Inquiry(pdev, lun, cmd); + break; + + case SCSI_START_STOP_UNIT: + ret = SCSI_StartStopUnit(pdev, lun, cmd); + break; + + case SCSI_ALLOW_MEDIUM_REMOVAL: + ret = SCSI_AllowPreventRemovable(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE6: + ret = SCSI_ModeSense6(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE10: + ret = SCSI_ModeSense10(pdev, lun, cmd); + break; + + case SCSI_READ_FORMAT_CAPACITIES: + ret = SCSI_ReadFormatCapacity(pdev, lun, cmd); + break; + + case SCSI_READ_CAPACITY10: + ret = SCSI_ReadCapacity10(pdev, lun, cmd); + break; + + case SCSI_READ_CAPACITY16: + ret = SCSI_ReadCapacity16(pdev, lun, cmd); + break; + + case SCSI_READ10: + ret = SCSI_Read10(pdev, lun, cmd); + break; + + case SCSI_READ12: + ret = SCSI_Read12(pdev, lun, cmd); + break; + + case SCSI_WRITE10: + ret = SCSI_Write10(pdev, lun, cmd); + break; + + case SCSI_WRITE12: + ret = SCSI_Write12(pdev, lun, cmd); + break; + + case SCSI_VERIFY10: + ret = SCSI_Verify10(pdev, lun, cmd); + break; + + default: + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + hmsc->bot_status = USBD_BOT_STATUS_ERROR; + ret = -1; + break; + } + + return ret; +} + + +/** +* @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) +{ + UNUSED(params); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + /* case 9 : Hi > D0 */ + if (hmsc->cbw.dDataLength != 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + + if (msc_storage->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 = msc_handle; + + if (hmsc->cbw.dDataLength == 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + if ((params[1] & 0x01U) != 0U) { + /* Evpd is set */ + if (params[2] == 0U) { + /* Request for Supported Vital Product Data Pages*/ + (void)SCSI_UpdateBotData(hmsc, MSC_Page00_Inquiry_Data, LENGTH_INQUIRY_PAGE00); + } else if (params[2] == 0x80U) { + /* Request for VPD page 0x80 Unit Serial Number */ + (void)SCSI_UpdateBotData(hmsc, MSC_Page80_Inquiry_Data, LENGTH_INQUIRY_PAGE80); + } else { + /* Request Not supported */ + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, + INVALID_FIELED_IN_COMMAND); + + return -1; + } + } else { + pPage = &msc_storage->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN]; + len = (uint16_t)pPage[4] + 5U; + + if (params[4] <= len) { + len = params[4]; + } + + (void)SCSI_UpdateBotData(hmsc, 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) +{ + UNUSED(params); + int8_t ret; + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + ret = msc_storage->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size); + + if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + 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_ReadCapacity16 +* Process Read Capacity 16 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + UNUSED(params); + uint8_t idx; + int8_t ret; + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + ret = msc_storage->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size); + + if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + hmsc->bot_data_length = ((uint32_t)params[10] << 24) | + ((uint32_t)params[11] << 16) | + ((uint32_t)params[12] << 8) | + (uint32_t)params[13]; + + for (idx = 0U; idx < hmsc->bot_data_length; idx++) { + hmsc->bot_data[idx] = 0U; + } + + hmsc->bot_data[4] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24); + hmsc->bot_data[5] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16); + hmsc->bot_data[6] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 8); + hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_nbr - 1U); + + hmsc->bot_data[8] = (uint8_t)(hmsc->scsi_blk_size >> 24); + hmsc->bot_data[9] = (uint8_t)(hmsc->scsi_blk_size >> 16); + hmsc->bot_data[10] = (uint8_t)(hmsc->scsi_blk_size >> 8); + hmsc->bot_data[11] = (uint8_t)(hmsc->scsi_blk_size); + + hmsc->bot_data_length = ((uint32_t)params[10] << 24) | + ((uint32_t)params[11] << 16) | + ((uint32_t)params[12] << 8) | + (uint32_t)params[13]; + + 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) +{ + UNUSED(params); + uint16_t blk_size; + uint32_t blk_nbr; + uint16_t i; + int8_t ret; + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + ret = msc_storage->GetCapacity(lun, &blk_nbr, &blk_size); + + if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + for (i = 0U; i < 12U ; i++) { + hmsc->bot_data[i] = 0U; + } + + 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) +{ + UNUSED(lun); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + uint16_t len = MODE_SENSE6_LEN; + + if (params[4] <= len) { + len = params[4]; + } + + (void)SCSI_UpdateBotData(hmsc, 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) +{ + UNUSED(lun); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + uint16_t len = MODE_SENSE10_LEN; + + if (params[8] <= len) { + len = params[8]; + } + + (void)SCSI_UpdateBotData(hmsc, 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) +{ + UNUSED(lun); + uint8_t i; + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + if (hmsc->cbw.dDataLength == 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + 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] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].Skey; + hmsc->bot_data[12] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC; + hmsc->bot_data[13] = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ; + 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 Code +* @retval none + +*/ +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC) +{ + UNUSED(lun); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey; + hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASC = ASC; + hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASCQ = 0U; + 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) +{ + UNUSED(lun); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + if ((hmsc->scsi_medium_state == SCSI_MEDIUM_LOCKED) && ((params[4] & 0x3U) == 2U)) { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; + } + + if ((params[4] & 0x3U) == 0x1U) { + /* START=1 */ + hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED; + } else if ((params[4] & 0x3U) == 0x2U) { + /* START=0 and LOEJ Load Eject=1 */ + hmsc->scsi_medium_state = SCSI_MEDIUM_EJECTED; + } else if ((params[4] & 0x3U) == 0x3U) { + /* START=1 and LOEJ Load Eject=1 */ + hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED; + } else { + /* .. */ + } + hmsc->bot_data_length = 0U; + + return 0; +} + + +/** +* @brief SCSI_AllowPreventRemovable +* Process Allow Prevent Removable medium command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + UNUSED(lun); + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + if (params[4] == 0U) { + hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED; + } else { + hmsc->scsi_medium_state = SCSI_MEDIUM_LOCKED; + } + + 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 = msc_handle; + + 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 (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + if (msc_storage->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 */ + } + + /* 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_state = USBD_BOT_DATA_IN; + } + hmsc->bot_data_length = MSC_MEDIA_PACKET; + + return SCSI_ProcessRead(pdev, lun); +} + + +/** +* @brief SCSI_Read12 +* Process Read12 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + + 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 (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + if (msc_storage->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[6] << 24) | + ((uint32_t)params[7] << 16) | + ((uint32_t)params[8] << 8) | + (uint32_t)params[9]; + + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + /* 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_state = USBD_BOT_DATA_IN; + } + 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 = msc_handle; + uint32_t len; + + if (hmsc->bot_state == USBD_BOT_IDLE) { + /* Idle */ + if (hmsc->cbw.dDataLength == 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + /* 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 (msc_storage->IsReady(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + /* Check If media is write-protected */ + if (msc_storage->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; + (void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } else { + /* Write Process ongoing */ + return SCSI_ProcessWrite(pdev, lun); + } + + return 0; +} + + +/** +* @brief SCSI_Write12 +* Process Write12 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = msc_handle; + uint32_t len; + + if (hmsc->bot_state == USBD_BOT_IDLE) { + /* Idle */ + if (hmsc->cbw.dDataLength == 0U) { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + /* 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 (msc_storage->IsReady(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + return -1; + } + + /* Check If media is write-protected */ + if (msc_storage->IsWriteProtected(lun) != 0) { + SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); + hmsc->bot_state = USBD_BOT_NO_DATA; + 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[6] << 24) | + ((uint32_t)params[7] << 16) | + ((uint32_t)params[8] << 8) | + (uint32_t)params[9]; + + /* 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; + (void)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 = msc_handle; + + 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 = msc_handle; + + 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 = msc_handle; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (msc_storage->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; + } + + (void)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 = msc_handle; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (msc_storage->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 */ + (void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } + + return 0; +} + + +/** +* @brief SCSI_UpdateBotData +* fill the requested Data to transmit buffer +* @param hmsc handler +* @param params: Data buffer +* @param length: Data length +* @retval status +*/ +static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc, + uint8_t *pBuff, uint16_t length) +{ + uint16_t len = length; + + hmsc->bot_data_length = len; + + while (len != 0U) { + len--; + hmsc->bot_data[len] = pBuff[len]; + } + + return 0; +} + + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc_scsi.h b/cores/arduino/stm32/usb/msc/usbd_msc_scsi.h new file mode 100644 index 0000000000..b39ad35c44 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_scsi.h @@ -0,0 +1,128 @@ +/** + ****************************************************************************** + * @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: + * 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" + +#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 + +#define SCSI_MEDIUM_UNLOCKED 0x00U +#define SCSI_MEDIUM_LOCKED 0x01U +#define SCSI_MEDIUM_EJECTED 0x02U + +typedef struct _SENSE_ITEM { + uint8_t Skey; + union { + struct _ASCs { + uint8_t ASC; + uint8_t ASCQ; + } b; + uint8_t ASC; + uint8_t *pData; + } w; +} USBD_SCSI_SenseTypeDef; + +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/msc/usbd_msc_storage_if.cpp b/cores/arduino/stm32/usb/msc/usbd_msc_storage_if.cpp new file mode 100644 index 0000000000..a614bfe288 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_storage_if.cpp @@ -0,0 +1,189 @@ +/** + ****************************************************************************** + * @file usbd_msc_storage_template.c + * @author MCD Application Team + * @brief Memory management 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +#include "usbd_ep_conf.h" + +#ifdef USBCON +#ifdef USBD_USE_MSC_CLASS + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +#include "USBMscHandler.h" +#include "usbd_msc_storage_if.h" + +uint8_t usbMscMaxLun = 0; +USBMscHandler **ppUsbMscHandlers = nullptr; + +int8_t STORAGE_Init(uint8_t lun); + +int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, + uint16_t *block_size); + +int8_t STORAGE_IsReady(uint8_t lun); + +int8_t STORAGE_IsWriteProtected(uint8_t lun); + +int8_t STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, + uint16_t blk_len); + +int8_t STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, + uint16_t blk_len); + +int8_t STORAGE_GetMaxLun(void); + +/* USB Mass storage Standard Inquiry Data */ +uint8_t STORAGE_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 USBD_MSC_fops = { + STORAGE_Init, + STORAGE_GetCapacity, + STORAGE_IsReady, + STORAGE_IsWriteProtected, + STORAGE_Read, + STORAGE_Write, + STORAGE_GetMaxLun, + STORAGE_Inquirydata, +}; + +#define HANDLER_LUN_CHECK \ + if (lun > usbMscMaxLun) { \ + return 1; \ + } + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the microSD card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_Init(uint8_t lun) +{ + HANDLER_LUN_CHECK + + return !ppUsbMscHandlers[lun]->Init(); +} + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the STORAGE card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) +{ + HANDLER_LUN_CHECK + + return !ppUsbMscHandlers[lun]->GetCapacity(block_num, block_size); +} + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the STORAGE card. +* Input : None. +* Output : None. +* Return : 0 if device is ready, otherwise not ready +*******************************************************************************/ +int8_t STORAGE_IsReady(uint8_t lun) +{ + HANDLER_LUN_CHECK + + return !ppUsbMscHandlers[lun]->IsReady(); +} + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the STORAGE card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_IsWriteProtected(uint8_t lun) +{ + HANDLER_LUN_CHECK + + return ppUsbMscHandlers[lun]->IsWriteProtected(); +} + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the STORAGE card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_Read(uint8_t lun, uint8_t *buf, + uint32_t blk_addr, uint16_t blk_len) +{ + HANDLER_LUN_CHECK + + return !ppUsbMscHandlers[lun]->Read(buf, blk_addr, blk_len); +} + +/******************************************************************************* +* Function Name : Write_Memory +* Description : Handle the Write operation to the STORAGE card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_Write(uint8_t lun, uint8_t *buf, + uint32_t blk_addr, uint16_t blk_len) +{ + HANDLER_LUN_CHECK + + return !ppUsbMscHandlers[lun]->Write(buf, blk_addr, blk_len); +} + +/******************************************************************************* +* Function Name : Write_Memory +* Description : Handle the Write operation to the STORAGE card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +int8_t STORAGE_GetMaxLun(void) +{ + return usbMscMaxLun; +} + +#endif /* USBD_USE_MSC_CLASS */ +#endif /* USBCON */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/msc/usbd_msc_storage_if.h b/cores/arduino/stm32/usb/msc/usbd_msc_storage_if.h new file mode 100644 index 0000000000..cddadecda0 --- /dev/null +++ b/cores/arduino/stm32/usb/msc/usbd_msc_storage_if.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * @file usbd_msc_storage.h + * @author MCD Application Team + * @brief Header file for the usbd_msc_storage.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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_STORAGE_H +#define __USBD_MSC_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usbd_msc.h" + +extern USBD_StorageTypeDef USBD_MSC_fops; + +#ifdef __cplusplus +#include "USBMscHandler.h" + +extern uint8_t usbMscMaxLun; +extern USBMscHandler **ppUsbMscHandlers; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_MSC_STORAGE_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 109f2f56f5..3094d3a331 100644 --- a/cores/arduino/stm32/usb/usbd_conf.c +++ b/cores/arduino/stm32/usb/usbd_conf.c @@ -514,13 +514,25 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) /* 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); + if (ep_def[i].ep_adress & 0xF0U) { + HAL_PCDEx_SetTxFiFo(&g_hpcd, ep_def[i].ep_adress & 0xF, ep_def[i].ep_size); + } } #else + uint32_t offset = PMA_BASE_OFFSET; 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); + ep_desc_t *pDesc = &ep_dep[i]; + uint32_t size = pDesc->ep_size; + uint32_t address = offset; + if (pDesc->ep_kind == PCD_DBL_BUF) { + address = address | ((address + size) << 16U); + size *= 2; + } + HAL_PCDEx_PMAConfig(&g_hpcd, pDesc->ep_adress, pDesc->ep_kind, address); + offset += size; } #endif /* USE_USB_HS */ + return USBD_OK; } diff --git a/cores/arduino/stm32/usb/usbd_conf.h b/cores/arduino/stm32/usb/usbd_conf.h index c1a4808380..01ef078aa3 100644 --- a/cores/arduino/stm32/usb/usbd_conf.h +++ b/cores/arduino/stm32/usb/usbd_conf.h @@ -40,6 +40,7 @@ extern "C" { #include #include + #if defined(USB_BASE) #if defined(STM32F1xx) diff --git a/cores/arduino/stm32/usb/usbd_desc.c b/cores/arduino/stm32/usb/usbd_desc.c index 229112ea5f..3d48f046ed 100644 --- a/cores/arduino/stm32/usb/usbd_desc.c +++ b/cores/arduino/stm32/usb/usbd_desc.c @@ -37,7 +37,7 @@ #define USBD_VID 0x0483 #if defined(USBD_USE_HID_COMPOSITE) #define USBD_PID 0x5711 - #elif defined(USBD_USE_CDC) + #elif defined(USBD_USE_CDC) || defined(USBD_USE_CDC_MSC) #define USBD_PID 0x5740 #endif #endif /* !USBD_PID && !USBD_VID */ @@ -70,7 +70,7 @@ #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) +#elif defined(USBD_USE_CDC) || defined(USBD_USE_CDC_MSC) #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 @@ -85,7 +85,7 @@ #define USBD_CLASS_INTERFACE_FS_STRING CONCATS(BOARD_NAME, "HID Interface") #endif /* USBD_USE_HID_COMPOSITE */ -#ifdef USBD_USE_CDC +#if defined(USBD_USE_CDC) || defined(USBD_USE_CDC_MSC) #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") @@ -129,81 +129,51 @@ USBD_DescriptorsTypeDef USBD_Desc = { #endif }; -#ifdef USBD_USE_HID_COMPOSITE -/* USB Standard Device Descriptor */ -__ALIGN_BEGIN uint8_t USBD_Class_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { - 0x12, /* bLength */ - USB_DESC_TYPE_DEVICE, /* bDescriptorType */ + +#define USB_CDC_CLASS_MULTI 0xEF +#define CDC_SUBCLASS_ACM 0x02 +#define CDC_PROTOCOL_V25TER 0x01 // Common AT commands + + #if ((USBD_LPM_ENABLED == 1) || (USBD_CLASS_BOS_ENABLED == 1)) - 0x01, /*bcdUSB */ /* changed to USB version 2.01 - in order to support BOS Desc */ + #define BCD_USB_FLAG 0x01 #else - 0x00, /* bcdUSB */ + #define BCD_USB_FLAG 0x00 +#endif + + +#define USBD_CLASS_DEVICE_DESCRIPTOR(_CLASS, _SUBCLASS, _PROTO) \ +__ALIGN_BEGIN uint8_t USBD_Class_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { \ + 0x12, /* bLength */ \ + USB_DESC_TYPE_DEVICE, /* bDescriptorType */ \ + BCD_USB_FLAG, /* bcdUSB */ \ + 0x02, \ + _CLASS, /* bDeviceClass */ \ + _SUBCLASS, /* bDeviceSubClass */ \ + _PROTO, /* bDeviceProtocol */ \ + 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, \ + 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 */ \ +} + +#ifdef USBD_USE_HID_COMPOSITE + USBD_CLASS_DEVICE_DESCRIPTOR(0x00, 0x00, 0x00); #endif - 0x02, - 0x00, /* bDeviceClass */ - 0x00, /* bDeviceSubClass */ - 0x00, /* bDeviceProtocol */ - 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, - 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 */ -#endif /* USBD_USE_HID_COMPOSITE */ #ifdef USBD_USE_CDC -/* USB Standard Device Descriptor */ -__ALIGN_BEGIN uint8_t USBD_Class_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { - 0x12, /* bLength */ - USB_DESC_TYPE_DEVICE, /* bDescriptorType */ -#if ((USBD_LPM_ENABLED == 1) || (USBD_CLASS_BOS_ENABLED == 1)) - 0x01, /*bcdUSB */ /* changed to USB version 2.01 - in order to support BOS Desc */ -#else - 0x00, /* bcdUSB */ + USBD_CLASS_DEVICE_DESCRIPTOR(0x02, 0x02, 0x00); #endif - 0x02, - 0x02, /* bDeviceClass */ - 0x02, /* bDeviceSubClass */ - 0x00, /* bDeviceProtocol */ - 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, - 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 */ -#endif /* USBD_USE_CDC */ -/* USB Device LPM BOS descriptor */ -#if (USBD_LPM_ENABLED == 1) -__ALIGN_BEGIN uint8_t USBD_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = { - 0x5, - USB_DESC_TYPE_BOS, - 0xC, - 0x0, - 0x1, /* 1 device capability */ - /* device capability */ - 0x7, - USB_DEVICE_CAPABITY_TYPE, - 0x2, - 0x6, /*LPM capability bit set */ - 0x0, - 0x0, - 0x0 -}; +#ifdef USBD_USE_CDC_MSC + USBD_CLASS_DEVICE_DESCRIPTOR(USB_CDC_CLASS_MULTI, CDC_SUBCLASS_ACM, CDC_PROTOCOL_V25TER); #endif /* USB Device Billboard BOS descriptor Template */ diff --git a/cores/arduino/stm32/usb/usbd_ep_conf.c b/cores/arduino/stm32/usb/usbd_ep_conf.c index 455afe5ecd..2e72855e5d 100644 --- a/cores/arduino/stm32/usb/usbd_ep_conf.c +++ b/cores/arduino/stm32/usb/usbd_ep_conf.c @@ -19,53 +19,86 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_ep_conf.h" -#ifdef USBD_USE_CDC -const ep_desc_t ep_def[] = { -#ifdef USE_USB_HS - {0x00, CDC_DATA_HS_MAX_PACKET_SIZE}, - {0x80, CDC_DATA_HS_MAX_PACKET_SIZE}, - {CDC_OUT_EP, CDC_DATA_HS_MAX_PACKET_SIZE}, - {CDC_IN_EP, CDC_DATA_HS_MAX_PACKET_SIZE}, - {CDC_CMD_EP, CDC_CMD_PACKET_SIZE} -#else /* USE_USB_FS */ -#ifdef USB_OTG_FS - {0x00, CDC_DATA_FS_MAX_PACKET_SIZE}, - {0x80, CDC_DATA_FS_MAX_PACKET_SIZE}, - {CDC_OUT_EP, CDC_DATA_FS_MAX_PACKET_SIZE}, - {CDC_IN_EP, CDC_DATA_FS_MAX_PACKET_SIZE}, - {CDC_CMD_EP, CDC_CMD_PACKET_SIZE} +#if defined(USB_OTG_FS) || defined(USE_USB_HS) + #define EP_DESC(ADDR, SIZE, KIND_TYP) {ADDR, SIZE} #else - {0x00, PMA_EP0_OUT_ADDR, PCD_SNG_BUF}, - {0x80, PMA_EP0_IN_ADDR, PCD_SNG_BUF}, - {CDC_OUT_EP, PMA_CDC_OUT_ADDR, PCD_DBL_BUF}, - {CDC_IN_EP, PMA_CDC_IN_ADDR, PCD_SNG_BUF}, - {CDC_CMD_EP, PMA_CDC_CMD_ADDR, PCD_SNG_BUF} -#endif + #define EP_DESC(ADDR, SIZE, KIND_TYP) {ADDR, SIZE, KIND_TYP} #endif -}; + +// *INDENT-OFF* + +#ifdef USBD_USE_CDC + #ifdef USE_USB_HS + #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + #else /* USE_USB_FS */ + #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + #endif + + + const ep_desc_t ep_def[] = { + EP_DESC(0x00, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(0x80, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(CDC_OUT_EP, CDC_DATA_MAX_PACKET_SIZE, PCD_DBL_BUF), + EP_DESC(CDC_IN_EP, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(CDC_CMD_EP, CDC_CMD_PACKET_SIZE, PCD_SNG_BUF) + }; #endif /* USBD_USE_CDC */ +#ifdef USBD_USE_MSC + #ifdef USE_USB_HS + #define MSC_DATA_MAX_PACKET_SIZE MSC_DATA_HS_MAX_PACKET_SIZE + #else /* USE_USB_FS */ + #define MSC_DATA_MAX_PACKET_SIZE MSC_DATA_FS_MAX_PACKET_SIZE + #endif + + + const ep_desc_t ep_def[] = { + EP_DESC(0x00, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(0x80, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(MSC_EPIN_ADDR, MSC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(MSC_EPOUT_ADDR, MSC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF) + }; +#endif /* USBD_USE_MSC */ + +#ifdef USBD_USE_CDC_MSC + #ifdef USE_USB_HS + #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + #define MSC_DATA_MAX_PACKET_SIZE MSC_DATA_HS_MAX_PACKET_SIZE + #else /* USE_USB_FS */ + #define CDC_DATA_MAX_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + #define MSC_DATA_MAX_PACKET_SIZE MSC_DATA_FS_MAX_PACKET_SIZE + #endif + + + const ep_desc_t ep_def[] = { + EP_DESC(0x00, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(0x80, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(CDC_OUT_EP, CDC_DATA_MAX_PACKET_SIZE, PCD_DBL_BUF), + EP_DESC(CDC_IN_EP, CDC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(CDC_CMD_EP, CDC_CMD_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(MSC_EPIN_ADDR, MSC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(MSC_EPOUT_ADDR, MSC_DATA_MAX_PACKET_SIZE, PCD_SNG_BUF) + }; +#endif /* USBD_USE_CDC */ + + #ifdef USBD_USE_HID_COMPOSITE -const ep_desc_t ep_def[] = { -#if !defined (USB) -#ifdef USE_USB_HS - {0x00, USB_HS_MAX_PACKET_SIZE}, - {0x80, USB_HS_MAX_PACKET_SIZE}, -#else - {0x00, USB_FS_MAX_PACKET_SIZE}, - {0x80, USB_FS_MAX_PACKET_SIZE}, -#endif - {HID_MOUSE_EPIN_ADDR, HID_MOUSE_EPIN_SIZE}, - {HID_KEYBOARD_EPIN_ADDR, HID_KEYBOARD_EPIN_SIZE}, -#else - {0x00, PMA_EP0_OUT_ADDR, PCD_SNG_BUF}, - {0x80, PMA_EP0_IN_ADDR, PCD_SNG_BUF}, - {HID_MOUSE_EPIN_ADDR, PMA_MOUSE_IN_ADDR, PCD_SNG_BUF}, - {HID_KEYBOARD_EPIN_ADDR, PMA_KEYBOARD_IN_ADDR, PCD_SNG_BUF}, -#endif -}; + #ifdef USE_USB_HS + #define HID_MAX_PACKET_SIZE USB_HS_MAX_PACKET_SIZE + #else /* USE_USB_FS */ + #define HID_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE + #endif + + const ep_desc_t ep_def[] = { + EP_DESC(0x00, HID_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(0x80, HID_MAX_PACKET_SIZE, PCD_SNG_BUF), + EP_DESC(HID_MOUSE_EPIN_ADDR, HID_MOUSE_EPIN_SIZE, PCD_SNG_BUF), + EP_DESC(HID_KEYBOARD_EPIN_ADDR, HID_MOUSE_EPIN_SIZE, PCD_SNG_BUF) + }; #endif /* USBD_USE_HID_COMPOSITE */ +// *INDENT-OFF* + #endif /* HAL_PCD_MODULE_ENABLED && USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/usbd_ep_conf.h b/cores/arduino/stm32/usb/usbd_ep_conf.h index 354b6f4d0c..75a458b4d1 100644 --- a/cores/arduino/stm32/usb/usbd_ep_conf.h +++ b/cores/arduino/stm32/usb/usbd_ep_conf.h @@ -33,9 +33,11 @@ typedef struct { #endif } ep_desc_t; +// *INDENT-OFF* /* CDC Endpoints Configurations */ #ifdef USBD_USE_CDC + #define USBD_USE_CDC_CLASS #define CDC_OUT_EP 0x01U /* EP1 for data OUT */ #define CDC_IN_EP 0x82U /* EP1 for data IN */ @@ -49,6 +51,40 @@ typedef struct { #define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ #endif /* USBD_USE_CDC */ +#ifdef USBD_USE_MSC + #define USBD_USE_MSC_CLASS + + #define MSC_EPOUT_ADDR 0x01U /* EP1 for MSC data IN */ + #define MSC_EPIN_ADDR 0x81U /* EP1 for MSC data IN */ + + #define DEV_NUM_EP 0x04U /* Device Endpoints number including EP0 IN and EP0 OUT */ + + /* MSC Endpoints parameters*/ + #define MSC_DATA_HS_MAX_PACKET_SIZE USB_HS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ + #define MSC_DATA_FS_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ +#endif + +#ifdef USBD_USE_CDC_MSC + #define USBD_USE_CDC_CLASS + #define USBD_USE_MSC_CLASS + + #define CDC_OUT_EP 0x01U /* EP1 for CDC data OUT */ + #define CDC_IN_EP 0x81U /* EP1 for CDC data IN */ + #define CDC_CMD_EP 0x82U /* EP2 for CDC commands */ + + #define MSC_EPOUT_ADDR 0x03U /* EP3 for MSC data IN */ + #define MSC_EPIN_ADDR 0x83U /* EP3 for MSC data IN */ + + #define DEV_NUM_EP 0x07U /* Device Endpoints number including EP0 */ + + /* CDC Endpoints parameters*/ + #define CDC_DATA_HS_MAX_PACKET_SIZE USB_HS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ + #define CDC_DATA_FS_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ + #define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ + /* MSC Endpoints parameters*/ + #define MSC_DATA_HS_MAX_PACKET_SIZE USB_HS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ + #define MSC_DATA_FS_MAX_PACKET_SIZE USB_FS_MAX_PACKET_SIZE /* Endpoint IN & OUT Packet size */ +#endif /* HID composite (Mouse + Keyboard) Endpoints Configurations */ #ifdef USBD_USE_HID_COMPOSITE @@ -61,29 +97,19 @@ typedef struct { #define DEV_NUM_EP 0x03U /* Device Endpoints number including EP0 */ #endif /* USBD_USE_HID_COMPOSITE */ + /* Require DEV_NUM_EP to be defined */ #if defined (USB) -/* Size in words, byte size divided by 2 */ -#define PMA_EP0_OUT_ADDR (8 * DEV_NUM_EP) -#define PMA_EP0_IN_ADDR (PMA_EP0_OUT_ADDR + USB_MAX_EP0_SIZE) - -#ifdef USBD_USE_CDC -#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 + CDC_CMD_PACKET_SIZE) -#endif /* USBD_USE_CDC */ -#ifdef USBD_USE_HID_COMPOSITE - #define PMA_MOUSE_IN_ADDR (PMA_EP0_IN_ADDR + HID_MOUSE_EPIN_SIZE) - #define PMA_KEYBOARD_IN_ADDR (PMA_MOUSE_IN_ADDR + HID_KEYBOARD_EPIN_SIZE) -#endif /* USBD_USE_HID_COMPOSITE */ + /* Size in words, byte size divided by 2 */ + #define PMA_BASE_OFFSET (8 * DEV_NUM_EP) #endif /* USB */ +// *INDENT-ON* + extern const ep_desc_t ep_def[DEV_NUM_EP + 1]; #endif /* USBCON */ #endif /* __USBD_EP_CONF_H */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ \ No newline at end of file +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/usbd_if.c b/cores/arduino/stm32/usb/usbd_if.c index e579140f72..0ea854909e 100644 --- a/cores/arduino/stm32/usb/usbd_if.c +++ b/cores/arduino/stm32/usb/usbd_if.c @@ -155,11 +155,4 @@ WEAK void USBD_reenumerate(void) #else /* !defined(USBD_REENUM_DISABLED) */ WEAK void USBD_reenumerate(void) { } #endif - -#ifdef USBD_USE_CDC -void USBD_CDC_init(void) -{ - CDC_init(); -} -#endif /* USBD_USE_CDC */ #endif /* USBCON */ diff --git a/cores/arduino/stm32/usb/usbd_if.h b/cores/arduino/stm32/usb/usbd_if.h index dc026240fe..bcd54020e6 100644 --- a/cores/arduino/stm32/usb/usbd_if.h +++ b/cores/arduino/stm32/usb/usbd_if.h @@ -24,9 +24,7 @@ extern "C" { #endif void USBD_reenumerate(void); -#ifdef USBD_USE_CDC -void USBD_CDC_init(void); -#endif + #ifdef __cplusplus } #endif diff --git a/libraries/SrcWrapper/src/stm32/hw_config.c b/libraries/SrcWrapper/src/stm32/hw_config.cpp similarity index 95% rename from libraries/SrcWrapper/src/stm32/hw_config.c rename to libraries/SrcWrapper/src/stm32/hw_config.cpp index 3434d6da96..6bec1f76f0 100644 --- a/libraries/SrcWrapper/src/stm32/hw_config.c +++ b/libraries/SrcWrapper/src/stm32/hw_config.cpp @@ -37,7 +37,8 @@ */ #include "stm32_def.h" #include "hw_config.h" -#include "usbd_if.h" +#include "usbd_ep_conf.h" +#include "USBSerial.h" #include "dwt.h" #ifdef __cplusplus @@ -62,8 +63,8 @@ void hw_config_init(void) /* Configure the system clock */ SystemClock_Config(); -#if defined (USBCON) && defined(USBD_USE_CDC) - USBD_CDC_init(); +#if defined (USBCON) && defined(USBD_USE_CDC_CLASS) + SerialUSB.begin(); #endif #if defined (STM32MP1xx) diff --git a/platform.txt b/platform.txt index 3674dfe7d2..925aa620ea 100644 --- a/platform.txt +++ b/platform.txt @@ -9,7 +9,7 @@ version=1.0.0 # STM compile variables # ---------------------- -compiler.stm.extra_include="-I{build.source.path}" "-I{build.core.path}/avr" "-I{build.core.path}/stm32" "-I{build.core.path}/stm32/LL" "-I{build.core.path}/stm32/usb" "-I{build.core.path}/stm32/OpenAMP" "-I{build.core.path}/stm32/usb/hid" "-I{build.core.path}/stm32/usb/cdc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Inc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Src" "-I{build.system.path}/{build.series}" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Src" {build.virtio_extra_include} +compiler.stm.extra_include="-I{build.source.path}" "-I{build.core.path}/avr" "-I{build.core.path}/stm32" "-I{build.core.path}/stm32/LL" "-I{build.core.path}/stm32/usb" "-I{build.core.path}/stm32/OpenAMP" "-I{build.core.path}/stm32/usb/hid" "-I{build.core.path}/stm32/usb/cdc" "-I{build.core.path}/stm32/usb/msc" "-I{build.core.path}/stm32/usb/cdc_msc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Inc" "-I{build.system.path}/Drivers/{build.series}_HAL_Driver/Src" "-I{build.system.path}/{build.series}" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc" "-I{build.system.path}/Middlewares/ST/STM32_USB_Device_Library/Core/Src" {build.virtio_extra_include} compiler.warning_flags=-w compiler.warning_flags.none=-w diff --git a/tools/platformio-build.py b/tools/platformio-build.py index 68b0dfc01c..7bdc40d781 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -86,7 +86,7 @@ def process_usb_configuration(cpp_defines): elif "PIO_FRAMEWORK_ARDUINO_ENABLE_HID" in cpp_defines: env.Append(CPPDEFINES=["USBD_USE_HID_COMPOSITE"]) - if any(f in env["CPPDEFINES"] for f in ("USBD_USE_CDC", "USBD_USE_HID_COMPOSITE")): + if any(f in env["CPPDEFINES"] for f in ["USBCON"]): env.Append(CPPDEFINES=["HAL_PCD_MODULE_ENABLED"]) @@ -170,6 +170,8 @@ def configure_application_offset(mcu, upload_protocol): join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb"), join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "hid"), join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "cdc"), + join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "msc"), + join(FRAMEWORK_DIR, "cores", "arduino", "stm32", "usb", "cdc_msc"), join(FRAMEWORK_DIR, "system", "Drivers", series + "_HAL_Driver", "Inc"), join(FRAMEWORK_DIR, "system", "Drivers", series + "_HAL_Driver", "Src"), join(FRAMEWORK_DIR, "system", series),