summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/usb.c42
-rw-r--r--ports/stm32/usb.h1
-rw-r--r--ports/stm32/usbd_cdc_interface.c22
-rw-r--r--ports/stm32/usbd_cdc_interface.h4
-rw-r--r--ports/stm32/usbd_conf.c42
-rw-r--r--ports/stm32/usbd_conf.h2
-rw-r--r--ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h8
-rw-r--r--ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h8
-rw-r--r--ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c201
9 files changed, 256 insertions, 74 deletions
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 7e30805cc..23c490d37 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -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) {
diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h
index 6b43af00f..1de9e5d0e 100644
--- a/ports/stm32/usb.h
+++ b/ports/stm32/usb.h
@@ -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,
diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c
index 3ab6157c4..4c464dbf3 100644
--- a/ports/stm32/usbd_cdc_interface.c
+++ b/ports/stm32/usbd_cdc_interface.c
@@ -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);
diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h
index bfcdfaf33..cdf556d4e 100644
--- a/ports/stm32/usbd_cdc_interface.h
+++ b/ports/stm32/usbd_cdc_interface.h
@@ -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;
}
diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c
index d4a09459b..7829dcce6 100644
--- a/ports/stm32/usbd_conf.c
+++ b/ports/stm32/usbd_conf.c
@@ -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
diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h
index e68cbd9a4..1f8e754a2 100644
--- a/ports/stm32/usbd_conf.h
+++ b/ports/stm32/usbd_conf.h
@@ -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
diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
index 8bf454558..a4f81f10d 100644
--- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
+++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h
@@ -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;
diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
index 95fc693a0..c876dcf29 100644
--- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
+++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h
@@ -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;
diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
index 6def258c6..d0b922d76 100644
--- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
+++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
@@ -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,7 +691,15 @@ 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) {
@@ -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,38 +751,15 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
if (usbd->usbd_mode & USBD_MODE_CDC) {
// CDC VCP component
+ usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP);
+ }
- 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);
+ #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;
}