Skip to content

Commit

Permalink
usb: Extend CDC device with second CDC channel
Browse files Browse the repository at this point in the history
  • Loading branch information
tore-espressif authored and dskulina committed Feb 5, 2022
1 parent 696adde commit f586364
Show file tree
Hide file tree
Showing 29 changed files with 113 additions and 164 deletions.
9 changes: 9 additions & 0 deletions components/tinyusb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ menu "TinyUSB Stack"

menu "Massive Storage Class (MSC)"
config TINYUSB_MSC_ENABLED
depends on TINYUSB_CDC_COUNT < 2
bool "Enable TinyUSB MSC feature"
default n
help
Expand All @@ -136,6 +137,14 @@ menu "TinyUSB Stack"
help
Enable TinyUSB CDC feature.

config TINYUSB_CDC_COUNT
int "CDC Channel Count"
default 1
range 1 2
depends on TINYUSB_CDC_ENABLED
help
Number of independent serial ports.

config TINYUSB_CDC_RX_BUFSIZE
depends on TINYUSB_CDC_ENABLED
int "CDC FIFO size of RX channel"
Expand Down
8 changes: 5 additions & 3 deletions components/tinyusb/additions/include/tusb_cdc_acm.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ extern "C" {
/**
* @brief CDC ports available to setup
*/
typedef enum{
TINYUSB_CDC_ACM_0 = 0x0
}tinyusb_cdcacm_itf_t;
typedef enum {
TINYUSB_CDC_ACM_0 = 0x0,
TINYUSB_CDC_ACM_1,
TINYUSB_CDC_ACM_MAX
} tinyusb_cdcacm_itf_t;

/* Callbacks and events
********************************************************************* */
Expand Down
6 changes: 5 additions & 1 deletion components/tinyusb/additions/include/tusb_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ extern "C" {
#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)

// Enabled device class driver
#define CFG_TUD_CDC CONFIG_TINYUSB_CDC_ENABLED
#if defined(CONFIG_TINYUSB_CDC_COUNT)
#define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT
#else
#define CFG_TUD_CDC 0
#endif
#define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED
#define CFG_TUD_HID CONFIG_TINYUSB_HID_ENABLED
#define CFG_TUD_VENDOR CONFIG_TINYUSB_VENDOR_ENABLED
Expand Down
8 changes: 0 additions & 8 deletions components/tinyusb/additions/include_private/cdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg);
esp_err_t tinyusb_cdc_deinit(int itf);


/**
* @brief Checks if the CDC initialized and ready to interaction
*
* @return true or false
*/
bool tinyusb_cdc_initialized(int itf);


/**
* @brief Return interface of a CDC device
*
Expand Down
16 changes: 5 additions & 11 deletions components/tinyusb/additions/include_private/descriptors_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,6 @@
#include <string.h>
#include "usb_descriptors.h"


/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
#define EPNUM_VENDOR 0x05
#define EPNUM_MIDI 0x06
#define EPNUM_MSC 0x03

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -38,6 +27,11 @@ enum {
ITF_NUM_CDC_DATA,
# endif

# if CFG_TUD_CDC > 1
ITF_NUM_CDC1,
ITF_NUM_CDC1_DATA,
# endif

# if CFG_TUD_MSC
ITF_NUM_MSC,
# endif
Expand Down
78 changes: 17 additions & 61 deletions components/tinyusb/additions/src/cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,65 +10,29 @@
#include "esp_log.h"
#include "tusb.h"
#include "cdc.h"
#include "sdkconfig.h"

static const char *TAG = "tusb_cdc";

#define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks

static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {};
static const char *TAG = "tusb_cdc";

/* Common CDC functions
********************************************************************* */
bool tinyusb_cdc_initialized(int itf)
{
return (cdc_obj[itf] != NULL);
}

static esp_err_t cdc_interface_check(int itf)
esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num)
{
if (tinyusb_cdc_initialized(itf)) {
return ESP_OK;
} else {
ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
return ESP_ERR_INVALID_STATE;
if (itf_num >= CDC_INTF_NUM || itf_num < 0) {
return NULL;
}
return cdc_obj[itf_num];
}

/**
* @brief
*
* @param itf
* @param expected_inited
* @param expected_type use -1 if you don't care
* @return esp_err_t
*/
static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type)
{
bool inited = (cdc_obj[itf] != NULL);
if (expected_inited != inited) {
ESP_LOGE(TAG, "Wrong state of the interface. Expected state: %s",
expected_inited ? "initialized" : "not initialized");
return ESP_ERR_INVALID_STATE;
}
if (inited && (expected_type != -1) && !(cdc_obj[itf]->type == expected_type)) {
ESP_LOGE(TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type);
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
esp_tusb_cdc_t *this_itf = tinyusb_cdc_get_intf(itf);

esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num)
{
if (cdc_interface_check(itf_num) != ESP_OK) {
return NULL;
}
return cdc_obj[itf_num];
bool inited = (this_itf != NULL);
ESP_RETURN_ON_FALSE(expected_inited == inited, ESP_ERR_INVALID_STATE, TAG, "Wrong state of the interface. Expected state: %s", expected_inited ? "initialized" : "not initialized");
ESP_RETURN_ON_FALSE(!(inited && (expected_type != -1) && !(this_itf->type == expected_type)), ESP_ERR_INVALID_STATE, TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type);
return ESP_OK;
}

/*********************************************************************** Common CDC functions*/
/* CDC class funcs
********************************************************************* */
static esp_err_t tusb_cdc_comm_init(int itf)
{
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");
Expand Down Expand Up @@ -112,16 +76,12 @@ static esp_err_t tusb_cdc_deinit_data(int itf)
cdc_obj[itf] = NULL;
return ESP_OK;
}
/*********************************************************************** CDC class funcs*/
/* CDC initialization
********************************************************************* */

esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
{
ESP_LOGD(TAG, "CDC initialization...");
if (itf != 0) {
ESP_LOGE(TAG, "There is not CDC no.%d", itf);
return ESP_ERR_INVALID_ARG;
}
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");

ESP_LOGD(TAG, "Init CDC %d", itf);
if (cfg->cdc_class == TUSB_CLASS_CDC) {
ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed");
cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass;
Expand All @@ -133,21 +93,17 @@ esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
return ESP_OK;
}


esp_err_t tinyusb_cdc_deinit(int itf)
{
if (itf != 0) {
ESP_LOGE(TAG, "There is not CDC no.%d", itf);
return ESP_ERR_INVALID_ARG;
}
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, -1), TAG, "cdc_obj_check failed");

ESP_LOGD(TAG, "Deinit CDC %d", itf);
if (cdc_obj[itf]->type == TUSB_CLASS_CDC) {
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed");
} else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) {
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed");
} else {
return ESP_ERR_INVALID_ARG;
}
ESP_LOGD(TAG, "De-initialized");
return ESP_OK;
}
/*********************************************************************** CDC initialization*/
12 changes: 11 additions & 1 deletion components/tinyusb/additions/src/descriptors_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ static tusb_desc_device_t s_descriptor;
static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
#define MAX_DESC_BUF_SIZE 32

