stm32/usb: Refactor CDC VCP code to enable N CDC interfaces.

The board config option MICROPY_HW_USB_ENABLE_CDC2 is now changed to
MICROPY_HW_USB_CDC_NUM, and the latter should be defined to the maximum
number of CDC interfaces to support (defaults to 1).
This commit is contained in:
Damien George 2019-05-18 23:01:36 +10:00
parent a4f1d82757
commit 0c29502ad9
9 changed files with 183 additions and 225 deletions

View File

@ -558,10 +558,6 @@ soft_reset:
#if MICROPY_HW_ENABLE_USB
pyb_usb_init0();
// Activate USB_VCP(0) on dupterm slot 1 for the REPL
MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj);
usb_vcp_attach_to_repl(&pyb_usb_vcp_obj, true);
#endif
// Initialise the local flash filesystem.

View File

@ -264,6 +264,10 @@
#define MICROPY_HW_MAX_CAN (1)
#endif
// Configure maximum number of CDC VCP interfaces
#ifndef MICROPY_HW_USB_CDC_NUM
#define MICROPY_HW_USB_CDC_NUM (1)
#endif
// Pin definition header file
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h"

View File

@ -55,6 +55,8 @@
#endif
#endif
STATIC void pyb_usb_vcp_init0(void);
// this will be persistent across a soft-reset
mp_uint_t pyb_usb_flags = 0;
@ -62,10 +64,7 @@ typedef struct _usb_device_t {
uint32_t enabled;
USBD_HandleTypeDef hUSBDDevice;
usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state;
usbd_cdc_itf_t usbd_cdc_itf;
#if MICROPY_HW_USB_ENABLE_CDC2
usbd_cdc_itf_t usbd_cdc2_itf;
#endif
usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM];
usbd_hid_itf_t usbd_hid_itf;
} usb_device_t;
@ -111,16 +110,15 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = {
};
void pyb_usb_init0(void) {
usb_device.usbd_cdc_itf.attached_to_repl = false;
#if MICROPY_HW_USB_ENABLE_CDC2
usb_device.usbd_cdc2_itf.attached_to_repl = false;
#endif
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
usb_device.usbd_cdc_itf[i].attached_to_repl = false;
}
MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL;
pyb_usb_vcp_init0();
}
bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info) {
bool high_speed = (mode & USBD_MODE_HIGH_SPEED) != 0;
mode &= 0x7f;
bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, 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
@ -132,15 +130,15 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors;
usbd->pClass = &USBD_CDC_MSC_HID;
usb_dev->usbd_cdc_msc_hid_state.pdev = usbd;
usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf.base;
#if MICROPY_HW_USB_ENABLE_CDC2
usb_dev->usbd_cdc_msc_hid_state.cdc2 = &usb_dev->usbd_cdc2_itf.base;
#endif
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base;
}
usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base;
usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state;
// configure the VID, PID and the USBD mode (interfaces it will expose)
USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC);
int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC;
USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only);
if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) {
return false;
}
@ -157,7 +155,7 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
}
// start the USB device
USBD_LL_Init(usbd, high_speed);
USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0);
USBD_LL_Start(usbd);
usb_dev->enabled = true;
}
@ -179,22 +177,17 @@ bool usb_vcp_is_enabled(void) {
}
int usb_vcp_recv_byte(uint8_t *c) {
return usbd_cdc_rx(&usb_device.usbd_cdc_itf, c, 1, 0);
return usbd_cdc_rx(&usb_device.usbd_cdc_itf[0], c, 1, 0);
}
void usb_vcp_send_strn(const char *str, int len) {
if (usb_device.enabled) {
usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)str, len);
usbd_cdc_tx_always(&usb_device.usbd_cdc_itf[0], (const uint8_t*)str, len);
}
}
usbd_cdc_itf_t *usb_vcp_get(int idx) {
#if MICROPY_HW_USB_ENABLE_CDC2
if (idx == 1) {
return &usb_device.usbd_cdc2_itf;
}
#endif
return &usb_device.usbd_cdc_itf;
return &usb_device.usbd_cdc_itf[idx];
}
/******************************************************************************/
@ -243,7 +236,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
return MP_OBJ_NEW_QSTR(MP_QSTR_host);
#else
uint8_t mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state);
switch (mode) {
switch (mode & USBD_MODE_IFACE_MASK) {
case USBD_MODE_CDC:
return MP_OBJ_NEW_QSTR(MP_QSTR_VCP);
case USBD_MODE_MSC:
@ -298,13 +291,13 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
// note: we support CDC as a synonym for VCP for backward compatibility
uint16_t vid = args[1].u_int;
uint16_t pid = args[2].u_int;
usb_device_mode_t mode;
uint8_t mode;
if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) {
if (args[2].u_int == -1) {
pid = USBD_PID_CDC_MSC;
}
mode = USBD_MODE_CDC_MSC;
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM >= 2
} else if (strcmp(mode_str, "VCP+VCP") == 0) {
if (args[2].u_int == -1) {
pid = USBD_PID_CDC2;
@ -337,7 +330,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
// get hid info if user selected such a mode
USBD_HID_ModeInfoTypeDef hid_info;
if (mode & USBD_MODE_HID) {
if (mode & USBD_MODE_IFACE_HID) {
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[3].u_obj, 5, &items);
hid_info.subclass = mp_obj_get_int(items[0]);
@ -388,13 +381,21 @@ typedef struct _pyb_usb_vcp_obj_t {
usbd_cdc_itf_t *cdc_itf;
} pyb_usb_vcp_obj_t;
const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf};
#if MICROPY_HW_USB_ENABLE_CDC2
STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp2_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc2_itf};
#endif
const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = {
{{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[0]},
#if MICROPY_HW_USB_CDC_NUM >= 2
{{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]},
#endif
};
STATIC void pyb_usb_vcp_init0(void) {
// Activate USB_VCP(0) on dupterm slot 1 for the REPL
MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]);
usb_vcp_attach_to_repl(&pyb_usb_vcp_obj[0], true);
}
STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf;
int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf[0];
mp_printf(print, "USB_VCP(%u)", id);
}
@ -411,12 +412,8 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, s
// TODO raise exception if USB is not configured for VCP
int id = (n_args == 0) ? 0 : mp_obj_get_int(args[0]);
if (id == 0) {
return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj);
#if MICROPY_HW_USB_ENABLE_CDC2
} else if (id == 1) {
return MP_OBJ_FROM_PTR(&pyb_usb_vcp2_obj);
#endif
if (0 <= id && id < MICROPY_HW_USB_CDC_NUM) {
return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[id]);
} else {
mp_raise_ValueError(NULL);
}
@ -457,7 +454,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconn
// deprecated in favour of USB_VCP.isconnected
STATIC mp_obj_t pyb_have_cdc(void) {
return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj));
return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]));
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);

