diff options
-rw-r--r-- | stmhal/Makefile | 10 | ||||
-rw-r--r-- | stmhal/led.c | 2 | ||||
-rw-r--r-- | stmhal/main.c | 169 | ||||
-rw-r--r-- | stmhal/modpyb.c | 2 | ||||
-rw-r--r-- | stmhal/qstrdefsport.h | 1 | ||||
-rw-r--r-- | stmhal/stm32f4xx_hal_msp.c | 2 | ||||
-rw-r--r-- | stmhal/stm32f4xx_it.c | 2 | ||||
-rw-r--r-- | stmhal/usb.c | 34 | ||||
-rw-r--r-- | stmhal/usb.h | 14 | ||||
-rw-r--r-- | stmhal/usbd_cdc_interface.c | 2 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h | 97 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_bot.h | 151 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_data.h | 104 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_scsi.h | 193 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c | 911 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc.c | 609 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_bot.c | 407 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_data.c | 134 | ||||
-rw-r--r-- | stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c | 770 | ||||
-rw-r--r-- | stmhal/usrsw.c | 11 | ||||
-rw-r--r-- | stmhal/usrsw.h | 1 |
21 files changed, 3513 insertions, 113 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile index b4169e3d63..67c1ebcb42 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -21,7 +21,7 @@ INC += -I$(PY_SRC) INC += -I$(CMSIS_DIR)/inc INC += -I$(CMSIS_DIR)/devinc INC += -I$(HAL_DIR)/inc -INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc/inc +INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc_hid/inc #INC += -I$(USBHOST_DIR) INC += -I$(FATFS_DIR)/src #INC += -I$(CC3K_DIR) @@ -135,10 +135,10 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ core/src/usbd_core.c \ core/src/usbd_ctlreq.c \ core/src/usbd_ioreq.c \ - class/cdc_msc/src/usbd_cdc_msc.c \ - class/cdc_msc/src/usbd_msc_bot.c \ - class/cdc_msc/src/usbd_msc_scsi.c \ - class/cdc_msc/src/usbd_msc_data.c \ + class/cdc_msc_hid/src/usbd_cdc_msc_hid.c \ + class/cdc_msc_hid/src/usbd_msc_bot.c \ + class/cdc_msc_hid/src/usbd_msc_scsi.c \ + class/cdc_msc_hid/src/usbd_msc_data.c \ ) # class/cdc/src/usbd_cdc.c \ diff --git a/stmhal/led.c b/stmhal/led.c index 557f54538e..5ff50fbb88 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -1,6 +1,6 @@ #include <stdio.h> #include <stm32f4xx_hal.h> -#include "usbd_cdc_msc.h" +#include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "nlr.h" diff --git a/stmhal/main.c b/stmhal/main.c index e40026efdd..9efaaec764 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -75,6 +75,7 @@ void __fatal_error(const char *msg) { STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; +STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL; STATIC mp_obj_t pyb_source_dir(mp_obj_t source_dir) { if (MP_OBJ_IS_STR(source_dir)) { @@ -94,6 +95,15 @@ STATIC mp_obj_t pyb_main(mp_obj_t main) { MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main); +STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) { + if (MP_OBJ_IS_STR(usb_mode)) { + pyb_config_usb_mode = usb_mode; + } + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode); + void fatality(void) { led_state(PYB_LED_R1, 1); led_state(PYB_LED_G1, 1); @@ -109,12 +119,9 @@ static const char fresh_boot_py[] = "# can run arbitrary Python, but best to keep it minimal\n" "\n" "import pyb\n" -"pyb.source_dir('/src')\n" -"pyb.main('main.py')\n" -"#pyb.usb_usr('VCP')\n" -"#pyb.usb_msd(True, 'dual partition')\n" -"#pyb.flush_cache(False)\n" -"#pyb.error_log('error.txt')\n" +"#pyb.source_dir('/src')\n" +"#pyb.main('main.py')\n" +"#pyb.usb_mode('CDC+MSC') # one of: 'CDC+MSC', 'CDC+HID'\n" ; static const char fresh_main_py[] = @@ -171,23 +178,64 @@ int main(void) { // basic sub-system init pendsv_init(); led_init(); + switch_init0(); - // turn on LED to indicate bootup - led_state(PYB_LED_GREEN, 1); + int first_soft_reset = true; + uint reset_mode; + +soft_reset: + + // check if user switch held to select the reset mode + reset_mode = 1; + led_state(1, 0); + led_state(2, 1); + led_state(3, 0); + led_state(4, 0); + +#if MICROPY_HW_HAS_SWITCH + if (switch_get()) { + for (uint i = 0; i < 3000; i++) { + if (!switch_get()) { + break; + } + HAL_Delay(20); + if (i % 30 == 29) { + reset_mode = (reset_mode + 1) & 7; + led_state(2, reset_mode & 1); + led_state(3, reset_mode & 2); + led_state(4, reset_mode & 4); + } + } + // flash the selected reset mode + for (uint i = 0; i < 6; i++) { + led_state(2, 0); + led_state(3, 0); + led_state(4, 0); + HAL_Delay(50); + led_state(2, reset_mode & 1); + led_state(3, reset_mode & 2); + led_state(4, reset_mode & 4); + HAL_Delay(50); + } + HAL_Delay(400); + } +#endif #if MICROPY_HW_ENABLE_RTC - rtc_init(); + if (first_soft_reset) { + rtc_init(); + } #endif // more sub-system init #if MICROPY_HW_HAS_SDCARD - sdcard_init(); + if (first_soft_reset) { + sdcard_init(); + } #endif - storage_init(); - - int first_soft_reset = true; - -soft_reset: + if (first_soft_reset) { + storage_init(); + } // GC init gc_init(&_heap_start, &_heap_end); @@ -215,6 +263,7 @@ soft_reset: exti_init(); #if MICROPY_HW_HAS_SWITCH + // must come after exti_init switch_init(); #endif @@ -225,29 +274,12 @@ soft_reset: pin_map_init(); - // check if user switch held (initiates reset of filesystem) - bool reset_filesystem = false; -#if MICROPY_HW_HAS_SWITCH - if (switch_get()) { - reset_filesystem = true; - for (int i = 0; i < 50; i++) { - if (!switch_get()) { - reset_filesystem = false; - break; - } - HAL_Delay(10); - } - } -#endif // local filesystem init { // try to mount the flash FRESULT res = f_mount(&fatfs0, "0:", 1); - if (!reset_filesystem && res == FR_OK) { - // mount sucessful - } else if (reset_filesystem || res == FR_NO_FILESYSTEM) { - // no filesystem, so create a fresh one - // TODO doesn't seem to work correctly when reset_filesystem is true... + if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { + // no filesystem, or asked to reset it, so create a fresh one // LED on to indicate creation of LFS led_state(PYB_LED_R2, 1); @@ -275,6 +307,8 @@ soft_reset: // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_R2, 0); + } else if (res == FR_OK) { + // mount sucessful } else { __fatal_error("could not access LFS"); } @@ -317,20 +351,24 @@ soft_reset: } // run /boot.py - if (!pyexec_file("0:/boot.py")) { - flash_error(4); + if (reset_mode == 1) { + if (!pyexec_file("0:/boot.py")) { + flash_error(4); + } } - // turn boot-up LED off - led_state(PYB_LED_GREEN, 0); + // turn boot-up LEDs off + led_state(2, 0); + led_state(3, 0); + led_state(4, 0); #if defined(USE_DEVICE_MODE) - usbd_storage_medium_kind_t usbd_medium_kind = USBD_STORAGE_MEDIUM_FLASH; + usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH; #endif #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on 1:/ - if (sdcard_is_present()) { + if (reset_mode == 1 && sdcard_is_present()) { FRESULT res = f_mount(&fatfs1, "1:", 1); if (res != FR_OK) { printf("[SD] could not mount SD card\n"); @@ -338,7 +376,7 @@ soft_reset: if (first_soft_reset) { // use SD card as medium for the USB MSD #if defined(USE_DEVICE_MODE) - usbd_medium_kind = USBD_STORAGE_MEDIUM_SDCARD; + usb_medium = USB_STORAGE_MEDIUM_SDCARD; #endif } } @@ -353,7 +391,17 @@ soft_reset: pyb_usb_host_init(); #elif defined(USE_DEVICE_MODE) // USB device - pyb_usb_dev_init(USBD_DEVICE_CDC_MSC, usbd_medium_kind); + if (reset_mode == 1) { + usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC; + if (pyb_config_usb_mode != MP_OBJ_NULL) { + if (strcmp(mp_obj_str_get_str(pyb_config_usb_mode), "CDC+HID") == 0) { + usb_mode = USB_DEVICE_MODE_CDC_HID; + } + } + pyb_usb_dev_init(usb_mode, usb_medium); + } else { + pyb_usb_dev_init(USB_DEVICE_MODE_CDC_MSC, usb_medium); + } #endif #if MICROPY_HW_ENABLE_RNG @@ -387,7 +435,7 @@ soft_reset: #endif // run main script - { + if (reset_mode == 1) { vstr_t *vstr = vstr_new(); vstr_add_str(vstr, "0:/"); if (pyb_config_source_dir == MP_OBJ_NULL) { @@ -408,41 +456,6 @@ soft_reset: } #if 0 -#if MICROPY_HW_HAS_MMA7660 - // HID example - if (0) { - uint8_t data[4]; - data[0] = 0; - data[1] = 1; - data[2] = -2; - data[3] = 0; - for (;;) { - #if MICROPY_HW_HAS_SWITCH - if (switch_get()) { - data[0] = 0x01; // 0x04 is middle, 0x02 is right - } else { - data[0] = 0x00; - } - #else - data[0] = 0x00; - #endif - accel_start(0x4c /* ACCEL_ADDR */, 1); - accel_send_byte(0); - accel_restart(0x4c /* ACCEL_ADDR */, 0); - for (int i = 0; i <= 1; i++) { - int v = accel_read_ack() & 0x3f; - if (v & 0x20) { - v |= ~0x1f; - } - data[1 + i] = v; - } - accel_read_nack(); - usb_hid_send_report(data); - HAL_Delay(15); - } - } -#endif - #if MICROPY_HW_HAS_WLAN // wifi pyb_wlan_init(); diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 6bdb2db846..87fab706d7 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -208,6 +208,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_input_obj, pyb_input); MP_DECLARE_CONST_FUN_OBJ(pyb_source_dir_obj); // defined in main.c MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c +MP_DECLARE_CONST_FUN_OBJ(pyb_usb_mode_obj); // defined in main.c STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) }, @@ -220,6 +221,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&pyb_standby_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_source_dir), (mp_obj_t)&pyb_source_dir_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj }, diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 29d97bafaa..0a7fe821dd 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -10,6 +10,7 @@ Q(stop) Q(standby) Q(source_dir) Q(main) +Q(usb_mode) Q(sync) Q(gc) Q(repl_info) diff --git a/stmhal/stm32f4xx_hal_msp.c b/stmhal/stm32f4xx_hal_msp.c index 15dca56517..1cf78336f8 100644 --- a/stmhal/stm32f4xx_hal_msp.c +++ b/stmhal/stm32f4xx_hal_msp.c @@ -38,7 +38,7 @@ /* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
-#include "usbd_cdc_msc.h"
+#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "misc.h"
diff --git a/stmhal/stm32f4xx_it.c b/stmhal/stm32f4xx_it.c index bd324a030d..e74b1c6c75 100644 --- a/stmhal/stm32f4xx_it.c +++ b/stmhal/stm32f4xx_it.c @@ -42,7 +42,7 @@ #include "stm32f4xx_it.h"
#include "stm32f4xx_hal.h"
-#include "usbd_cdc_msc.h"
+#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "misc.h"
diff --git a/stmhal/usb.c b/stmhal/usb.c index 79f9b85f35..3d795f1823 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -2,7 +2,7 @@ #include "usbd_core.h" #include "usbd_desc.h" -#include "usbd_cdc_msc.h" +#include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "usbd_msc_storage.h" @@ -19,28 +19,24 @@ USBD_HandleTypeDef hUSBDDevice; static int dev_is_enabled = 0; mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL; -void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind) { +void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) { #ifdef USE_DEVICE_MODE if (!dev_is_enabled) { // only init USB once in the device's power-lifetime - switch (device_kind) { - case USBD_DEVICE_CDC_MSC: - USBD_Init(&hUSBDDevice, &VCP_Desc, 0); - USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC); - USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops); - if (medium_kind == USBD_STORAGE_MEDIUM_FLASH) { - USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops); - } else { - USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops); - } - USBD_Start(&hUSBDDevice); - break; - - case USBD_DEVICE_HID: - //USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb); - // TODO - break; + if (mode == USB_DEVICE_MODE_CDC_MSC) { + USBD_SelectMode(USBD_MODE_CDC_MSC); + } else { + USBD_SelectMode(USBD_MODE_CDC_HID); } + USBD_Init(&hUSBDDevice, &VCP_Desc, 0); + USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC_HID); + USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops); + if (medium == USB_STORAGE_MEDIUM_FLASH) { + USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops); + } else { + USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops); + } + USBD_Start(&hUSBDDevice); } dev_is_enabled = 1; diff --git a/stmhal/usb.h b/stmhal/usb.h index e30b1364f9..014b51eefa 100644 --- a/stmhal/usb.h +++ b/stmhal/usb.h @@ -5,16 +5,16 @@ #define VCP_CHAR_CTRL_D (4) typedef enum { - USBD_DEVICE_CDC_MSC, - USBD_DEVICE_HID, -} usbd_device_kind_t; + USB_DEVICE_MODE_CDC_MSC, + USB_DEVICE_MODE_CDC_HID, +} usb_device_mode_t; typedef enum { - USBD_STORAGE_MEDIUM_FLASH, - USBD_STORAGE_MEDIUM_SDCARD, -} usbd_storage_medium_kind_t; + USB_STORAGE_MEDIUM_FLASH, + USB_STORAGE_MEDIUM_SDCARD, +} usb_storage_medium_t; -void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind); +void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium); bool usb_vcp_is_enabled(void); bool usb_vcp_is_connected(void); void usb_vcp_set_interrupt_char(int c); diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c index c441e9c61c..693f51b7c8 100644 --- a/stmhal/usbd_cdc_interface.c +++ b/stmhal/usbd_cdc_interface.c @@ -28,7 +28,7 @@ /* Includes ------------------------------------------------------------------*/ #include <stdbool.h> #include "stm32f4xx_hal.h" -#include "usbd_cdc_msc.h" +#include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" #include "pendsv.h" #include "usb.h" diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h new file mode 100644 index 0000000000..8423ad7759 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h @@ -0,0 +1,97 @@ +#ifndef _USB_CDC_MSC_CORE_H_ +#define _USB_CDC_MSC_CORE_H_ + +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" + +// CDC and MSC packet sizes +#define CDC_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size +#define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working? + +// Need to define here for BOT and SCSI layers +#define MSC_IN_EP (0x81) +#define MSC_OUT_EP (0x01) + +// only CDC_MSC and CDC_HID are available +#define USBD_MODE_CDC (0x01) +#define USBD_MODE_MSC (0x02) +#define USBD_MODE_HID (0x04) +#define USBD_MODE_CDC_MSC (USBD_MODE_CDC | USBD_MODE_MSC) +#define USBD_MODE_CDC_HID (USBD_MODE_CDC | USBD_MODE_HID) +#define USBD_MODE_MSC_HID (USBD_MODE_MSC | USBD_MODE_HID) + +typedef struct { + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +} USBD_CDC_LineCodingTypeDef; + +typedef struct _USBD_CDC_Itf { + int8_t (* Init) (void); + int8_t (* DeInit) (void); + int8_t (* Control) (uint8_t, uint8_t * , uint16_t); + int8_t (* Receive) (uint8_t *, uint32_t *); +} USBD_CDC_ItfTypeDef; + +typedef struct { + uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} USBD_CDC_HandleTypeDef; + +typedef struct _USBD_STORAGE { + int8_t (* Init) (uint8_t lun); + int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size); + int8_t (* IsReady) (uint8_t lun); + int8_t (* IsWriteProtected) (uint8_t lun); + int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* GetMaxLun)(void); + int8_t *pInquiry; +} USBD_StorageTypeDef; + +typedef struct { + uint32_t max_lun; + uint32_t interface; + uint8_t bot_state; + uint8_t bot_status; + uint16_t bot_data_length; + uint8_t bot_data[MSC_MEDIA_PACKET]; + USBD_MSC_BOT_CBWTypeDef cbw; + USBD_MSC_BOT_CSWTypeDef csw; + + USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH]; + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint16_t scsi_blk_size; + uint32_t scsi_blk_nbr; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; +} USBD_MSC_BOT_HandleTypeDef; + +extern USBD_ClassTypeDef USBD_CDC_MSC_HID; + +void USBD_SelectMode(uint32_t mode); + +uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops); +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length); +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff); +uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); +uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev); + +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops); + +uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len); + +#endif // _USB_CDC_MSC_CORE_H_ diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_bot.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_bot.h new file mode 100644 index 0000000000..41f8ab5a53 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_bot.h @@ -0,0 +1,151 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_bot.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_bot.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+
+#include "usbd_core.h"
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_MSC_BOT_H
+#define __USBD_MSC_BOT_H
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup MSC_BOT
+ * @brief This file is the Header file for usbd_bot.c
+ * @{
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Defines
+ * @{
+ */
+#define USBD_BOT_IDLE 0 /* Idle state */
+#define USBD_BOT_DATA_OUT 1 /* Data Out state */
+#define USBD_BOT_DATA_IN 2 /* Data In state */
+#define USBD_BOT_LAST_DATA_IN 3 /* Last Data In Last */
+#define USBD_BOT_SEND_DATA 4 /* Send Immediate data */
+#define USBD_BOT_NO_DATA 5 /* No data Stage */
+
+#define USBD_BOT_CBW_SIGNATURE 0x43425355
+#define USBD_BOT_CSW_SIGNATURE 0x53425355
+#define USBD_BOT_CBW_LENGTH 31
+#define USBD_BOT_CSW_LENGTH 13
+#define USBD_BOT_MAX_DATA 256
+
+/* CSW Status Definitions */
+#define USBD_CSW_CMD_PASSED 0x00
+#define USBD_CSW_CMD_FAILED 0x01
+#define USBD_CSW_PHASE_ERROR 0x02
+
+/* BOT Status */
+#define USBD_BOT_STATUS_NORMAL 0
+#define USBD_BOT_STATUS_RECOVERY 1
+#define USBD_BOT_STATUS_ERROR 2
+
+
+#define USBD_DIR_IN 0
+#define USBD_DIR_OUT 1
+#define USBD_BOTH_DIR 2
+
+/**
+ * @}
+ */
+
+/** @defgroup MSC_CORE_Private_TypesDefinitions
+ * @{
+ */
+
+typedef struct
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataLength;
+ uint8_t bmFlags;
+ uint8_t bLUN;
+ uint8_t bCBLength;
+ uint8_t CB[16];
+ uint8_t ReservedForAlign;
+}
+USBD_MSC_BOT_CBWTypeDef;
+
+
+typedef struct
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataResidue;
+ uint8_t bStatus;
+ uint8_t ReservedForAlign[3];
+}
+USBD_MSC_BOT_CSWTypeDef;
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_CORE_Exported_Types
+ * @{
+ */
+
+/**
+ * @}
+ */
+/** @defgroup USBD_CORE_Exported_FunctionsPrototypes
+ * @{
+ */
+void MSC_BOT_Init (USBD_HandleTypeDef *pdev);
+void MSC_BOT_Reset (USBD_HandleTypeDef *pdev);
+void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev);
+void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+
+void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
+ uint8_t CSW_Status);
+
+void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev,
+ uint8_t epnum);
+/**
+ * @}
+ */
+
+#endif /* __USBD_MSC_BOT_H */
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_data.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_data.h new file mode 100644 index 0000000000..f468267f43 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_data.h @@ -0,0 +1,104 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_data.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_data.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+
+#ifndef _USBD_MSC_DATA_H_
+#define _USBD_MSC_DATA_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_conf.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USB_INFO
+ * @brief general defines for the usb device library file
+ * @{
+ */
+
+/** @defgroup USB_INFO_Exported_Defines
+ * @{
+ */
+#define MODE_SENSE6_LEN 8
+#define MODE_SENSE10_LEN 8
+#define LENGTH_INQUIRY_PAGE00 7
+#define LENGTH_FORMAT_CAPACITIES 20
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_INFO_Exported_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_INFO_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_INFO_Exported_Variables
+ * @{
+ */
+extern const uint8_t MSC_Page00_Inquiry_Data[];
+extern const uint8_t MSC_Mode_Sense6_data[];
+extern const uint8_t MSC_Mode_Sense10_data[] ;
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_INFO_Exported_FunctionsPrototype
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+#endif /* _USBD_MSC_DATA_H_ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_scsi.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_scsi.h new file mode 100644 index 0000000000..dea247bca8 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_msc_scsi.h @@ -0,0 +1,193 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_scsi.h
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief header for the usbd_msc_scsi.c file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_MSC_SCSI_H
+#define __USBD_MSC_SCSI_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_def.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USBD_SCSI
+ * @brief header file for the storage disk file
+ * @{
+ */
+
+/** @defgroup USBD_SCSI_Exported_Defines
+ * @{
+ */
+
+#define SENSE_LIST_DEEPTH 4
+
+/* SCSI Commands */
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SELECT6 0x15
+#define SCSI_MODE_SELECT10 0x55
+#define SCSI_MODE_SENSE6 0x1A
+#define SCSI_MODE_SENSE10 0x5A
+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
+#define SCSI_READ6 0x08
+#define SCSI_READ10 0x28
+#define SCSI_READ12 0xA8
+#define SCSI_READ16 0x88
+
+#define SCSI_READ_CAPACITY10 0x25
+#define SCSI_READ_CAPACITY16 0x9E
+
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_START_STOP_UNIT 0x1B
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_WRITE6 0x0A
+#define SCSI_WRITE10 0x2A
+#define SCSI_WRITE12 0xAA
+#define SCSI_WRITE16 0x8A
+
+#define SCSI_VERIFY10 0x2F
+#define SCSI_VERIFY12 0xAF
+#define SCSI_VERIFY16 0x8F
+
+#define SCSI_SEND_DIAGNOSTIC 0x1D
+#define SCSI_READ_FORMAT_CAPACITIES 0x23
+
+#define NO_SENSE 0
+#define RECOVERED_ERROR 1
+#define NOT_READY 2
+#define MEDIUM_ERROR 3
+#define HARDWARE_ERROR 4
+#define ILLEGAL_REQUEST 5
+#define UNIT_ATTENTION 6
+#define DATA_PROTECT 7
+#define BLANK_CHECK 8
+#define VENDOR_SPECIFIC 9
+#define COPY_ABORTED 10
+#define ABORTED_COMMAND 11
+#define VOLUME_OVERFLOW 13
+#define MISCOMPARE 14
+
+
+#define INVALID_CDB 0x20
+#define INVALID_FIELED_IN_COMMAND 0x24
+#define PARAMETER_LIST_LENGTH_ERROR 0x1A
+#define INVALID_FIELD_IN_PARAMETER_LIST 0x26
+#define ADDRESS_OUT_OF_RANGE 0x21
+#define MEDIUM_NOT_PRESENT 0x3A
+#define MEDIUM_HAVE_CHANGED 0x28
+#define WRITE_PROTECTED 0x27
+#define UNRECOVERED_READ_ERROR 0x11
+#define WRITE_FAULT 0x03
+
+#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C
+#define READ_CAPACITY10_DATA_LEN 0x08
+#define MODE_SENSE10_DATA_LEN 0x08
+#define MODE_SENSE6_DATA_LEN 0x04
+#define REQUEST_SENSE_DATA_LEN 0x12
+#define STANDARD_INQUIRY_DATA_LEN 0x24
+#define BLKVFY 0x04
+
+extern uint8_t Page00_Inquiry_Data[];
+extern uint8_t Standard_Inquiry_Data[];
+extern uint8_t Standard_Inquiry_Data2[];
+extern uint8_t Mode_Sense6_data[];
+extern uint8_t Mode_Sense10_data[];
+extern uint8_t Scsi_Sense_Data[];
+extern uint8_t ReadCapacity10_Data[];
+extern uint8_t ReadFormatCapacity_Data [];
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_SCSI_Exported_TypesDefinitions
+ * @{
+ */
+
+typedef struct _SENSE_ITEM {
+ char Skey;
+ union {
+ struct _ASCs {
+ char ASC;
+ char ASCQ;
+ }b;
+ unsigned int ASC;
+ char *pData;
+ } w;
+} USBD_SCSI_SenseTypeDef;
+/**
+ * @}
+ */
+
+/** @defgroup USBD_SCSI_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup USBD_SCSI_Exported_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+/** @defgroup USBD_SCSI_Exported_FunctionsPrototype
+ * @{
+ */
+int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t *cmd);
+
+void SCSI_SenseCode(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t sKey,
+ uint8_t ASC);
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_MSC_SCSI_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c new file mode 100644 index 0000000000..6cb15ba210 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c @@ -0,0 +1,911 @@ +#include "usbd_ioreq.h" +#include "usbd_cdc_msc_hid.h" + +#define USB_CDC_MSC_CONFIG_DESC_SIZ (98) +#define USB_CDC_HID_CONFIG_DESC_SIZ (100) +#define CDC_IFACE_NUM (1) +#define CDC_IN_EP (0x83) +#define CDC_OUT_EP (0x03) +#define CDC_CMD_EP (0x82) +#define MSC_IFACE_NUM (0) +#define HID_IFACE_NUM_WITH_CDC (0) +#define HID_IFACE_NUM_WITH_MSC (1) +#define HID_IN_EP_WITH_CDC (0x81) +#define HID_IN_EP_WITH_MSC (0x83) + +#define USB_DESC_TYPE_ASSOCIATION (0x0b) + +#define CDC_CMD_PACKET_SIZE 8 // Control Endpoint Packet size +#define CDC_DATA_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +#define MSC_MAX_PACKET 0x40 +#define USB_MSC_CONFIG_DESC_SIZ 32 +#define BOT_GET_MAX_LUN 0xFE +#define BOT_RESET 0xFF + +#define HID_MAX_PACKET 0x04 +#define USB_HID_DESC_SIZ 9 +#define HID_MOUSE_REPORT_DESC_SIZE 74 +#define HID_KEYBOARD_REPORT_DESC_SIZE 63 +#define HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESC 0x22 +#define HID_REQ_SET_PROTOCOL 0x0B +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_GET_IDLE 0x02 + +typedef enum { + HID_IDLE = 0, + HID_BUSY, +} HID_StateTypeDef; + +typedef struct { + uint32_t Protocol; + uint32_t IdleState; + uint32_t AltSetting; + HID_StateTypeDef state; +} USBD_HID_HandleTypeDef; + +static uint8_t usbd_mode; +static uint8_t hid_in_ep; +static uint8_t hid_iface_num; + +static USBD_CDC_ItfTypeDef *CDC_fops; +static USBD_StorageTypeDef *MSC_fops; + +static USBD_CDC_HandleTypeDef CDC_ClassData; +static USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; +static USBD_HID_HandleTypeDef HID_ClassData; + +// I don't think we can make these descriptors constant because they are +// modified (perhaps unnecessarily) by the USB driver. + +// USB Standard Device Descriptor +__ALIGN_BEGIN static uint8_t USBD_CDC_MSC_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, // same for CDC and MSC (latter being MSC_MAX_PACKET), HID is 0x04 + 0x01, + 0x00, +}; + +// USB CDC MSC device Configuration Descriptor +__ALIGN_BEGIN static uint8_t USBD_CDC_MSC_CfgDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] __ALIGN_END = { + //-------------------------------------------------------------------------- + // Configuration Descriptor + 0x09, // bLength: Configuration Descriptor size + USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration + LOBYTE(USB_CDC_MSC_CONFIG_DESC_SIZ), // wTotalLength: no of returned bytes + HIBYTE(USB_CDC_MSC_CONFIG_DESC_SIZ), + 0x03, // bNumInterfaces: 3 interfaces + 0x01, // bConfigurationValue: Configuration value + 0x00, // iConfiguration: Index of string descriptor describing the configuration + 0x80, // bmAttributes: bus powered; 0xc0 for self powered + 0xfa, // bMaxPower: in units of 2mA + + //========================================================================== + // Interface Association for CDC VCP + 0x08, // bLength: 8 bytes + USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD + CDC_IFACE_NUM, // bFirstInterface: first interface for this association + 0x02, // bInterfaceCount: nummber of interfaces for this association + 0x00, // bFunctionClass: ? + 0x00, // bFunctionSubClass: ? + 0x00, // bFunctionProtocol: ? + 0x00, // iFunction: index of string for this function + + //-------------------------------------------------------------------------- + // Interface Descriptor + 0x09, // bLength: Interface Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface + CDC_IFACE_NUM, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x01, // bNumEndpoints: One endpoints used + 0x02, // bInterfaceClass: Communication Interface Class + 0x02, // bInterfaceSubClass: Abstract Control Model + 0x01, // bInterfaceProtocol: Common AT commands + 0x00, // iInterface: + + // Header Functional Descriptor + 0x05, // bLength: Endpoint Descriptor size + 0x24, // bDescriptorType: CS_INTERFACE + 0x00, // bDescriptorSubtype: Header Func Desc + 0x10, // bcdCDC: spec release number + 0x01, // ? + + // Call Management Functional Descriptor + 0x05, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x01, // bDescriptorSubtype: Call Management Func Desc + 0x00, // bmCapabilities: D0+D1 + CDC_IFACE_NUM + 1, // bDataInterface: 1 + + // ACM Functional Descriptor + 0x04, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x02, // bDescriptorSubtype: Abstract Control Management desc + 0x02, // bmCapabilities + + // Union Functional Descriptor + 0x05, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x06, // bDescriptorSubtype: Union func desc + CDC_IFACE_NUM + 0, // bMasterInterface: Communication class interface + CDC_IFACE_NUM + 1, // bSlaveInterface0: Data Class Interface + + // Endpoint 2 Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_CMD_EP, // bEndpointAddress + 0x03, // bmAttributes: Interrupt + LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x20, // bInterval: polling interval in frames of 1ms + + //-------------------------------------------------------------------------- + // Data class interface descriptor + 0x09, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface + CDC_IFACE_NUM + 1, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x02, // bNumEndpoints: Two endpoints used + 0x0A, // bInterfaceClass: CDC + 0x00, // bInterfaceSubClass: ? + 0x00, // bInterfaceProtocol: ? + 0x00, // iInterface: + + // Endpoint OUT Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_OUT_EP, // bEndpointAddress + 0x02, // bmAttributes: Bulk + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, // bInterval: ignore for Bulk transfer + + // Endpoint IN Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_IN_EP, // bEndpointAddress + 0x02, // bmAttributes: Bulk + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, // bInterval: ignore for Bulk transfer + + //========================================================================== + // MSC only has 1 interface so doesn't need an IAD + + //-------------------------------------------------------------------------- + // Interface Descriptor + 0x09, // bLength: Interface Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor + MSC_IFACE_NUM, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x02, // bNumEndpoints + 0x08, // bInterfaceClass: MSC Class + 0x06, // bInterfaceSubClass : SCSI transparent + 0x50, // nInterfaceProtocol + 0x00, // iInterface: + + // Endpoint IN descriptor + 0x07, // bLength: Endpoint descriptor length + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type + MSC_IN_EP, // bEndpointAddress: IN, address 3 + 0x02, // bmAttributes: Bulk endpoint type + LOBYTE(MSC_MAX_PACKET), // wMaxPacketSize + HIBYTE(MSC_MAX_PACKET), + 0x00, // bInterval: ignore for Bulk transfer + + // Endpoint OUT descriptor + 0x07, // bLength: Endpoint descriptor length + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type + MSC_OUT_EP, // bEndpointAddress: OUT, address 3 + 0x02, // bmAttributes: Bulk endpoint type + LOBYTE(MSC_MAX_PACKET), // wMaxPacketSize + HIBYTE(MSC_MAX_PACKET), + 0x00, // bInterval: ignore for Bulk transfer +}; + +// USB CDC HID device Configuration Descriptor +__ALIGN_BEGIN static uint8_t USBD_CDC_HID_CfgDesc[USB_CDC_HID_CONFIG_DESC_SIZ] __ALIGN_END = { + //-------------------------------------------------------------------------- + // Configuration Descriptor + 0x09, // bLength: Configuration Descriptor size + USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration + LOBYTE(USB_CDC_HID_CONFIG_DESC_SIZ), // wTotalLength: no of returned bytes + HIBYTE(USB_CDC_HID_CONFIG_DESC_SIZ), + 0x03, // bNumInterfaces: 3 interfaces + 0x01, // bConfigurationValue: Configuration value + 0x00, // iConfiguration: Index of string descriptor describing the configuration + 0x80, // bmAttributes: bus powered; 0xc0 for self powered + 0xfa, // bMaxPower: in units of 2mA + + //========================================================================== + // Interface Association for CDC VCP + 0x08, // bLength: 8 bytes + USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD + CDC_IFACE_NUM, // bFirstInterface: first interface for this association + 0x02, // bInterfaceCount: nummber of interfaces for this association + 0x00, // bFunctionClass: ? + 0x00, // bFunctionSubClass: ? + 0x00, // bFunctionProtocol: ? + 0x00, // iFunction: index of string for this function + + //-------------------------------------------------------------------------- + // Interface Descriptor + 0x09, // bLength: Interface Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface + CDC_IFACE_NUM, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x01, // bNumEndpoints: One endpoints used + 0x02, // bInterfaceClass: Communication Interface Class + 0x02, // bInterfaceSubClass: Abstract Control Model + 0x01, // bInterfaceProtocol: Common AT commands + 0x00, // iInterface: + + // Header Functional Descriptor + 0x05, // bLength: Endpoint Descriptor size + 0x24, // bDescriptorType: CS_INTERFACE + 0x00, // bDescriptorSubtype: Header Func Desc + 0x10, // bcdCDC: spec release number + 0x01, // ? + + // Call Management Functional Descriptor + 0x05, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x01, // bDescriptorSubtype: Call Management Func Desc + 0x00, // bmCapabilities: D0+D1 + CDC_IFACE_NUM + 1, // bDataInterface: 1 + + // ACM Functional Descriptor + 0x04, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x02, // bDescriptorSubtype: Abstract Control Management desc + 0x02, // bmCapabilities + + // Union Functional Descriptor + 0x05, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x06, // bDescriptorSubtype: Union func desc + CDC_IFACE_NUM + 0, // bMasterInterface: Communication class interface + CDC_IFACE_NUM + 1, // bSlaveInterface0: Data Class Interface + + // Endpoint 2 Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_CMD_EP, // bEndpointAddress + 0x03, // bmAttributes: Interrupt + LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x20, // bInterval: polling interval in frames of 1ms + + //-------------------------------------------------------------------------- + // Data class interface descriptor + 0x09, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface + CDC_IFACE_NUM + 1, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x02, // bNumEndpoints: Two endpoints used + 0x0A, // bInterfaceClass: CDC + 0x00, // bInterfaceSubClass: ? + 0x00, // bInterfaceProtocol: ? + 0x00, // iInterface: + + // Endpoint OUT Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_OUT_EP, // bEndpointAddress + 0x02, // bmAttributes: Bulk + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, // bInterval: ignore for Bulk transfer + + // Endpoint IN Descriptor + 0x07, // bLength: Endpoint Descriptor size + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint + CDC_IN_EP, // bEndpointAddress + 0x02, // bmAttributes: Bulk + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, // bInterval: ignore for Bulk transfer + + //========================================================================== + // HID only has 1 interface so doesn't need an IAD + + //-------------------------------------------------------------------------- + // Interface Descriptor + 0x09, // bLength: Interface Descriptor size + USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor + HID_IFACE_NUM_WITH_CDC, // bInterfaceNumber: Number of Interface + 0x00, // bAlternateSetting: Alternate setting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass: HID Class + 0x01, // bInterfaceSubClass: 1=BOOT, 0=no boot + 0x01, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse + 0x00, // iInterface: + + // HID descriptor + 0x09, // bLength: HID Descriptor size + HID_DESCRIPTOR_TYPE, // bDescriptorType: HID + 0x11, // bcdHID: HID Class Spec release number + 0x01, + 0x00, // bCountryCode: Hardware target country + 0x01, // bNumDescriptors: Number of HID class descriptors to follow + 0x22, // bDescriptorType + HID_MOUSE_REPORT_DESC_SIZE, // wItemLength: Total length of Report descriptor + 0x00, + + // Endpoint IN descriptor + 0x07, // bLength: Endpoint descriptor length + USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type + HID_IN_EP_WITH_CDC, // bEndpointAddress: IN + 0x03, // bmAttributes: Interrupt endpoint type + LOBYTE(HID_MAX_PACKET), // wMaxPacketSize + HIBYTE(HID_MAX_PACKET), + 0x08, // bInterval: Polling interval +}; + +/* USB HID device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END = { + 0x09, /*bLength: HID Descriptor size*/ + HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ + 0x11, /*bcdHID: HID Class Spec release number*/ + 0x01, + 0x00, /*bCountryCode: Hardware target country*/ + 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/ + 0x22, /*bDescriptorType*/ + HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/ + 0x00, +}; + +__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = { + 0x05, 0x01, + 0x09, 0x02, + 0xA1, 0x01, + 0x09, 0x01, + + 0xA1, 0x00, + 0x05, 0x09, + 0x19, 0x01, + 0x29, 0x03, + + 0x15, 0x00, + 0x25, 0x01, + 0x95, 0x03, + 0x75, 0x01, + + 0x81, 0x02, + 0x95, 0x01, + 0x75, 0x05, + 0x81, 0x01, + + 0x05, 0x01, + 0x09, 0x30, + 0x09, 0x31, + 0x09, 0x38, + + 0x15, 0x81, + 0x25, 0x7F, + 0x75, 0x08, + 0x95, 0x03, + + 0x81, 0x06, + 0xC0, 0x09, + 0x3c, 0x05, + 0xff, 0x09, + + 0x01, 0x15, + 0x00, 0x25, + 0x01, 0x75, + 0x01, 0x95, + + 0x02, 0xb1, + 0x22, 0x75, + 0x06, 0x95, + 0x01, 0xb1, + + 0x01, 0xc0 +}; + +#if 0 +__ALIGN_BEGIN static const uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END = { + // From p69 of http://www.usb.org/developers/devclass_docs/HID1_11.pdf + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + 0x05, 0x07, // Usage Page (Key Codes); + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte + 0x95, 0x01, // Report Count (1), + 0x75, 0x08, // Report Size (8), + 0x81, 0x01, // Input (Constant), ;Reserved byte + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (Page# for LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x01, // Output (Constant), ;LED report padding + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x65, // Logical Maximum(101), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x65, // Usage Maximum (101), + 0x81, 0x00, // Input (Data, Array), ;Key arrays (6 bytes) + 0xC0 // End Collection +}; +#endif + +void USBD_SelectMode(uint32_t mode) { + // save mode + usbd_mode = mode; + + // set up HID parameters if HID is selected + if (mode & USBD_MODE_HID) { + if (mode & USBD_MODE_CDC) { + hid_in_ep = HID_IN_EP_WITH_CDC; + hid_iface_num = HID_IFACE_NUM_WITH_CDC; + } else if (mode & USBD_MODE_MSC) { + hid_in_ep = HID_IN_EP_WITH_MSC; + hid_iface_num = HID_IFACE_NUM_WITH_MSC; + } + } +} + +static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { + if (pdev->dev_speed == USBD_SPEED_HIGH) { + // can't handle high speed + return 1; + } + + if (usbd_mode & USBD_MODE_CDC) { + // CDC VCP component + + // Open EP IN + USBD_LL_OpenEP(pdev, + CDC_IN_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_IN_PACKET_SIZE); + + // Open EP OUT + USBD_LL_OpenEP(pdev, + CDC_OUT_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_OUT_PACKET_SIZE); + + // Open Command IN EP + USBD_LL_OpenEP(pdev, + CDC_CMD_EP, + USBD_EP_TYPE_INTR, + CDC_CMD_PACKET_SIZE); + + // Init physical Interface components + CDC_fops->Init(); + + // Init Xfer states + CDC_ClassData.TxState =0; + CDC_ClassData.RxState =0; + + // Prepare Out endpoint to receive next packet + USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, CDC_ClassData.RxBuffer, CDC_DATA_OUT_PACKET_SIZE); + } + + if (usbd_mode & USBD_MODE_MSC) { + // MSC component + + // Open EP OUT + USBD_LL_OpenEP(pdev, + MSC_OUT_EP, + USBD_EP_TYPE_BULK, + MSC_MAX_PACKET); + + // Open EP IN + USBD_LL_OpenEP(pdev, + MSC_IN_EP, + USBD_EP_TYPE_BULK, + MSC_MAX_PACKET); + + // MSC uses the pClassData pointer because SCSI and BOT reference it + pdev->pClassData = &MSC_BOT_ClassData; + + // Init the BOT layer + MSC_BOT_Init(pdev); + } + + if (usbd_mode & USBD_MODE_HID) { + // HID component + + // Open EP IN + USBD_LL_OpenEP(pdev, + hid_in_ep, + USBD_EP_TYPE_INTR, + HID_MAX_PACKET); + + HID_ClassData.state = HID_IDLE; + } + + return 0; +} + +static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { + if (usbd_mode & USBD_MODE_CDC) { + // CDC VCP component + + // close endpoints + USBD_LL_CloseEP(pdev, CDC_IN_EP); + USBD_LL_CloseEP(pdev, CDC_OUT_EP); + USBD_LL_CloseEP(pdev, CDC_CMD_EP); + + // DeInit physical Interface components + CDC_fops->DeInit(); + } + + if (usbd_mode & USBD_MODE_MSC) { + // MSC component + + // close endpoints + USBD_LL_CloseEP(pdev, MSC_OUT_EP); + USBD_LL_CloseEP(pdev, MSC_IN_EP); + + // DeInit the BOT layer + MSC_BOT_DeInit(pdev); + + // clear the pointer + pdev->pClassData = NULL; + } + + if (usbd_mode & USBD_MODE_HID) { + // HID component + + // close endpoints + USBD_LL_CloseEP(pdev, hid_in_ep); + } + + return 0; +} + +static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { + + /* + printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex); + This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2: + SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE + SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING + SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0 + SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE + */ + + switch (req->bmRequest & USB_REQ_TYPE_MASK) { + + // Class request + case USB_REQ_TYPE_CLASS: + // req->wIndex is the recipient interface number + if ((usbd_mode & USBD_MODE_CDC) && req->wIndex == CDC_IFACE_NUM) { + // CDC component + if (req->wLength) { + if (req->bmRequest & 0x80) { + // device-to-host request + CDC_fops->Control(req->bRequest, (uint8_t*)CDC_ClassData.data, req->wLength); + USBD_CtlSendData(pdev, (uint8_t*)CDC_ClassData.data, req->wLength); + } else { + // host-to-device request + CDC_ClassData.CmdOpCode = req->bRequest; + CDC_ClassData.CmdLength = req->wLength; + USBD_CtlPrepareRx(pdev, (uint8_t*)CDC_ClassData.data, req->wLength); + } + } else { + // Not a Data request + // Transfer the command to the interface layer + return CDC_fops->Control(req->bRequest, NULL, req->wValue); + } + } else if ((usbd_mode & USBD_MODE_MSC) && req->wIndex == MSC_IFACE_NUM) { + // MSC component + switch (req->bRequest) { + case BOT_GET_MAX_LUN: + if ((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { + MSC_BOT_ClassData.max_lun = MSC_fops->GetMaxLun(); + USBD_CtlSendData(pdev, (uint8_t *)&MSC_BOT_ClassData.max_lun, 1); + } else { + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + break; + + case BOT_RESET: + if((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { + MSC_BOT_Reset(pdev); + } else { + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + break; + + default: + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + } else if ((usbd_mode & USBD_MODE_HID) && req->wIndex == hid_iface_num) { + switch (req->bRequest) { + case HID_REQ_SET_PROTOCOL: + HID_ClassData.Protocol = (uint8_t)(req->wValue); + break; + + case HID_REQ_GET_PROTOCOL: + USBD_CtlSendData (pdev, (uint8_t *)&HID_ClassData.Protocol, 1); + break; + + case HID_REQ_SET_IDLE: + HID_ClassData.IdleState = (uint8_t)(req->wValue >> 8); + break; + + case HID_REQ_GET_IDLE: + USBD_CtlSendData (pdev, (uint8_t *)&HID_ClassData.IdleState, 1); + break; + + default: + USBD_CtlError(pdev, req); + return USBD_FAIL; + } + } + break; + + // Interface & Endpoint request + case USB_REQ_TYPE_STANDARD: + if ((usbd_mode & USBD_MODE_MSC) && req->wIndex == MSC_IFACE_NUM) { + switch (req->bRequest) { + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData(pdev, (uint8_t *)&MSC_BOT_ClassData.interface, 1); + break; + + case USB_REQ_SET_INTERFACE : + MSC_BOT_ClassData.interface = (uint8_t)(req->wValue); + break; + + case USB_REQ_CLEAR_FEATURE: + /* Flush the FIFO and Clear the stall status */ + USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex); + + /* Re-activate the EP */ + USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex); + if((((uint8_t)req->wIndex) & 0x80) == 0x80) { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, MSC_IN_EP, USBD_EP_TYPE_BULK, MSC_MAX_PACKET); + } else { + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, MSC_OUT_EP, USBD_EP_TYPE_BULK, MSC_MAX_PACKET); + } + /* Handle BOT error */ + MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); + break; + } + } else if ((usbd_mode & USBD_MODE_HID) && req->wIndex == hid_iface_num) { + switch (req->bRequest) { + case USB_REQ_GET_DESCRIPTOR: { + uint16_t len = 0; + const uint8_t *pbuf = NULL; + if (req->wValue >> 8 == HID_REPORT_DESC) { + len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength); + pbuf = HID_MOUSE_ReportDesc; + } else if (req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { + len = MIN(USB_HID_DESC_SIZ , req->wLength); + pbuf = USBD_HID_Desc; + } + USBD_CtlSendData(pdev, (uint8_t*)pbuf, len); + break; + } + + case USB_REQ_GET_INTERFACE: + USBD_CtlSendData (pdev, (uint8_t *)&HID_ClassData.AltSetting, 1); + break; + + case USB_REQ_SET_INTERFACE: + HID_ClassData.AltSetting = (uint8_t)(req->wValue); + break; + } + } + break; + } + return USBD_OK; +} + +static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { + if((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xFF)) { + CDC_fops->Control(CDC_ClassData.CmdOpCode, (uint8_t *)CDC_ClassData.data, CDC_ClassData.CmdLength); + CDC_ClassData.CmdOpCode = 0xFF; + } + return USBD_OK; +} + +static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { + if ((usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) { + CDC_ClassData.TxState = 0; + return USBD_OK; + } else if ((usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { + MSC_BOT_DataIn(pdev, epnum); + return USBD_OK; + } else if ((usbd_mode & USBD_MODE_HID) && epnum == (hid_in_ep & 0x7f)) { + /* Ensure that the FIFO is empty before a new transfer, this condition could + be caused by a new transfer before the end of the previous transfer */ + HID_ClassData.state = HID_IDLE; + return USBD_OK; + } + + return USBD_OK; +} + +static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { + if ((usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) { + /* Get the received data length */ + CDC_ClassData.RxLength = USBD_LL_GetRxDataSize (pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + CDC_fops->Receive(CDC_ClassData.RxBuffer, &CDC_ClassData.RxLength); + + return USBD_OK; + } else if ((usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { + MSC_BOT_DataOut(pdev, epnum); + return USBD_OK; + } + + return USBD_OK; +} + +static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(uint16_t *length) { + switch (usbd_mode) { + case USBD_MODE_CDC_MSC: + *length = sizeof(USBD_CDC_MSC_CfgDesc); + return USBD_CDC_MSC_CfgDesc; + + case USBD_MODE_CDC_HID: + default: + *length = sizeof(USBD_CDC_HID_CfgDesc); + return USBD_CDC_HID_CfgDesc; + } +} + +uint8_t *USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor (uint16_t *length) { + *length = sizeof(USBD_CDC_MSC_HID_DeviceQualifierDesc); + return USBD_CDC_MSC_HID_DeviceQualifierDesc; +} + +uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops) { + if (fops == NULL) { + return USBD_FAIL; + } else { + CDC_fops = fops; + return USBD_OK; + } +} + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length) +{ + CDC_ClassData.TxBuffer = pbuff; + CDC_ClassData.TxLength = length; + + return USBD_OK; +} + + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff) +{ + CDC_ClassData.RxBuffer = pbuff; + + return USBD_OK; +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) { + if(CDC_ClassData.TxState == 0) { + + /* Transmit next packet */ + USBD_LL_Transmit(pdev, + CDC_IN_EP, + CDC_ClassData.TxBuffer, + CDC_ClassData.TxLength); + + /* Tx Transfer in progress */ + CDC_ClassData.TxState = 1; + return USBD_OK; + } + else + { + return USBD_BUSY; + } +} + + +/** + * @brief USBD_CDC_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) { + // Suspend or Resume USB Out process + if (pdev->dev_speed == USBD_SPEED_HIGH) { + return USBD_FAIL; + } + + // Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + CDC_ClassData.RxBuffer, + CDC_DATA_OUT_PACKET_SIZE); + + return USBD_OK; +} + +uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops) { + if (fops == NULL) { + return USBD_FAIL; + } else { + MSC_fops = fops; + pdev->pUserData = fops; // MSC uses pUserData because SCSI and BOT reference it + return USBD_OK; + } +} + +uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) { + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + if (HID_ClassData.state == HID_IDLE) { + HID_ClassData.state = HID_BUSY; + USBD_LL_Transmit(pdev, hid_in_ep, report, len); + } + } + return USBD_OK; +} + +// CDC + MSC interface class callbacks structure +USBD_ClassTypeDef USBD_CDC_MSC_HID = { + USBD_CDC_MSC_HID_Init, + USBD_CDC_MSC_HID_DeInit, + USBD_CDC_MSC_HID_Setup, + NULL, // EP0_TxSent + USBD_CDC_MSC_HID_EP0_RxReady, + USBD_CDC_MSC_HID_DataIn, + USBD_CDC_MSC_HID_DataOut, + NULL, // SOF + NULL, + NULL, + USBD_CDC_MSC_HID_GetCfgDesc, + USBD_CDC_MSC_HID_GetCfgDesc, + USBD_CDC_MSC_HID_GetCfgDesc, + USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor, +}; diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc.c new file mode 100644 index 0000000000..7817c98b1c --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc.c @@ -0,0 +1,609 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_core.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @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
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc.h"
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_CORE
+ * @brief Mass storage core module
+ * @{
+ */
+
+/** @defgroup MSC_CORE_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_FunctionPrototypes
+ * @{
+ */
+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);
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Variables
+ * @{
+ */
+
+
+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 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 */
+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 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 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,
+};
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_CORE_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief USBD_MSC_Init
+ * Initialize the mass storage configuration
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+uint8_t USBD_MSC_Init (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx)
+{
+ int16_t ret = 0;
+
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP OUT */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP OUT */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ pdev->pClassData = USBD_malloc(sizeof (USBD_MSC_BOT_HandleTypeDef));
+
+ if(pdev->pClassData == NULL)
+ {
+ ret = 1;
+ }
+ else
+ {
+ /* Init the BOT layer */
+ MSC_BOT_Init(pdev);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USBD_MSC_DeInit
+ * DeInitilaize the mass storage configuration
+ * @param pdev: device instance
+ * @param cfgidx: configuration index
+ * @retval status
+ */
+uint8_t USBD_MSC_DeInit (USBD_HandleTypeDef *pdev,
+ uint8_t cfgidx)
+{
+ /* Close MSC EPs */
+ USBD_LL_CloseEP(pdev,
+ MSC_EPOUT_ADDR);
+
+ /* Open EP IN */
+ USBD_LL_CloseEP(pdev,
+ MSC_EPIN_ADDR);
+
+
+ /* D-Init the BOT layer */
+ MSC_BOT_DeInit(pdev);
+
+ /* Free MSC Class Resources */
+ if(pdev->pClassData != NULL)
+ {
+ USBD_free(pdev->pClassData);
+ pdev->pClassData = NULL;
+ }
+ return 0;
+}
+/**
+* @brief USBD_MSC_Setup
+* Handle the MSC specific requests
+* @param pdev: device instance
+* @param req: USB request
+* @retval status
+*/
+uint8_t USBD_MSC_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ switch (req->bmRequest & USB_REQ_TYPE_MASK)
+ {
+
+ /* Class request */
+ case USB_REQ_TYPE_CLASS :
+ switch (req->bRequest)
+ {
+ case BOT_GET_MAX_LUN :
+
+ if((req->wValue == 0) &&
+ (req->wLength == 1) &&
+ ((req->bmRequest & 0x80) == 0x80))
+ {
+ hmsc->max_lun = ((USBD_StorageTypeDef *)pdev->pUserData)->GetMaxLun();
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&hmsc->max_lun,
+ 1);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ case BOT_RESET :
+ if((req->wValue == 0) &&
+ (req->wLength == 0) &&
+ ((req->bmRequest & 0x80) != 0x80))
+ {
+ MSC_BOT_Reset(pdev);
+ }
+ else
+ {
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+
+ default:
+ USBD_CtlError(pdev , req);
+ return USBD_FAIL;
+ }
+ break;
+ /* Interface & Endpoint request */
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->bRequest)
+ {
+ case USB_REQ_GET_INTERFACE :
+ USBD_CtlSendData (pdev,
+ (uint8_t *)&hmsc->interface,
+ 1);
+ break;
+
+ case USB_REQ_SET_INTERFACE :
+ hmsc->interface = (uint8_t)(req->wValue);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+
+ /* Flush the FIFO and Clear the stall status */
+ USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
+
+ /* Re-activate the EP */
+ USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex);
+ if((((uint8_t)req->wIndex) & 0x80) == 0x80)
+ {
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPIN_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ }
+ else
+ {
+ if(pdev->dev_speed == USBD_SPEED_HIGH )
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_HS_PACKET);
+ }
+ else
+ {
+ /* Open EP IN */
+ USBD_LL_OpenEP(pdev,
+ MSC_EPOUT_ADDR,
+ USBD_EP_TYPE_BULK,
+ MSC_MAX_FS_PACKET);
+ }
+ }
+
+ /* Handle BOT error */
+ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
+ break;
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+* @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 0;
+}
+
+/**
+* @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 0;
+}
+
+/**
+* @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 = 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 = 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 = 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 = 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)
+ {
+ pdev->pUserData= fops;
+ }
+ return 0;
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_bot.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_bot.c new file mode 100644 index 0000000000..3c06f3cf68 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_bot.c @@ -0,0 +1,407 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_bot.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the BOT protocol core functions.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_cdc_msc_hid.h"
+#include "usbd_ioreq.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_BOT
+ * @brief BOT protocol module
+ * @{
+ */
+
+/** @defgroup MSC_BOT_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_FunctionPrototypes
+ * @{
+ */
+static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev);
+
+static void MSC_BOT_SendData (USBD_HandleTypeDef *pdev,
+ uint8_t* pbuf,
+ uint16_t len);
+
+static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_BOT_Private_Functions
+ * @{
+ */
+
+
+
+/**
+* @brief MSC_BOT_Init
+* Initialize the BOT Process
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_Init (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_state = USBD_BOT_IDLE;
+ hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
+
+ hmsc->scsi_sense_tail = 0;
+ hmsc->scsi_sense_head = 0;
+
+ ((USBD_StorageTypeDef *)pdev->pUserData)->Init(0);
+
+ USBD_LL_FlushEP(pdev, MSC_OUT_EP);
+ USBD_LL_FlushEP(pdev, MSC_IN_EP);
+
+ /* Prapare EP to Receive First BOT Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+}
+
+/**
+* @brief MSC_BOT_Reset
+* Reset the BOT Machine
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_Reset (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_state = USBD_BOT_IDLE;
+ hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
+
+ /* Prapare EP to Receive First BOT Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+}
+
+/**
+* @brief MSC_BOT_DeInit
+* Uninitialize the BOT Machine
+* @param pdev: device instance
+* @retval None
+*/
+void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ hmsc->bot_state = USBD_BOT_IDLE;
+}
+
+/**
+* @brief MSC_BOT_DataIn
+* Handle BOT IN data stage
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ 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
+* Proccess MSC OUT data
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
+ uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ 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 accordingtly
+* @param pdev: device instance
+* @retval None
+*/
+static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->csw.dTag = hmsc->cbw.dTag;
+ hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
+
+ if ((USBD_LL_GetRxDataSize (pdev ,MSC_OUT_EP) != USBD_BOT_CBW_LENGTH) ||
+ (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)||
+ (hmsc->cbw.bLUN > 1) ||
+ (hmsc->cbw.bCBLength < 1) ||
+ (hmsc->cbw.bCBLength > 16))
+ {
+
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+
+ hmsc->bot_status = USBD_BOT_STATUS_ERROR;
+ MSC_BOT_Abort(pdev);
+
+ }
+ else
+ {
+ if(SCSI_ProcessCmd(pdev,
+ hmsc->cbw.bLUN,
+ &hmsc->cbw.CB[0]) < 0)
+ {
+ if(hmsc->bot_state == USBD_BOT_NO_DATA)
+ {
+ MSC_BOT_SendCSW (pdev,
+ USBD_CSW_CMD_FAILED);
+ }
+ else
+ {
+ MSC_BOT_Abort(pdev);
+ }
+ }
+ /*Burst xfer handled internally*/
+ else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
+ (hmsc->bot_state != USBD_BOT_DATA_OUT) &&
+ (hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
+ {
+ if (hmsc->bot_data_length > 0)
+ {
+ MSC_BOT_SendData(pdev,
+ hmsc->bot_data,
+ hmsc->bot_data_length);
+ }
+ else if (hmsc->bot_data_length == 0)
+ {
+ MSC_BOT_SendCSW (pdev,
+ USBD_CSW_CMD_PASSED);
+ }
+ }
+ }
+}
+
+/**
+* @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* buf,
+ uint16_t len)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ len = MIN (hmsc->cbw.dDataLength, len);
+ hmsc->csw.dDataResidue -= len;
+ hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
+ hmsc->bot_state = USBD_BOT_SEND_DATA;
+
+ USBD_LL_Transmit (pdev, MSC_IN_EP, buf, len);
+}
+
+/**
+* @brief MSC_BOT_SendCSW
+* Send the Command Status Wrapper
+* @param pdev: device instance
+* @param status : CSW status
+* @retval None
+*/
+void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
+ uint8_t CSW_Status)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
+ hmsc->csw.bStatus = CSW_Status;
+ hmsc->bot_state = USBD_BOT_IDLE;
+
+ USBD_LL_Transmit (pdev,
+ MSC_IN_EP,
+ (uint8_t *)&hmsc->csw,
+ USBD_BOT_CSW_LENGTH);
+
+ /* Prapare EP to Receive next Cmd */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (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 = pdev->pClassData;
+
+ if ((hmsc->cbw.bmFlags == 0) &&
+ (hmsc->cbw.dDataLength != 0) &&
+ (hmsc->bot_status == USBD_BOT_STATUS_NORMAL) )
+ {
+ USBD_LL_StallEP(pdev, MSC_OUT_EP );
+ }
+ USBD_LL_StallEP(pdev, MSC_IN_EP);
+
+ if(hmsc->bot_status == USBD_BOT_STATUS_ERROR)
+ {
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ (uint8_t *)&hmsc->cbw,
+ USBD_BOT_CBW_LENGTH);
+ }
+}
+
+/**
+* @brief MSC_BOT_CplClrFeature
+* Complete the clear feature request
+* @param pdev: device instance
+* @param epnum: endpoint index
+* @retval None
+*/
+
+void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */
+ {
+ USBD_LL_StallEP(pdev, MSC_IN_EP);
+ hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
+ }
+ else if(((epnum & 0x80) == 0x80) && ( hmsc->bot_status != USBD_BOT_STATUS_RECOVERY))
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
+ }
+
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_data.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_data.c new file mode 100644 index 0000000000..4d72bd5fce --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_data.c @@ -0,0 +1,134 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_data.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the vital inquiry pages and sense data.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_data.h"
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_DATA
+ * @brief Mass storage info/data module
+ * @{
+ */
+
+/** @defgroup MSC_DATA_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Defines
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Variables
+ * @{
+ */
+
+
+/* USB Mass storage Page 0 Inquiry Data */
+const uint8_t MSC_Page00_Inquiry_Data[] = {//7
+ 0x00,
+ 0x00,
+ 0x00,
+ (LENGTH_INQUIRY_PAGE00 - 4),
+ 0x00,
+ 0x80,
+ 0x83
+};
+/* USB Mass storage sense 6 Data */
+const uint8_t MSC_Mode_Sense6_data[] = {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+/* USB Mass storage sense 10 Data */
+const uint8_t MSC_Mode_Sense10_data[] = {
+ 0x00,
+ 0x06,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_FunctionPrototypes
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_DATA_Private_Functions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c new file mode 100644 index 0000000000..af3818d373 --- /dev/null +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c @@ -0,0 +1,770 @@ +/**
+ ******************************************************************************
+ * @file usbd_msc_scsi.c
+ * @author MCD Application Team
+ * @version V2.0.0
+ * @date 18-February-2014
+ * @brief This file provides all the USBD SCSI layer functions.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_msc_data.h"
+#include "usbd_cdc_msc_hid.h"
+
+
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+
+/** @defgroup MSC_SCSI
+ * @brief Mass storage SCSI layer module
+ * @{
+ */
+
+/** @defgroup MSC_SCSI_Private_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_FunctionPrototypes
+ * @{
+ */
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
+static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
+static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev,
+ uint8_t lun ,
+ uint32_t blk_offset ,
+ uint16_t blk_nbr);
+static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev,
+ uint8_t lun);
+
+static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev,
+ uint8_t lun);
+/**
+ * @}
+ */
+
+
+/** @defgroup MSC_SCSI_Private_Functions
+ * @{
+ */
+
+
+/**
+* @brief SCSI_ProcessCmd
+* Process SCSI commands
+* @param pdev: device instance
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
+ uint8_t lun,
+ uint8_t *params)
+{
+
+ switch (params[0])
+ {
+ case SCSI_TEST_UNIT_READY:
+ return SCSI_TestUnitReady(pdev, lun, params);
+
+ case SCSI_REQUEST_SENSE:
+ return SCSI_RequestSense (pdev, lun, params);
+ case SCSI_INQUIRY:
+ return SCSI_Inquiry(pdev, lun, params);
+
+ case SCSI_START_STOP_UNIT:
+ return SCSI_StartStopUnit(pdev, lun, params);
+
+ case SCSI_ALLOW_MEDIUM_REMOVAL:
+ return SCSI_StartStopUnit(pdev, lun, params);
+
+ case SCSI_MODE_SENSE6:
+ return SCSI_ModeSense6 (pdev, lun, params);
+
+ case SCSI_MODE_SENSE10:
+ return SCSI_ModeSense10 (pdev, lun, params);
+
+ case SCSI_READ_FORMAT_CAPACITIES:
+ return SCSI_ReadFormatCapacity(pdev, lun, params);
+
+ case SCSI_READ_CAPACITY10:
+ return SCSI_ReadCapacity10(pdev, lun, params);
+
+ case SCSI_READ10:
+ return SCSI_Read10(pdev, lun, params);
+
+ case SCSI_WRITE10:
+ return SCSI_Write10(pdev, lun, params);
+
+ case SCSI_VERIFY10:
+ return SCSI_Verify10(pdev, lun, params);
+
+ default:
+ SCSI_SenseCode(pdev,
+ lun,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+}
+
+
+/**
+* @brief SCSI_TestUnitReady
+* Process SCSI Test Unit Ready Command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ /* case 9 : Hi > D0 */
+ if (hmsc->cbw.dDataLength != 0)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->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 = 0;
+ 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 = pdev->pClassData;
+
+ if (params[1] & 0x01)/*Evpd is set*/
+ {
+ pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
+ len = LENGTH_INQUIRY_PAGE00;
+ }
+ else
+ {
+
+ pPage = (uint8_t *)&((USBD_StorageTypeDef *)pdev->pUserData)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];
+ len = pPage[4] + 5;
+
+ if (params[4] <= len)
+ {
+ len = params[4];
+ }
+ }
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = pPage[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ReadCapacity10
+* Process Read Capacity 10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+ else
+ {
+
+ hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24);
+ hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16);
+ hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8);
+ hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1);
+
+ 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 = 8;
+ return 0;
+ }
+}
+/**
+* @brief SCSI_ReadFormatCapacity
+* Process Read Format Capacity command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ uint16_t blk_size;
+ uint32_t blk_nbr;
+ uint16_t i;
+
+ for(i=0 ; i < 12 ; i++)
+ {
+ hmsc->bot_data[i] = 0;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+ else
+ {
+ hmsc->bot_data[3] = 0x08;
+ hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
+ hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
+ hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8);
+ hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
+
+ hmsc->bot_data[8] = 0x02;
+ 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 = 12;
+ return 0;
+ }
+}
+/**
+* @brief SCSI_ModeSense6
+* Process Mode Sense6 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ uint16_t len = 8 ;
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_ModeSense10
+* Process Mode Sense10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ uint16_t len = 8;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->bot_data_length = len;
+
+ while (len)
+ {
+ len--;
+ hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_RequestSense
+* Process Request Sense command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+
+static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ uint8_t i;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
+ {
+ hmsc->bot_data[i] = 0;
+ }
+
+ hmsc->bot_data[0] = 0x70;
+ hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
+
+ if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
+
+ hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
+ hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
+ hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
+ hmsc->scsi_sense_head++;
+
+ if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
+ {
+ hmsc->scsi_sense_head = 0;
+ }
+ }
+ hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
+
+ if (params[4] <= REQUEST_SENSE_DATA_LEN)
+ {
+ hmsc->bot_data_length = params[4];
+ }
+ return 0;
+}
+
+/**
+* @brief SCSI_SenseCode
+* Load the last error code in the error list
+* @param lun: Logical unit number
+* @param sKey: Sense Key
+* @param ASC: Additional Sense Key
+* @retval none
+
+*/
+void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
+ hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
+ hmsc->scsi_sense_tail++;
+ if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
+ {
+ hmsc->scsi_sense_tail = 0;
+ }
+}
+/**
+* @brief SCSI_StartStopUnit
+* Process Start Stop Unit command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ hmsc->bot_data_length = 0;
+ 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 = pdev->pClassData;
+
+ if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
+ {
+
+ /* case 10 : Ho <> Di */
+
+ if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+
+ hmsc->scsi_blk_addr = (params[2] << 24) | \
+ (params[3] << 16) | \
+ (params[4] << 8) | \
+ params[5];
+
+ hmsc->scsi_blk_len = (params[7] << 8) | \
+ params[8];
+
+
+
+ if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
+ {
+ return -1; /* error */
+ }
+
+ hmsc->bot_state = USBD_BOT_DATA_IN;
+ hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
+ hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
+
+ /* cases 4,5 : Hi <> Dn */
+ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+ }
+ hmsc->bot_data_length = MSC_MEDIA_PACKET;
+
+ return SCSI_ProcessRead(pdev, lun);
+}
+
+/**
+* @brief SCSI_Write10
+* Process Write10 command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+
+static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
+ {
+
+ /* case 8 : Hi <> Do */
+
+ if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ /* Check whether Media is ready */
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ MEDIUM_NOT_PRESENT);
+ return -1;
+ }
+
+ /* Check If media is write-protected */
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ NOT_READY,
+ WRITE_PROTECTED);
+ return -1;
+ }
+
+
+ hmsc->scsi_blk_addr = (params[2] << 24) | \
+ (params[3] << 16) | \
+ (params[4] << 8) | \
+ params[5];
+ hmsc->scsi_blk_len = (params[7] << 8) | \
+ 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 */
+ }
+
+ hmsc->scsi_blk_addr *= hmsc->scsi_blk_size;
+ hmsc->scsi_blk_len *= hmsc->scsi_blk_size;
+
+ /* cases 3,11,13 : Hn,Ho <> D0 */
+ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
+ {
+ SCSI_SenseCode(pdev,
+ hmsc->cbw.bLUN,
+ ILLEGAL_REQUEST,
+ INVALID_CDB);
+ return -1;
+ }
+
+ /* Prepare EP to receive first data packet */
+ hmsc->bot_state = USBD_BOT_DATA_OUT;
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ hmsc->bot_data,
+ MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
+ }
+ 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 = pdev->pClassData;
+
+ if ((params[1]& 0x02) == 0x02)
+ {
+ 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 = 0;
+ 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 , uint16_t blk_nbr)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ 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 = pdev->pClassData;
+ uint32_t len;
+
+ len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
+
+ if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
+ hmsc->bot_data,
+ hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
+ len / hmsc->scsi_blk_size) < 0)
+ {
+
+ SCSI_SenseCode(pdev,
+ lun,
+ HARDWARE_ERROR,
+ UNRECOVERED_READ_ERROR);
+ return -1;
+ }
+
+
+ USBD_LL_Transmit (pdev,
+ MSC_IN_EP,
+ hmsc->bot_data,
+ len);
+
+
+ hmsc->scsi_blk_addr += len;
+ hmsc->scsi_blk_len -= len;
+
+ /* case 6 : Hi = Di */
+ hmsc->csw.dDataResidue -= len;
+
+ if (hmsc->scsi_blk_len == 0)
+ {
+ 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)
+{
+ uint32_t len;
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+
+ len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
+
+ if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
+ hmsc->bot_data,
+ hmsc->scsi_blk_addr / hmsc->scsi_blk_size,
+ len / hmsc->scsi_blk_size) < 0)
+ {
+ SCSI_SenseCode(pdev,
+ lun,
+ HARDWARE_ERROR,
+ WRITE_FAULT);
+ return -1;
+ }
+
+
+ hmsc->scsi_blk_addr += len;
+ hmsc->scsi_blk_len -= len;
+
+ /* case 12 : Ho = Do */
+ hmsc->csw.dDataResidue -= len;
+
+ if (hmsc->scsi_blk_len == 0)
+ {
+ MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
+ }
+ else
+ {
+ /* Prapare EP to Receive next packet */
+ USBD_LL_PrepareReceive (pdev,
+ MSC_OUT_EP,
+ hmsc->bot_data,
+ MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET));
+ }
+
+ return 0;
+}
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c index 69a03b2cc3..60032c4ecb 100644 --- a/stmhal/usrsw.c +++ b/stmhal/usrsw.c @@ -39,6 +39,17 @@ static mp_obj_t switch_callback(mp_obj_t line) { } static MP_DEFINE_CONST_FUN_OBJ_1(switch_callback_obj, switch_callback); +// this function inits the switch GPIO so that it can be used +void switch_init0(void) { + GPIO_InitTypeDef init; + init.Pin = USRSW_PIN.pin_mask; + init.Mode = GPIO_MODE_INPUT; + init.Pull = USRSW_PULL; + init.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(USRSW_PIN.gpio, &init); +} + +// this function inits the callback and EXTI function of the switch void switch_init(void) { switch_user_callback_obj = mp_const_none; exti_register((mp_obj_t)&USRSW_PIN, diff --git a/stmhal/usrsw.h b/stmhal/usrsw.h index 2da8f069ba..b1b838653f 100644 --- a/stmhal/usrsw.h +++ b/stmhal/usrsw.h @@ -1,3 +1,4 @@ +void switch_init0(void); void switch_init(void); int switch_get(void); |