From 53200247b779358ffa03e1b7a8d1e9964befc234 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 16:10:52 +1000 Subject: [PATCH] stm32/usb: Add "msc" kw-arg to pyb.usb_mode to select MSC logical units. With this the user can select multiple logical units to expose over USB MSC at once, eg: pyb.usb_mode('VCP+MSC', msc=(pyb.Flash(), pyb.SDCard())). The default behaviour is the original behaviour of just one unit at a time. --- ports/stm32/main.c | 2 +- ports/stm32/usb.c | 57 ++++++++++++++++++++++++-------- ports/stm32/usb.h | 2 +- ports/stm32/usbd_msc_interface.c | 2 -- ports/stm32/usbd_msc_interface.h | 2 ++ 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 3852ff9b0..44e29921b 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -645,7 +645,7 @@ soft_reset: #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { - pyb_usb_dev_init(USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, NULL); + pyb_usb_dev_init(USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, 0, NULL, NULL); } #endif diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 158265411..3e432fc8e 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -120,7 +120,7 @@ void pyb_usb_init0(void) { pyb_usb_vcp_init0(); } -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime @@ -146,18 +146,22 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInf } // Configure the MSC interface - const void *lu[1]; - switch (pyb_usb_storage_medium) { - #if MICROPY_HW_ENABLE_SDCARD - case PYB_USB_STORAGE_MEDIUM_SDCARD: - lu[0] = &pyb_sdcard_type; - break; - #endif - default: - lu[0] = &pyb_flash_type; - break; + const void *msc_unit_default[1]; + if (msc_n == 0) { + msc_n = 1; + msc_unit = msc_unit_default; + switch (pyb_usb_storage_medium) { + #if MICROPY_HW_ENABLE_SDCARD + case PYB_USB_STORAGE_MEDIUM_SDCARD: + msc_unit_default[0] = &pyb_sdcard_type; + break; + #endif + default: + msc_unit_default[0] = &pyb_flash_type; + break; + } } - usbd_msc_init_lu(1, lu); + usbd_msc_init_lu(msc_n, msc_unit); USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); // start the USB device @@ -226,11 +230,12 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_vid, ARG_pid, ARG_hid, ARG_high_speed }; + enum { ARG_mode, ARG_vid, ARG_pid, ARG_msc, ARG_hid, ARG_high_speed }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_msc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_empty_tuple_obj)} }, { MP_QSTR_hid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&pyb_usb_hid_mouse_obj)} }, #if USBD_SUPPORT_HS_MODE { MP_QSTR_high_speed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, @@ -347,6 +352,30 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * goto bad_mode; } + // Get MSC logical units + size_t msc_n = 0; + const void *msc_unit[USBD_MSC_MAX_LUN]; + if (mode & USBD_MODE_IFACE_MSC) { + mp_obj_t *items; + mp_obj_get_array(args[ARG_msc].u_obj, &msc_n, &items); + if (msc_n > USBD_MSC_MAX_LUN) { + mp_raise_ValueError("too many logical units"); + } + for (size_t i = 0; i < msc_n; ++i) { + mp_obj_type_t *type = mp_obj_get_type(items[i]); + if (type == &pyb_flash_type + || type == &pyb_sdcard_type + #if MICROPY_HW_ENABLE_MMCARD + || type == &pyb_mmcard_type + #endif + ) { + msc_unit[i] = type; + } else { + mp_raise_ValueError("unsupported logical unit"); + } + } + } + // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; if (mode & USBD_MODE_IFACE_HID) { @@ -372,7 +401,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * #endif // init the USB device - if (!pyb_usb_dev_init(vid, pid, mode, &hid_info)) { + if (!pyb_usb_dev_init(vid, pid, mode, msc_n, msc_unit, &hid_info)) { goto bad_mode; } diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 0aa50f9e7..b1c8b476a 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -66,7 +66,7 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 0148fc7c6..1f9f68ed8 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -33,8 +33,6 @@ #include "storage.h" #include "sdcard.h" -#define USBD_MSC_MAX_LUN (2) - // This flag is needed to support removal of the medium, so that the USB drive // can be unmounted and won't be remounted automatically. #define FLAGS_STARTED (0x01) diff --git a/ports/stm32/usbd_msc_interface.h b/ports/stm32/usbd_msc_interface.h index 9d25a72a3..411c707ca 100644 --- a/ports/stm32/usbd_msc_interface.h +++ b/ports/stm32/usbd_msc_interface.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H +#define USBD_MSC_MAX_LUN (2) + extern const USBD_StorageTypeDef usbd_msc_fops; void usbd_msc_init_lu(size_t lu_n, const void *lu_data);