View File

@ -58,14 +58,13 @@ extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj;
extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj;
extern const mp_obj_type_t pyb_usb_vcp_type;
extern const mp_obj_type_t pyb_usb_hid_type;
extern const pyb_usb_vcp_obj_t pyb_usb_vcp_obj;
MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj);
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, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, 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

View File

@ -217,18 +217,13 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
} else {
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc;
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i];
if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {
cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED;
usbd_cdc_try_tx(cdc);
}
#if MICROPY_HW_USB_ENABLE_CDC2
cdc = (usbd_cdc_itf_t*)usbd->cdc2;
if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) {
cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED;
usbd_cdc_try_tx(cdc);
}
#endif
}
}

View File

@ -334,7 +334,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
if (pdev->id == USB_PHY_FS_ID) {
// Set LL Driver parameters
pcd_fs_handle.Instance = USB_OTG_FS;
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM == 2
pcd_fs_handle.Init.dev_endpoints = 6;
#else
pcd_fs_handle.Init.dev_endpoints = 4;
@ -364,7 +364,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
HAL_PCD_Init(&pcd_fs_handle);
// We have 320 32-bit words in total to use here
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM == 2
HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128);
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID

View File

@ -18,12 +18,13 @@
#define USBD_SUPPORT_HS_MODE (0)
#endif
// Needed for the CDC+MSC+HID state and should be maximum of all template
// config descriptors defined in usbd_cdc_msc_hid.c
#if MICROPY_HW_USB_ENABLE_CDC2
// Should be maximum of possible config descriptors that might be configured
#if MICROPY_HW_USB_CDC_NUM == 2
// Maximum is MSC+CDC+CDC
#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58))
#else
#define MAX_TEMPLATE_CONFIG_DESC_SIZE (107)
// Maximum is HID+CDC
#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58))
#endif
// CDC, MSC and HID packet sizes
@ -124,10 +125,7 @@ typedef struct _usbd_cdc_msc_hid_state_t {
__ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
__ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END;
usbd_cdc_state_t *cdc;
#if MICROPY_HW_USB_ENABLE_CDC2
usbd_cdc_state_t *cdc2;
#endif
usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM];
usbd_hid_state_t *hid;
} usbd_cdc_msc_hid_state_t;

