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.
This commit is contained in:
Damien George 2019-06-11 16:10:52 +10:00
parent 9e68eec8ea
commit 53200247b7
5 changed files with 47 additions and 18 deletions

View File

@ -645,7 +645,7 @@ soft_reset:
#if MICROPY_HW_ENABLE_USB #if MICROPY_HW_ENABLE_USB
// init USB device to default setting if it was not already configured // init USB device to default setting if it was not already configured
if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { 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 #endif

View File

@ -120,7 +120,7 @@ void pyb_usb_init0(void) {
pyb_usb_vcp_init0(); 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; usb_device_t *usb_dev = &usb_device;
if (!usb_dev->enabled) { if (!usb_dev->enabled) {
// only init USB once in the device's power-lifetime // 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 // Configure the MSC interface
const void *lu[1]; const void *msc_unit_default[1];
if (msc_n == 0) {
msc_n = 1;
msc_unit = msc_unit_default;
switch (pyb_usb_storage_medium) { switch (pyb_usb_storage_medium) {
#if MICROPY_HW_ENABLE_SDCARD #if MICROPY_HW_ENABLE_SDCARD
case PYB_USB_STORAGE_MEDIUM_SDCARD: case PYB_USB_STORAGE_MEDIUM_SDCARD:
lu[0] = &pyb_sdcard_type; msc_unit_default[0] = &pyb_sdcard_type;
break; break;
#endif #endif
default: default:
lu[0] = &pyb_flash_type; msc_unit_default[0] = &pyb_flash_type;
break; 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); USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops);
// start the USB device // 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) { 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[] = { 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_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_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_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)} }, { 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 #if USBD_SUPPORT_HS_MODE
{ MP_QSTR_high_speed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { 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; 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 // get hid info if user selected such a mode
USBD_HID_ModeInfoTypeDef hid_info; USBD_HID_ModeInfoTypeDef hid_info;
if (mode & USBD_MODE_IFACE_HID) { 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 #endif
// init the USB device // 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; goto bad_mode;
} }

View File

@ -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 MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated
void pyb_usb_init0(void); 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); void pyb_usb_dev_deinit(void);
bool usb_vcp_is_enabled(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 int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0

View File

@ -33,8 +33,6 @@
#include "storage.h" #include "storage.h"
#include "sdcard.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 // This flag is needed to support removal of the medium, so that the USB drive
// can be unmounted and won't be remounted automatically. // can be unmounted and won't be remounted automatically.
#define FLAGS_STARTED (0x01) #define FLAGS_STARTED (0x01)

View File

@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H
#define 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; extern const USBD_StorageTypeDef usbd_msc_fops;
void usbd_msc_init_lu(size_t lu_n, const void *lu_data); void usbd_msc_init_lu(size_t lu_n, const void *lu_data);