stm32/usb: Add ability to have 2x VCP interfaces on the one USB device.
This patch adds the configuration MICROPY_HW_USB_ENABLE_CDC2 which enables a new USB device configuration at runtime: VCP+VCP+MSC. It will give two independent VCP interfaces available via pyb.USB_VCP(0) and pyb.USB_VCP(1). The first one is the usual one and has the REPL on it. The second one is available for general use. This configuration is disabled by default because if the mode is not used then it takes up about 2200 bytes of RAM. Also, F4 MCUs can't support this mode on their USB FS peripheral (eg PYBv1.x) because they don't have enough endpoints. The USB HS peripheral of an F4 supports it, as well as both the USB FS and USB HS peripherals of F7 MCUs.
This commit is contained in:
parent
2e565cc0d4
commit
47ecbbbecb
@ -63,6 +63,9 @@ typedef struct _usb_device_t {
|
||||
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_hid_itf_t usbd_hid_itf;
|
||||
} usb_device_t;
|
||||
|
||||
@ -127,6 +130,9 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
|
||||
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
|
||||
usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base;
|
||||
usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state;
|
||||
|
||||
@ -178,6 +184,15 @@ void usb_vcp_send_strn(const char *str, int 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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for USB
|
||||
|
||||
@ -285,6 +300,13 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
|
||||
pid = USBD_PID_CDC_MSC;
|
||||
}
|
||||
mode = USBD_MODE_CDC_MSC;
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
} else if (strcmp(mode_str, "VCP+VCP+MSC") == 0) {
|
||||
if (args[2].u_int == -1) {
|
||||
pid = USBD_PID_CDC2_MSC;
|
||||
}
|
||||
mode = USBD_MODE_CDC2_MSC;
|
||||
#endif
|
||||
} else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) {
|
||||
if (args[2].u_int == -1) {
|
||||
pid = USBD_PID_CDC_HID;
|
||||
@ -358,21 +380,33 @@ typedef struct _pyb_usb_vcp_obj_t {
|
||||
} pyb_usb_vcp_obj_t;
|
||||
|
||||
STATIC 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
|
||||
|
||||
STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_print_str(print, "USB_VCP()");
|
||||
int id = ((pyb_usb_vcp_obj_t*)self_in)->cdc_itf - &usb_device.usbd_cdc_itf;
|
||||
mp_printf(print, "USB_VCP(%u)", id);
|
||||
}
|
||||
|
||||
/// \classmethod \constructor()
|
||||
/// Create a new USB_VCP object.
|
||||
STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
// TODO raise exception if USB is not configured for VCP
|
||||
|
||||
// return the USB VCP object
|
||||
return (mp_obj_t)&pyb_usb_vcp_obj;
|
||||
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
|
||||
} else {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_usb_vcp_setinterrupt(mp_obj_t self_in, mp_obj_t int_chr_in) {
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define USBD_PID_CDC_HID (0x9801)
|
||||
#define USBD_PID_CDC (0x9802)
|
||||
#define USBD_PID_MSC (0x9803)
|
||||
#define USBD_PID_CDC2_MSC (0x9804)
|
||||
|
||||
typedef enum {
|
||||
PYB_USB_STORAGE_MEDIUM_NONE = 0,
|
||||
|
@ -69,6 +69,11 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
|
||||
cdc->tx_buf_ptr_wait_count = 0;
|
||||
cdc->tx_need_empty_packet = 0;
|
||||
cdc->dev_is_connected = 0;
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
cdc->attached_to_repl = &cdc->base == cdc->base.usbd->cdc;
|
||||
#else
|
||||
cdc->attached_to_repl = 1;
|
||||
#endif
|
||||
|
||||
// Return the buffer to place the first USB OUT packet
|
||||
return cdc->rx_packet_buf;
|
||||
@ -143,10 +148,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui
|
||||
// This function is called to process outgoing data. We hook directly into the
|
||||
// SOF (start of frame) callback so that it is called exactly at the time it is
|
||||
// needed (reducing latency), and often enough (increasing bandwidth).
|
||||
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
|
||||
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
|
||||
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc;
|
||||
|
||||
static void usbd_cdc_sof(PCD_HandleTypeDef *hpcd, usbd_cdc_itf_t *cdc) {
|
||||
if (cdc == NULL || !cdc->dev_is_connected) {
|
||||
// CDC device is not connected to a host, so we are unable to send any data
|
||||
return;
|
||||
@ -199,11 +201,19 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
|
||||
// the host waits for all data to arrive (ie, waits for a packet < max packet size).
|
||||
// To flush a packet of exactly max packet size, we need to send a zero-size packet.
|
||||
// See eg http://www.cypress.com/?id=4&rID=92719
|
||||
cdc->tx_need_empty_packet = (buffsize > 0 && buffsize % usbd_cdc_max_packet(usbd->pdev) == 0 && cdc->tx_buf_ptr_out_shadow == cdc->tx_buf_ptr_in);
|
||||
cdc->tx_need_empty_packet = (buffsize > 0 && buffsize % usbd_cdc_max_packet(cdc->base.usbd->pdev) == 0 && cdc->tx_buf_ptr_out_shadow == cdc->tx_buf_ptr_in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
|
||||
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
|
||||
usbd_cdc_sof(hpcd, (usbd_cdc_itf_t*)usbd->cdc);
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
usbd_cdc_sof(hpcd, (usbd_cdc_itf_t*)usbd->cdc2);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Data received over USB OUT endpoint is processed here.
|
||||
// len: number of bytes received into the buffer we passed to USBD_CDC_ReceivePacket
|
||||
// Returns USBD_OK if all operations are OK else USBD_FAIL
|
||||
@ -212,7 +222,7 @@ int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc_in, size_t len) {
|
||||
|
||||
// copy the incoming data into the circular buffer
|
||||
for (const uint8_t *src = cdc->rx_packet_buf, *top = cdc->rx_packet_buf + len; src < top; ++src) {
|
||||
if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
|
||||
if (cdc->attached_to_repl && mp_interrupt_char != -1 && *src == mp_interrupt_char) {
|
||||
pendsv_kbd_intr();
|
||||
} else {
|
||||
uint16_t next_put = (cdc->rx_buf_put + 1) & (USBD_CDC_RX_DATA_SIZE - 1);
|
||||
|
@ -50,8 +50,12 @@ typedef struct _usbd_cdc_itf_t {
|
||||
uint8_t tx_need_empty_packet; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
|
||||
|
||||
volatile uint8_t dev_is_connected; // indicates if we are connected
|
||||
uint8_t attached_to_repl; // indicates if interface is connected to REPL
|
||||
} usbd_cdc_itf_t;
|
||||
|
||||
// This is implemented in usb.c
|
||||
usbd_cdc_itf_t *usb_vcp_get(int idx);
|
||||
|
||||
static inline int usbd_cdc_is_connected(usbd_cdc_itf_t *cdc) {
|
||||
return cdc->dev_is_connected;
|
||||
}
|
||||
|
@ -368,7 +368,11 @@ 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
|
||||
pcd_fs_handle.Init.dev_endpoints = 6;
|
||||
#else
|
||||
pcd_fs_handle.Init.dev_endpoints = 4;
|
||||
#endif
|
||||
pcd_fs_handle.Init.use_dedicated_ep1 = 0;
|
||||
pcd_fs_handle.Init.ep0_mps = 0x40;
|
||||
pcd_fs_handle.Init.dma_enable = 0;
|
||||
@ -393,11 +397,22 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
|
||||
// Initialize LL Driver
|
||||
HAL_PCD_Init(&pcd_fs_handle);
|
||||
|
||||
HAL_PCD_SetRxFiFo(&pcd_fs_handle, 0x80);
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 0x20);
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 0x40);
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 0x20);
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 0x40);
|
||||
// We have 320 32-bit words in total to use here
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
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
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 16); // CDC CMD
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 32); // CDC DATA
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 4, 16); // CDC2 CMD
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 5, 32); // CDC2 DATA
|
||||
#else
|
||||
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
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 32); // CDC CMD
|
||||
HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 64); // CDC DATA
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if MICROPY_HW_USB_HS
|
||||
@ -406,11 +421,13 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
|
||||
|
||||
// Set LL Driver parameters
|
||||
pcd_hs_handle.Instance = USB_OTG_HS;
|
||||
pcd_hs_handle.Init.dev_endpoints = 4;
|
||||
pcd_hs_handle.Init.dev_endpoints = 6;
|
||||
pcd_hs_handle.Init.use_dedicated_ep1 = 0;
|
||||
pcd_hs_handle.Init.ep0_mps = 0x40;
|
||||
pcd_hs_handle.Init.dma_enable = 0;
|
||||
pcd_hs_handle.Init.low_power_enable = 0;
|
||||
pcd_hs_handle.Init.lpm_enable = DISABLE;
|
||||
pcd_hs_handle.Init.battery_charging_enable = DISABLE;
|
||||
#if defined(STM32F723xx) || defined(STM32F733xx)
|
||||
pcd_hs_handle.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY;
|
||||
#else
|
||||
@ -436,11 +453,14 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) {
|
||||
// Initialize LL Driver
|
||||
HAL_PCD_Init(&pcd_hs_handle);
|
||||
|
||||
HAL_PCD_SetRxFiFo(&pcd_hs_handle, 0x200);
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 0x20);
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 0x100);
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 2, 0x20);
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 3, 0xc0);
|
||||
// We have 1024 32-bit words in total to use here
|
||||
HAL_PCD_SetRxFiFo(&pcd_hs_handle, 512);
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 32); // EP0
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 256); // MSC / HID
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 2, 32); // CDC CMD
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 3, 64); // CDC DATA
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 4, 32); // CDC2 CMD
|
||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 5, 64); // CDC2 DATA
|
||||
|
||||
#else // !MICROPY_HW_USB_HS_IN_FS
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define USBD_MAX_NUM_INTERFACES 1
|
||||
#define USBD_MAX_NUM_INTERFACES 4
|
||||
#define USBD_MAX_NUM_CONFIGURATION 1
|
||||
#define USBD_MAX_STR_DESC_SIZ 0x100
|
||||
#define USBD_SELF_POWERED 0
|
||||
|
@ -20,7 +20,11 @@
|
||||
|
||||
// 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
|
||||
#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58))
|
||||
#else
|
||||
#define MAX_TEMPLATE_CONFIG_DESC_SIZE (107)
|
||||
#endif
|
||||
|
||||
// CDC, MSC and HID packet sizes
|
||||
#define MSC_FS_MAX_PACKET (64)
|
||||
@ -46,6 +50,7 @@ typedef struct {
|
||||
uint32_t ctl_packet_buf[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32-bit alignment
|
||||
uint8_t iface_num;
|
||||
uint8_t in_ep;
|
||||
uint8_t out_ep;
|
||||
uint8_t cur_request;
|
||||
uint8_t cur_length;
|
||||
volatile uint8_t tx_in_progress;
|
||||
@ -120,6 +125,9 @@ typedef struct _usbd_cdc_msc_hid_state_t {
|
||||
__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_hid_state_t *hid;
|
||||
} usbd_cdc_msc_hid_state_t;
|
||||
|
||||
|
@ -34,9 +34,11 @@ typedef enum {
|
||||
USBD_MODE_CDC = 0x01,
|
||||
USBD_MODE_MSC = 0x02,
|
||||
USBD_MODE_HID = 0x04,
|
||||
USBD_MODE_CDC_MSC = 0x03,
|
||||
USBD_MODE_CDC_HID = 0x05,
|
||||
USBD_MODE_MSC_HID = 0x06,
|
||||
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;
|
||||
|
||||
|
@ -34,6 +34,10 @@
|
||||
#define CDC_MSC_TEMPLATE_CONFIG_DESC_SIZE (98)
|
||||
#define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9)
|
||||
#define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40)
|
||||
#define CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58))
|
||||
#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)
|
||||
#define CDC_HID_TEMPLATE_CONFIG_DESC_SIZE (107)
|
||||
#define CDC_HID_TEMPLATE_HID_DESC_OFFSET (9)
|
||||
#define CDC_HID_TEMPLATE_CDC_DESC_OFFSET (49)
|
||||
@ -57,6 +61,7 @@
|
||||
|
||||
#define CDC_IFACE_NUM_ALONE (0)
|
||||
#define CDC_IFACE_NUM_WITH_MSC (1)
|
||||
#define CDC2_IFACE_NUM_WITH_MSC (3)
|
||||
#define CDC_IFACE_NUM_WITH_HID (1)
|
||||
#define MSC_IFACE_NUM_WITH_CDC (0)
|
||||
#define HID_IFACE_NUM_WITH_CDC (0)
|
||||
@ -66,6 +71,10 @@
|
||||
#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 HID_IN_EP_WITH_CDC (0x81)
|
||||
#define HID_OUT_EP_WITH_CDC (0x01)
|
||||
#define HID_IN_EP_WITH_MSC (0x83)
|
||||
@ -625,6 +634,31 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
|
||||
usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
|
||||
break;
|
||||
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
case USBD_MODE_CDC2_MSC: {
|
||||
usbd->usbd_config_desc_size = CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE;
|
||||
uint8_t *d = usbd->usbd_config_desc;
|
||||
memcpy(d, cdc_msc_template_config_desc, sizeof(cdc_msc_template_config_desc));
|
||||
d[2] = LOBYTE(CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE); // wTotalLength
|
||||
d[3] = HIBYTE(CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE);
|
||||
d[4] = 5; // bNumInterfaces
|
||||
memcpy(d + 9 + 23 + (8 + 58), d + 9 + 23, 8 + 58);
|
||||
d += 9 + 23 + (8 + 58);
|
||||
d[2] = CDC2_IFACE_NUM_WITH_MSC; // bFirstInterface
|
||||
d[10] = CDC2_IFACE_NUM_WITH_MSC; // bInterfaceNumber
|
||||
d[26] = CDC2_IFACE_NUM_WITH_MSC + 1; // bDataInterface
|
||||
d[34] = CDC2_IFACE_NUM_WITH_MSC + 0; // bMasterInterface
|
||||
d[35] = CDC2_IFACE_NUM_WITH_MSC + 1; // bSlaveInterface
|
||||
d[38] = CDC2_CMD_EP; // bEndpointAddress
|
||||
d[45] = CDC2_IFACE_NUM_WITH_MSC + 1; // bInterfaceNumber
|
||||
d[54] = CDC2_OUT_EP; // bEndpointAddress
|
||||
d[61] = CDC2_IN_EP; // bEndpointAddress
|
||||
usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
|
||||
usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case USBD_MODE_CDC_HID:
|
||||
usbd->usbd_config_desc_size = sizeof(cdc_hid_template_config_desc);
|
||||
memcpy(usbd->usbd_config_desc, cdc_hid_template_config_desc, sizeof(cdc_hid_template_config_desc));
|
||||
@ -657,8 +691,16 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
|
||||
|
||||
if (usbd->usbd_mode & USBD_MODE_CDC) {
|
||||
usbd->cdc->in_ep = CDC_IN_EP;
|
||||
usbd->cdc->out_ep = CDC_OUT_EP;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
// configure the HID descriptor, if needed
|
||||
if (usbd->usbd_mode & USBD_MODE_HID) {
|
||||
uint8_t *hid_desc = usbd->hid->desc;
|
||||
@ -677,6 +719,26 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbd_cdc_state_init(USBD_HandleTypeDef *pdev, usbd_cdc_msc_hid_state_t *usbd, usbd_cdc_state_t *cdc, uint8_t cmd_ep) {
|
||||
int mp = usbd_cdc_max_packet(pdev);
|
||||
|
||||
// Open endpoints
|
||||
USBD_LL_OpenEP(pdev, cdc->in_ep, USBD_EP_TYPE_BULK, mp);
|
||||
USBD_LL_OpenEP(pdev, cdc->out_ep, USBD_EP_TYPE_BULK, mp);
|
||||
USBD_LL_OpenEP(pdev, cmd_ep, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
|
||||
|
||||
// Init state
|
||||
cdc->usbd = usbd;
|
||||
cdc->cur_request = 0xff;
|
||||
cdc->tx_in_progress = 0;
|
||||
|
||||
// Init interface
|
||||
uint8_t *buf = usbd_cdc_init(cdc);
|
||||
|
||||
// Prepare Out endpoint to receive next packet
|
||||
USBD_LL_PrepareReceive(pdev, cdc->out_ep, buf, mp);
|
||||
}
|
||||
|
||||
static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
|
||||
#if !USBD_SUPPORT_HS_MODE
|
||||
if (pdev->dev_speed == USBD_SPEED_HIGH) {
|
||||
@ -689,39 +751,16 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
|
||||
|
||||
if (usbd->usbd_mode & USBD_MODE_CDC) {
|
||||
// CDC VCP component
|
||||
|
||||
int mp = usbd_cdc_max_packet(pdev);
|
||||
|
||||
// Open EP IN
|
||||
USBD_LL_OpenEP(pdev,
|
||||
CDC_IN_EP,
|
||||
USBD_EP_TYPE_BULK,
|
||||
mp);
|
||||
|
||||
// Open EP OUT
|
||||
USBD_LL_OpenEP(pdev,
|
||||
CDC_OUT_EP,
|
||||
USBD_EP_TYPE_BULK,
|
||||
mp);
|
||||
|
||||
// Open Command IN EP
|
||||
USBD_LL_OpenEP(pdev,
|
||||
CDC_CMD_EP,
|
||||
USBD_EP_TYPE_INTR,
|
||||
CDC_CMD_PACKET_SIZE);
|
||||
|
||||
// Init Xfer states
|
||||
usbd->cdc->usbd = usbd;
|
||||
usbd->cdc->cur_request = 0xff;
|
||||
usbd->cdc->tx_in_progress = 0;
|
||||
|
||||
// Init physical Interface components
|
||||
uint8_t *buf = usbd_cdc_init(usbd->cdc);
|
||||
|
||||
// Prepare Out endpoint to receive next packet
|
||||
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, buf, mp);
|
||||
usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP);
|
||||
}
|
||||
|
||||
#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) {
|
||||
// MSC component
|
||||
|
||||
@ -785,6 +824,17 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
USBD_LL_CloseEP(pdev, CDC_CMD_EP);
|
||||
}
|
||||
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
if ((usbd->usbd_mode & USBD_MODE_CDC2) && usbd->cdc2) {
|
||||
// CDC VCP #2 component
|
||||
|
||||
// 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) {
|
||||
// MSC component
|
||||
|
||||
@ -830,11 +880,18 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
|
||||
// Work out the recipient of the setup request
|
||||
uint8_t mode = usbd->usbd_mode;
|
||||
uint8_t recipient = 0;
|
||||
usbd_cdc_state_t *cdc;
|
||||
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) {
|
||||
recipient = USBD_MODE_MSC;
|
||||
} else if ((mode & USBD_MODE_HID) && iface == usbd->hid->iface_num) {
|
||||
@ -846,6 +903,12 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
|
||||
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) {
|
||||
recipient = USBD_MODE_MSC;
|
||||
} else if ((mode & USBD_MODE_HID) && ep == usbd->hid->out_ep) {
|
||||
@ -869,18 +932,18 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
|
||||
if (req->wLength) {
|
||||
if (req->bmRequest & 0x80) {
|
||||
// device-to-host request
|
||||
usbd_cdc_control(usbd->cdc, req->bRequest, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
|
||||
USBD_CtlSendData(pdev, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
|
||||
usbd_cdc_control(cdc, req->bRequest, (uint8_t*)cdc->ctl_packet_buf, req->wLength);
|
||||
USBD_CtlSendData(pdev, (uint8_t*)cdc->ctl_packet_buf, req->wLength);
|
||||
} else {
|
||||
// host-to-device request
|
||||
usbd->cdc->cur_request = req->bRequest;
|
||||
usbd->cdc->cur_length = req->wLength;
|
||||
USBD_CtlPrepareRx(pdev, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
|
||||
cdc->cur_request = req->bRequest;
|
||||
cdc->cur_length = req->wLength;
|
||||
USBD_CtlPrepareRx(pdev, (uint8_t*)cdc->ctl_packet_buf, req->wLength);
|
||||
}
|
||||
} else {
|
||||
// Not a Data request
|
||||
// Transfer the command to the interface layer
|
||||
return usbd_cdc_control(usbd->cdc, req->bRequest, NULL, req->wValue);
|
||||
return usbd_cdc_control(cdc, req->bRequest, NULL, req->wValue);
|
||||
}
|
||||
} else if (recipient == USBD_MODE_MSC) {
|
||||
switch (req->bRequest) {
|
||||
@ -1002,6 +1065,12 @@ static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
|
||||
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;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
@ -1011,6 +1080,11 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) {
|
||||
usbd->cdc->tx_in_progress = 0;
|
||||
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;
|
||||
return USBD_OK;
|
||||
#endif
|
||||
} else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
|
||||
MSC_BOT_DataIn(pdev, epnum);
|
||||
return USBD_OK;
|
||||
@ -1035,6 +1109,12 @@ static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
usbd_cdc_receive(usbd->cdc, len);
|
||||
|
||||
return USBD_OK;
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
} else if ((usbd->usbd_mode & USBD_MODE_CDC2) && epnum == (CDC2_OUT_EP & 0x7f)) {
|
||||
size_t len = USBD_LL_GetRxDataSize(pdev, epnum);
|
||||
usbd_cdc_receive(usbd->cdc2, len);
|
||||
return USBD_OK;
|
||||
#endif
|
||||
} else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
|
||||
MSC_BOT_DataOut(pdev, epnum);
|
||||
return USBD_OK;
|
||||
@ -1046,11 +1126,31 @@ static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
#if USBD_SUPPORT_HS_MODE
|
||||
static void usbd_cdc_desc_config_max_packet(USBD_HandleTypeDef *pdev, uint8_t *cdc_desc) {
|
||||
uint32_t mp = usbd_cdc_max_packet(pdev);
|
||||
cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_LO] = LOBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_HI] = HIBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_LO] = LOBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_HI] = HIBYTE(mp);
|
||||
uint8_t interval; // polling interval in frames of 1ms
|
||||
if (pdev->dev_speed == USBD_SPEED_HIGH) {
|
||||
interval = 0x09;
|
||||
} else {
|
||||
interval = 0x20;
|
||||
}
|
||||
cdc_desc[CDC_DESC_OFFSET_INTR_INTERVAL] = interval;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *length) {
|
||||
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 *msc_desc = NULL;
|
||||
switch (usbd->usbd_mode) {
|
||||
case USBD_MODE_MSC:
|
||||
@ -1062,6 +1162,14 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *
|
||||
msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET;
|
||||
break;
|
||||
|
||||
#if MICROPY_HW_USB_ENABLE_CDC2
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
@ -1073,20 +1181,15 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t *
|
||||
|
||||
// configure CDC descriptors, if needed
|
||||
if (cdc_desc != NULL) {
|
||||
uint32_t mp = usbd_cdc_max_packet(pdev);
|
||||
cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_LO] = LOBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_OUT_MAX_PACKET_HI] = HIBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_LO] = LOBYTE(mp);
|
||||
cdc_desc[CDC_DESC_OFFSET_IN_MAX_PACKET_HI] = HIBYTE(mp);
|
||||
uint8_t interval; // polling interval in frames of 1ms
|
||||
if (pdev->dev_speed == USBD_SPEED_HIGH) {
|
||||
interval = 0x09;
|
||||
} else {
|
||||
interval = 0x20;
|
||||
}
|
||||
cdc_desc[CDC_DESC_OFFSET_INTR_INTERVAL] = interval;
|
||||
usbd_cdc_desc_config_max_packet(pdev, cdc_desc);
|
||||
}
|
||||
|
||||
#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);
|
||||
msc_desc[13] = LOBYTE(mp);
|
||||
@ -1135,7 +1238,7 @@ uint8_t USBD_CDC_ReceivePacket(usbd_cdc_state_t *cdc, uint8_t *buf) {
|
||||
#endif
|
||||
|
||||
// Prepare Out endpoint to receive next packet
|
||||
USBD_LL_PrepareReceive(cdc->usbd->pdev, CDC_OUT_EP, buf, usbd_cdc_max_packet(cdc->usbd->pdev));
|
||||
USBD_LL_PrepareReceive(cdc->usbd->pdev, cdc->out_ep, buf, usbd_cdc_max_packet(cdc->usbd->pdev));
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user