View File

@ -29,18 +29,22 @@
// these are exports for the CDC/MSC/HID interface that are independent
// from any other definitions/declarations
// only CDC_MSC and CDC_HID are available
typedef enum {
USBD_MODE_CDC = 0x01,
USBD_MODE_MSC = 0x02,
USBD_MODE_HID = 0x04,
USBD_MODE_CDC2 = 0x08,
USBD_MODE_CDC_MSC = USBD_MODE_CDC | USBD_MODE_MSC,
USBD_MODE_CDC_HID = USBD_MODE_CDC | USBD_MODE_HID,
USBD_MODE_MSC_HID = USBD_MODE_MSC | USBD_MODE_HID,
USBD_MODE_CDC2_MSC = USBD_MODE_CDC | USBD_MODE_MSC | USBD_MODE_CDC2,
USBD_MODE_HIGH_SPEED = 0x80, // or with one of the above
} usb_device_mode_t;
// These can be or'd together (but not all combinations may be available)
#define USBD_MODE_IFACE_MASK (0x7f)
#define USBD_MODE_IFACE_CDC(i) (0x01 << (i))
#define USBD_MODE_IFACE_HID (0x10)
#define USBD_MODE_IFACE_MSC (0x20)
#define USBD_MODE_HIGH_SPEED (0x80)
// Convenience macros for supported mode combinations
#define USBD_MODE_CDC (USBD_MODE_IFACE_CDC(0))
#define USBD_MODE_CDC2 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1))
#define USBD_MODE_CDC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID)
#define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC)
#define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC)
#define USBD_MODE_HID (USBD_MODE_IFACE_HID)
#define USBD_MODE_MSC (USBD_MODE_IFACE_MSC)
#define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID)
typedef struct _USBD_HID_ModeInfoTypeDef {
uint8_t subclass; // 0=no sub class, 1=boot

View File

@ -38,6 +38,8 @@
#define MSC_TEMPLATE_MSC_DESC_OFFSET (9)
#define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9)
#define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40)
#define CDC2_TEMPLATE_CDC_DESC_OFFSET (9 + 8)
#define CDC2_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8)
#define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9)
#define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8)
#define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8)
@ -69,13 +71,9 @@
#define HID_IFACE_NUM_WITH_CDC (0)
#define HID_IFACE_NUM_WITH_MSC (1)
#define CDC_IN_EP (0x83)
#define CDC_OUT_EP (0x03)
#define CDC_CMD_EP (0x82)
#define CDC2_IN_EP (0x85)
#define CDC2_OUT_EP (0x05)
#define CDC2_CMD_EP (0x84)
#define CDC_IN_EP(i) (0x83 + 2 * (i))
#define CDC_OUT_EP(i) (0x03 + 2 * (i))
#define CDC_CMD_EP(i) (0x82 + 2 * (i))
#define HID_IN_EP_WITH_CDC (0x81)
#define HID_OUT_EP_WITH_CDC (0x01)
@ -232,7 +230,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
// Endpoint CMD Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
CDC_CMD_EP, // bEndpointAddress
CDC_CMD_EP(0), // bEndpointAddress
0x03, // bmAttributes: Interrupt
LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize:
HIBYTE(CDC_CMD_PACKET_SIZE),
@ -253,7 +251,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
// Endpoint OUT Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
CDC_OUT_EP, // bEndpointAddress
CDC_OUT_EP(0), // bEndpointAddress
0x02, // bmAttributes: Bulk
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
@ -262,7 +260,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = {
// Endpoint IN Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint
CDC_IN_EP, // bEndpointAddress
CDC_IN_EP(0), // bEndpointAddress
0x02, // bmAttributes: Bulk
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize:
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
@ -421,7 +419,7 @@ static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) {
return need_iad ? 8 + 58 : 58;
}
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM >= 2
static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) {
size_t n = make_cdc_desc(dest, need_iad, iface_num);
if (need_iad) {
@ -461,7 +459,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
size_t n = HEAD_DESC_SIZE;
uint8_t *d = usbd->usbd_config_desc;
uint8_t num_itf = 0;
switch (usbd->usbd_mode) {
switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) {
case USBD_MODE_MSC:
n += make_msc_desc(d + n);
num_itf = 1;
@ -470,19 +468,16 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
case USBD_MODE_CDC_MSC:
n += make_msc_desc(d + n);
n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC);
usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC;
num_itf = 3;
break;
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM >= 2
case USBD_MODE_CDC2: {
// Ensure the first interface is also enabled
usbd->usbd_mode |= USBD_MODE_CDC;
n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE);
n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP);
usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE;
usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_CDC;
n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1));
usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE;
usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC;
num_itf = 4;
break;
}
@ -490,9 +485,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
case USBD_MODE_CDC2_MSC: {
n += make_msc_desc(d + n);
n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC);
n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP);
usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC;
n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1));
usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC;
usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC;
num_itf = 5;
break;
}
@ -502,7 +497,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
usbd->hid->desc = d + n;
n += make_hid_desc(d + n, hid_info);
n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID);
usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID;
usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID;
usbd->hid->in_ep = HID_IN_EP_WITH_CDC;
usbd->hid->out_ep = HID_OUT_EP_WITH_CDC;
usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC;
@ -512,7 +507,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
case USBD_MODE_CDC:
n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE);
usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE;
usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE;
num_itf = 2;
break;
@ -533,17 +528,12 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
make_head_desc(d, n, num_itf);
usbd->usbd_config_desc_size = n;
if (usbd->usbd_mode & USBD_MODE_CDC) {
usbd->cdc->in_ep = CDC_IN_EP;
usbd->cdc->out_ep = CDC_OUT_EP;
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) {
usbd->cdc[i]->in_ep = CDC_IN_EP(i);
usbd->cdc[i]->out_ep = CDC_OUT_EP(i);
}
#if MICROPY_HW_USB_ENABLE_CDC2
if (usbd->usbd_mode & USBD_MODE_CDC2) {
usbd->cdc2->in_ep = CDC2_IN_EP;
usbd->cdc2->out_ep = CDC2_OUT_EP;
}
#endif
return 0;
}
@ -578,19 +568,14 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if (usbd->usbd_mode & USBD_MODE_CDC) {
// CDC VCP component
usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP);
// CDC VCP component(s)
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) {
usbd_cdc_state_init(pdev, usbd, usbd->cdc[i], CDC_CMD_EP(i));
}
}
#if MICROPY_HW_USB_ENABLE_CDC2
if (usbd->usbd_mode & USBD_MODE_CDC2) {
// CDC VCP #2 component
usbd_cdc_state_init(pdev, usbd, usbd->cdc2, CDC2_CMD_EP);
}
#endif
if (usbd->usbd_mode & USBD_MODE_MSC) {
if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) {
// MSC component
int mp = usbd_msc_max_packet(pdev);
@ -611,7 +596,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
MSC_BOT_Init(pdev);
}
if (usbd->usbd_mode & USBD_MODE_HID) {
if (usbd->usbd_mode & USBD_MODE_IFACE_HID) {
// HID component
// get max packet lengths from descriptor
@ -644,31 +629,20 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if ((usbd->usbd_mode & USBD_MODE_CDC) && usbd->cdc) {
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && usbd->cdc[i]) {
// CDC VCP component
usbd_cdc_deinit(usbd->cdc);
usbd_cdc_deinit(usbd->cdc[i]);
// close endpoints
USBD_LL_CloseEP(pdev, CDC_IN_EP);
USBD_LL_CloseEP(pdev, CDC_OUT_EP);
USBD_LL_CloseEP(pdev, CDC_CMD_EP);
USBD_LL_CloseEP(pdev, CDC_IN_EP(i));
USBD_LL_CloseEP(pdev, CDC_OUT_EP(i));
USBD_LL_CloseEP(pdev, CDC_CMD_EP(i));
}
}
#if MICROPY_HW_USB_ENABLE_CDC2
if ((usbd->usbd_mode & USBD_MODE_CDC2) && usbd->cdc2) {
// CDC VCP #2 component
usbd_cdc_deinit(usbd->cdc2);
// close endpoints
USBD_LL_CloseEP(pdev, CDC2_IN_EP);
USBD_LL_CloseEP(pdev, CDC2_OUT_EP);
USBD_LL_CloseEP(pdev, CDC2_CMD_EP);
}
#endif
if (usbd->usbd_mode & USBD_MODE_MSC) {
if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) {
// MSC component
// close endpoints
@ -679,7 +653,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
MSC_BOT_DeInit(pdev);
}
if (usbd->usbd_mode & USBD_MODE_HID) {
if (usbd->usbd_mode & USBD_MODE_IFACE_HID) {
// HID component
// close endpoints
@ -717,35 +691,35 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) {
case USB_REQ_RECIPIENT_INTERFACE: {
uint16_t iface = req->wIndex;
if ((mode & USBD_MODE_CDC) && iface == usbd->cdc->iface_num) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc;
#if MICROPY_HW_USB_ENABLE_CDC2
} else if ((mode & USBD_MODE_CDC2) && iface == usbd->cdc2->iface_num) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc2;
#endif
} else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) {
if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) {
recipient = USBD_MODE_MSC;
} else if ((mode & USBD_MODE_HID) && iface == usbd->hid->iface_num) {
} else if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) {
recipient = USBD_MODE_HID;
} else {
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc[i];
break;
}
}
}
break;
}
case USB_REQ_RECIPIENT_ENDPOINT: {
uint8_t ep = req->wIndex & 0x7f;
if ((mode & USBD_MODE_CDC) && (ep == CDC_OUT_EP || ep == (CDC_CMD_EP & 0x7f))) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc;
#if MICROPY_HW_USB_ENABLE_CDC2
} else if ((mode & USBD_MODE_CDC2) && (ep == CDC2_OUT_EP || ep == (CDC2_CMD_EP & 0x7f))) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc2;
#endif
} else if ((mode & USBD_MODE_MSC) && ep == MSC_OUT_EP) {
if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) {
recipient = USBD_MODE_MSC;
} else if ((mode & USBD_MODE_HID) && ep == usbd->hid->out_ep) {
} else if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) {
recipient = USBD_MODE_HID;
} else {
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) {
recipient = USBD_MODE_CDC;
cdc = usbd->cdc[i];
break;
}
}
}
break;
}
@ -894,36 +868,32 @@ static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) {
static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) {
usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length);
usbd->cdc->cur_request = 0xff;
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if (usbd->cdc[i] != NULL && usbd->cdc[i]->cur_request != 0xff) {
usbd_cdc_control(usbd->cdc[i], usbd->cdc[i]->cur_request, (uint8_t*)usbd->cdc[i]->ctl_packet_buf, usbd->cdc[i]->cur_length);
usbd->cdc[i]->cur_request = 0xff;
}
#if MICROPY_HW_USB_ENABLE_CDC2
if (usbd->cdc2 != NULL && usbd->cdc2->cur_request != 0xff) {
usbd_cdc_control(usbd->cdc2, usbd->cdc2->cur_request, (uint8_t*)usbd->cdc2->ctl_packet_buf, usbd->cdc2->cur_length);
usbd->cdc2->cur_request = 0xff;
}
#endif
return USBD_OK;
}
static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) {
usbd->cdc->tx_in_progress = 0;
usbd_cdc_tx_ready(usbd->cdc);
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && (epnum == (CDC_IN_EP(i) & 0x7f) || epnum == (CDC_CMD_EP(i) & 0x7f))) {
usbd->cdc[i]->tx_in_progress = 0;
usbd_cdc_tx_ready(usbd->cdc[i]);
return USBD_OK;
#if MICROPY_HW_USB_ENABLE_CDC2
} else if ((usbd->usbd_mode & USBD_MODE_CDC2) && (epnum == (CDC2_IN_EP & 0x7f) || epnum == (CDC2_CMD_EP & 0x7f))) {
usbd->cdc2->tx_in_progress = 0;
usbd_cdc_tx_ready(usbd->cdc2);
return USBD_OK;
#endif
} else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
}
}
if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
MSC_BOT_DataIn(pdev, epnum);
return USBD_OK;
} else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) {
}
if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->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 */
usbd->hid->state = HID_IDLE;
@ -935,26 +905,23 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if ((usbd->usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) {
/* Get the received data length */
size_t len = 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 */
return usbd_cdc_receive(usbd->cdc, len);
#if MICROPY_HW_USB_ENABLE_CDC2
} else if ((usbd->usbd_mode & USBD_MODE_CDC2) && epnum == (CDC2_OUT_EP & 0x7f)) {
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && epnum == (CDC_OUT_EP(i) & 0x7f)) {
size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
return usbd_cdc_receive(usbd->cdc2, len);
// USB data will be immediately processed, and next USB traffic is NAKed until it's done
return usbd_cdc_receive(usbd->cdc[i], len);
}
}
#endif
} else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
MSC_BOT_DataOut(pdev, epnum);
return USBD_OK;
} else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) {
}
if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) {
size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
usbd_hid_receive(usbd->hid, len);
return usbd_hid_receive(usbd->hid, len);
}
return USBD_OK;
@ -981,48 +948,46 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
#if USBD_SUPPORT_HS_MODE
uint8_t *cdc_desc = NULL;
#if MICROPY_HW_USB_ENABLE_CDC2
uint8_t *cdc2_desc = NULL;
#endif
uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0};
uint8_t *msc_desc = NULL;
switch (usbd->usbd_mode) {
switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) {
case USBD_MODE_MSC:
msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET;
break;
case USBD_MODE_CDC_MSC:
cdc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET;
cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET;
msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET;
break;
#if MICROPY_HW_USB_ENABLE_CDC2
#if MICROPY_HW_USB_CDC_NUM >= 2
case USBD_MODE_CDC2:
cdc_desc[0] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC_DESC_OFFSET;
cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET;
break;
case USBD_MODE_CDC2_MSC:
cdc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET;
cdc2_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET;
cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET;
cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET;
msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET;
break;
#endif
case USBD_MODE_CDC_HID:
cdc_desc = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET;
cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET;
break;
case USBD_MODE_CDC:
cdc_desc = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET;
cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET;
break;
}
// configure CDC descriptors, if needed
if (cdc_desc != NULL) {
usbd_cdc_desc_config_max_packet(pdev, cdc_desc);
for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) {
if (cdc_desc[i] != NULL) {
usbd_cdc_desc_config_max_packet(pdev, cdc_desc[i]);
}
#if MICROPY_HW_USB_ENABLE_CDC2
if (cdc2_desc != NULL) {
usbd_cdc_desc_config_max_packet(pdev, cdc2_desc);
}
#endif
if (msc_desc != NULL) {
uint32_t mp = usbd_msc_max_packet(pdev);