#define EPNUM_MSC ((CFG_TUD_CDC * 2) + 1)
#define EPNUM_HID (EPNUM_MSC + 1)

#if CFG_TUD_HID //HID Report Descriptor
uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
Expand All @@ -27,13 +30,20 @@ uint8_t const desc_configuration[] = {
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64),
# endif

# if CFG_TUD_CDC > 1
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x83, 8, 0x04, 0x84, 64),
# endif

# if CFG_TUD_MSC
// Interface number, string index, EP Out & EP In address, EP size
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
# endif

# if CFG_TUD_HID
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10),
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x80 | EPNUM_HID, 16, 10)
# endif
# if CFG_TUD_VENDOR
// Interface number, string index, EP Out & IN address, EP size
Expand Down
27 changes: 4 additions & 23 deletions components/tinyusb/additions/src/tusb_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "tusb_console.h"
#include "tinyusb.h"
#include "vfs_tinyusb.h"
#include "esp_check.h"

#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
Expand Down Expand Up @@ -100,35 +101,15 @@ static esp_err_t restore_std_streams(FILE **f_in, FILE **f_out, FILE **f_err)

esp_err_t esp_tusb_init_console(int cdc_intf)
{
if (!tinyusb_cdc_initialized(cdc_intf)) {
ESP_LOGE(TAG, "Can't init the console because TinyUSB's CDC is not initialized!");
return ESP_ERR_INVALID_STATE;
}
/* Registering TUSB at VFS */
int res = esp_vfs_tusb_cdc_register(cdc_intf, NULL);
if (res != ESP_OK) {
return res;
}

res = redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc");
if (res != ESP_OK) {
return res;
}

ESP_RETURN_ON_ERROR(esp_vfs_tusb_cdc_register(cdc_intf, NULL), TAG, "");
ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"), TAG, "Failed to redirect STD streams");
return ESP_OK;
}

esp_err_t esp_tusb_deinit_console(int cdc_intf)
{
if (!tinyusb_cdc_initialized(cdc_intf)) {
ESP_LOGE(TAG, "Can't deinit the console because TinyUSB's CDC is not initialized!");
return ESP_ERR_INVALID_STATE;
}

int res = restore_std_streams(&con.in, &con.out, &con.err);
if (res != ESP_OK) {
return res;
}
ESP_RETURN_ON_ERROR(restore_std_streams(&con.in, &con.out, &con.err), TAG, "Failed to restore STD streams");
esp_vfs_tusb_cdc_unregister(NULL);
return ESP_OK;
}
7 changes: 7 additions & 0 deletions components/tinyusb/additions/src/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
#include "usb_descriptors.h"
#include "sdkconfig.h"

/*
* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
#define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3))

/**** TinyUSB default ****/
Expand Down
6 changes: 3 additions & 3 deletions docs/en/api-reference/peripherals/usb_device.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ The table below describes the code examples available in the directory :example:

* - Code Example
- Description
* - :example:`peripherals/usb/tusb_console`
* - :example:`peripherals/usb/device/tusb_console`
- How to set up {IDF_TARGET_NAME} chip to get log output via Serial Device connection
* - :example:`peripherals/usb/tusb_sample_descriptor`
* - :example:`peripherals/usb/device/tusb_sample_descriptor`
- How to set up {IDF_TARGET_NAME} chip to work as a Generic USB Device with a user-defined descriptor
* - :example:`peripherals/usb/tusb_serial_device`
* - :example:`peripherals/usb/device/tusb_serial_device`
- How to set up {IDF_TARGET_NAME} chip to work as a USB Serial Device


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Any ESP boards that have USB-OTG supported.

#### Pin Assignment

See common pin assignments for USB Device examples from [upper level](../README.md#common-pin-assignments).
See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).

### Build and Flash

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/* USB Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/

// DESCRIPTION:
// This example contains minimal code to make ESP32-S2 based device
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Any ESP boards that have USB-OTG supported.

#### Pin Assignment

See common pin assignments for USB Device examples from [upper level](../README.md#common-pin-assignments).
See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).

### Configure the project

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/* USB Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/

#include <stdlib.h>
#include "esp_log.h"
Expand Down
Loading

0 comments on commit f586364

Please sign in to comment.