Skip to content

Add reset interface to multi CDC example #694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions usb/device/dev_multi_cdc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ target_sources(dev_multi_cdc PUBLIC
target_include_directories(dev_multi_cdc PUBLIC
${CMAKE_CURRENT_LIST_DIR})

# Enable the reset interface
target_compile_definitions(dev_multi_cdc PUBLIC
PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE=1
# use SDK MS_OS_20 descriptor, as this doesn't have a custom one
PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_MS_OS_20_DESCRIPTOR=1
# pass the interface number to the SDK MS_OS_20 descriptor
PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF=4
)

# In addition to pico_stdlib required for common PicoSDK functionality, add dependency on tinyusb_device
# for TinyUSB device support and tinyusb_board for the additional board support library used by the example
target_link_libraries(dev_multi_cdc PUBLIC pico_stdlib pico_unique_id tinyusb_device tinyusb_board)
Expand Down
17 changes: 13 additions & 4 deletions usb/device/dev_multi_cdc/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
#include <tusb.h>

#include <pico/stdio.h>
#include <pico/stdlib.h>

void custom_cdc_task(void);

bool tud_task_callback(__unused struct repeating_timer *t) {
tud_task();
return true;
}

int main(void)
{
// Initialize TinyUSB stack
Expand All @@ -26,15 +32,18 @@ int main(void)
// let pico sdk use the first cdc interface for std io
stdio_init_all();

// TinyUSB device task must be called regularly, so we use a repeating timer
struct repeating_timer timer;
add_repeating_timer_ms(1, tud_task_callback, NULL, &timer);

// main run loop
while (1) {
// TinyUSB device task | must be called regurlarly
tud_task();

// custom tasks
// custom tasks can run in the main loop without blocking the TinyUSB task
custom_cdc_task();
}

cancel_repeating_timer(&timer);

// indicate no error
return 0;
}
Expand Down
73 changes: 41 additions & 32 deletions usb/device/dev_multi_cdc/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,40 @@
#include <tusb.h>
#include <bsp/board_api.h>

#include "pico/usb_reset_interface_device.h"

// set some example Vendor and Product ID
// the board will use to identify at the host
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define CDC_EXAMPLE_VID 0xCafe
// use _PID_MAP to generate unique PID for each interface
#define CDC_EXAMPLE_PID (0x4000 | _PID_MAP(CDC, 0))
// set USB 2.0
#define CDC_EXAMPLE_BCD 0x0200
#define CDC_EXAMPLE_PID (0x4100 | _PID_MAP(CDC, 0))
// set to 2.10 so the MS_OS_20_DESCRIPTOR works
#define CDC_EXAMPLE_BCD 0x0210

// String descriptors referenced with .i... in the descriptor tables

enum {
STRID_LANGID = 0, // 0: supported language ID
STRID_MANUFACTURER, // 1: Manufacturer
STRID_PRODUCT, // 2: Product
STRID_SERIAL, // 3: Serials
STRID_CDC_0, // 4: CDC Interface 0
STRID_CDC_1, // 5: CDC Interface 1
STRID_RPI_RESET, // 6: Reset Interface
};

// array of pointer to string descriptors
char const *string_desc_arr[] = {
// switched because board is little endian
(const char[]) { 0x09, 0x04 }, // 0: supported language is English (0x0409)
"Raspberry Pi", // 1: Manufacturer
"Pico (2)", // 2: Product
NULL, // 3: Serials (null so it uses unique ID if available)
"Pico SDK stdio", // 4: CDC Interface 0
"Custom CDC", // 5: CDC Interface 1,
"Reset" // 6: Reset Interface
};

// defines a descriptor that will be communicated to the host
tusb_desc_device_t const desc_device = {
Expand All @@ -32,9 +58,9 @@ tusb_desc_device_t const desc_device = {
.idProduct = CDC_EXAMPLE_PID,
.bcdDevice = 0x0100, // Device release number

.iManufacturer = 0x01, // Index of manufacturer string
.iProduct = 0x02, // Index of product string
.iSerialNumber = 0x03, // Index of serial number string
.iManufacturer = STRID_MANUFACTURER, // Index of manufacturer string
.iProduct = STRID_PRODUCT, // Index of product string
.iSerialNumber = STRID_SERIAL, // Index of serial number string

.bNumConfigurations = 0x01 // 1 configuration
};
Expand All @@ -47,11 +73,14 @@ enum {
ITF_NUM_CDC_0_DATA,
ITF_NUM_CDC_1,
ITF_NUM_CDC_1_DATA,
ITF_NUM_RPI_RESET,
ITF_NUM_TOTAL
};

static_assert(ITF_NUM_RPI_RESET == PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF, "ITF_NUM_RPI_RESET must be equal to the PICO_STDIO_USB_RESET_INTERFACE_MS_OS_20_DESCRIPTOR_ITF set in CMakeLists.txt");

// total length of configuration descriptor
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN)
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + TUD_RPI_RESET_DESC_LEN)

// define endpoint numbers
#define EPNUM_CDC_0_NOTIF 0x81 // notification endpoint for CDC 0
Expand All @@ -68,14 +97,17 @@ uint8_t const desc_configuration[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 100),

// CDC 0: Communication Interface - TODO: get 64 from tusb_config.h
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, STRID_CDC_0, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
// CDC 0: Data Interface
//TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0_DATA, 4, 0x01, 0x02),

// CDC 1: Communication Interface - TODO: get 64 from tusb_config.h
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, STRID_CDC_1, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
// CDC 1: Data Interface
//TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1_DATA, 4, 0x03, 0x04),

// RPi Reset Interface
TUD_RPI_RESET_DESCRIPTOR(ITF_NUM_RPI_RESET, STRID_RPI_RESET),
};

// called when host requests to get configuration descriptor
Expand All @@ -99,29 +131,6 @@ tusb_desc_device_qualifier_t const desc_device_qualifier = {
// called when host requests to get device qualifier descriptor
uint8_t const* tud_descriptor_device_qualifier_cb(void);

// String descriptors referenced with .i... in the descriptor tables

enum {
STRID_LANGID = 0, // 0: supported language ID
STRID_MANUFACTURER, // 1: Manufacturer
STRID_PRODUCT, // 2: Product
STRID_SERIAL, // 3: Serials
STRID_CDC_0, // 4: CDC Interface 0
STRID_CDC_1, // 5: CDC Interface 1
};

// array of pointer to string descriptors
char const *string_desc_arr[] = {
// switched because board is little endian
(const char[]) { 0x09, 0x04 }, // 0: supported language is English (0x0409)
"Raspberry Pi", // 1: Manufacturer
"Pico (2)", // 2: Product
NULL, // 3: Serials (null so it uses unique ID if available)
"Pico SDK stdio" // 4: CDC Interface 0
"Custom CDC", // 5: CDC Interface 1,
"RPiReset" // 6: Reset Interface
};

// buffer to hold the string descriptor during the request | plus 1 for the null terminator
static uint16_t _desc_str[32 + 1];

Expand Down
Loading