wip: descriptor building

This commit is contained in:
Dan Halbert 2021-04-21 23:25:36 -04:00
parent 6b18a51d57
commit 64e0958916
20 changed files with 239 additions and 152 deletions

View File

@ -346,7 +346,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
for (int k=0; k<4; k++) { for (int k=0; k<4; k++) {
raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; raw_id[4 * i + (3 -k)] = (*(id_addresses[i]) >> k * 8) & 0xff;
} }
} }
} }

View File

@ -20,8 +20,6 @@ endif
INTERNAL_LIBM = 1 INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 32
# Number of USB endpoint pairs. # Number of USB endpoint pairs.
USB_NUM_EP = 8 USB_NUM_EP = 8

View File

@ -1,4 +1,3 @@
USB_SERIAL_NUMBER_LENGTH = 10
USB_HIGHSPEED = 1 USB_HIGHSPEED = 1
USB_RENUMBER_ENDPOINTS = 0 USB_RENUMBER_ENDPOINTS = 0
USB_CDC_EP_NUM_NOTIFICATION = 3 USB_CDC_EP_NUM_NOTIFICATION = 3

View File

@ -6,9 +6,6 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
# Internal math library is substantially smaller than toolchain one # Internal math library is substantially smaller than toolchain one
INTERNAL_LIBM = 1 INTERNAL_LIBM = 1
# Chip supplied serial number, in bytes
USB_SERIAL_NUMBER_LENGTH = 12
# Longints can be implemented as mpz, as longlong, or not # Longints can be implemented as mpz, as longlong, or not
LONGINT_IMPL = MPZ LONGINT_IMPL = MPZ

View File

@ -9,9 +9,6 @@ INTERNAL_LIBM = 1
# Number of USB endpoint pairs. # Number of USB endpoint pairs.
USB_NUM_EP = 16 USB_NUM_EP = 16
# Chip supplied serial number, in bytes
USB_SERIAL_NUMBER_LENGTH = 30
# Longints can be implemented as mpz, as longlong, or not # Longints can be implemented as mpz, as longlong, or not
LONGINT_IMPL = MPZ LONGINT_IMPL = MPZ

View File

@ -14,7 +14,6 @@ endif
INTERNAL_LIBM = 1 INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 32
USB_HIGHSPEED = 1 USB_HIGHSPEED = 1
# Number of USB endpoint pairs. # Number of USB endpoint pairs.

View File

@ -9,8 +9,6 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
INTERNAL_LIBM = 1 INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 16
# Number of USB endpoint pairs. # Number of USB endpoint pairs.
USB_NUM_EP = 8 USB_NUM_EP = 8

View File

@ -47,8 +47,6 @@ CIRCUITPY_AUDIOMIXER ?= 0
INTERNAL_LIBM = 1 INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 16
# Number of USB endpoint pairs. # Number of USB endpoint pairs.
USB_NUM_EP = 8 USB_NUM_EP = 8

View File

@ -1,7 +1,6 @@
MPY_TOOL_LONGINT_IMPL ?= -mlongint-impl=mpz MPY_TOOL_LONGINT_IMPL ?= -mlongint-impl=mpz
LONGINT_IMPL ?= MPZ LONGINT_IMPL ?= MPZ
INTERNAL_LIBM ?= 1 INTERNAL_LIBM ?= 1
USB_SERIAL_NUMBER_LENGTH ?= 24
ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx)) ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx))
CIRCUITPY_CANIO = 1 CIRCUITPY_CANIO = 1

View File

@ -58,7 +58,7 @@ static const uint8_t storage_usb_msc_descriptor_template[] = {
// MSC Endpoint IN Descriptor // MSC Endpoint IN Descriptor
0x07, // 9 bLength 0x07, // 9 bLength
0x05, // 10 bDescriptorType (Endpoint) 0x05, // 10 bDescriptorType (Endpoint)
0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x8 | number] 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number]
#define MSC_IN_ENDPOINT_INDEX 11 #define MSC_IN_ENDPOINT_INDEX 11
0x02, // 12 bmAttributes (Bulk) 0x02, // 12 bmAttributes (Bulk)
0x40, 0x00, // 13,14 wMaxPacketSize 64 0x40, 0x00, // 13,14 wMaxPacketSize 64
@ -81,12 +81,21 @@ size_t storage_usb_descriptor_length(void) {
return sizeof(usb_msc_descriptor); return sizeof(usb_msc_descriptor);
} }
size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t interface_number, uint8_t in_endpoint, uint8_t out_endpoint, uint8_t interface_string) { static const char[] storage_interface_name = USB_INTERFACE_NAME " Mass Storage";
size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string) {
memcpy(descriptor_buf, storage_usb_msc_descriptor_template, sizeof(storage_usb_msc_descriptor_template)); memcpy(descriptor_buf, storage_usb_msc_descriptor_template, sizeof(storage_usb_msc_descriptor_template));
descriptor_buf[MSC_INTERFACE_INDEX] = interface_number; descriptor_buf[MSC_INTERFACE_INDEX] = *current_interface;
descriptor_buf[MSC_INTERFACE_STRING_INDEX] = interface_string; (*current_interface)++;
descriptor_buf[MSC_IN_ENDPOINT_INDEX] = in_endpoint_address;
descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | out_endpoint_address; descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : *current_endpoint;
descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | (USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : *current_endpoint);
(*current_endpoint)++:
usb_add_interface_string(*current_interface_string,);
descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
return sizeof(storage_usb_msc_descriptor_template); return sizeof(storage_usb_msc_descriptor_template);
} }

View File

@ -31,6 +31,6 @@ extern bool storage_usb_enabled;
void storage_init(void); void storage_init(void);
size_t storage_usb_descriptor_length(void); size_t storage_usb_descriptor_length(void);
size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t interface, uint8_t in_endpoint, uint8_t out_endpoint, uint8_tt interface_string); size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string);
#endif // SHARED_MODULE_STORAGE___INIT___H #endif // SHARED_MODULE_STORAGE___INIT___H

View File

@ -140,21 +140,48 @@ size_t usb_cdc_descriptor_length(void) {
return sizeof(usb_cdc_descriptor_template); return sizeof(usb_cdc_descriptor_template);
} }
size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8 comm_interface, uint8_t data_interface, uint8_t control_in_endpoint, uint8_t data_in_endpoint, uint8_t data_out_endpoint, uint8_t comm_interface_string, uint8_t data_interface_string) { static const char[] repl_cdc_comm_interface_name = USB_INTERFACE_NAME " CDC control";
static const char[] data_cdc_comm_interface_name = USB_INTERFACE_NAME " CDC2 control";
static const char[] repl_cdc_data_interface_name = USB_INTERFACE_NAME " CDC data";
static const char[] data_cdc_data_interface_name = USB_INTERFACE_NAME " CDC2 data";
size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string, bool repl) {
memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template)); memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template));
descriptor_buf[CDC_FIRST_INTERFACE_INDEX] = comm_interface;
descriptor_buf[CDC_COMM_INTERFACE_INDEX] = comm_interface;
descriptor_buf[CDC_CALL_MANAGEMENT_DATA_INTERFACE_INDEX] = data_interface;
descriptor_buf[CDC_UNION_MASTER_INTERFACE_INDEX] = comm_interface;
descriptor_buf[CDC_UNION_SLAVE_INTERFACE_INDEX] = data_interface;
descriptor_buf[CDC_DATA_INTERFACE_INDEX] = data_interface;
descriptor_buf[CDC_CONTROL_IN_ENDPOINT_INDEX] = control_in_endpoint; // Store comm interface number.
descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = data_out_endpoint; descriptor_buf[CDC_FIRST_INTERFACE_INDEX] = *current_interface;
descriptor_buf[CDC_DATA_IN_ENDPOINT_INDEX] = data_in_endpoint; descriptor_buf[CDC_COMM_INTERFACE_INDEX] = *current_interface;
descriptor_buf[CDC_UNION_MASTER_INTERFACE_INDEX] = *current_interface;
(*current_interface)++;
descriptor_buf[CDC_COMM_INTERFACE_STRING_INDEX] = comm_interface_string; // Now store data interface number.
descriptor_buf[CDC_DATA_INTERFACE_STRING_INDEX] = data_interface_string; descriptor_buf[CDC_CALL_MANAGEMENT_DATA_INTERFACE_INDEX] = *current_interface;
descriptor_buf[CDC_UNION_SLAVE_INTERFACE_INDEX] = *current_interface;
descriptor_buf[CDC_DATA_INTERFACE_INDEX] = *current_interface;
descriptor_buf[CDC_CONTROL_IN_ENDPOINT_INDEX] = repl
? (USB_CDC_EP_NUM_NOTIFICATION ? USB_CDC_EP_NUM_NOTIFICATION : *current_endpoint)
: (USB_CDC2_EP_NUM_NOTIFICATION ? USB_CDC2_EP_NUM_NOTIFICATION : *current_endpoint);
(*current_endpoint)++;
descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = repl
? (USB_CDC_EP_NUM_DATA_OUT ? USB_CDC_EP_NUM_DATA_OUT : *current_endpoint)
: (USB_CDC2_EP_NUM_DATA_OUT ? USB_CDC2_EP_NUM_DATA_OUT : *current_endpoint);
descriptor_buf[CDC_DATA_IN_ENDPOINT_INDEX] = repl
? (USB_CDC_EP_NUM_DATA_IN ? USB_CDC_EP_NUM_DATA_IN : *current_endpoint)
: (USB_CDC2_EP_NUM_DATA_IN ? USB_CDC2_EP_NUM_DATA_IN : *current_endpoint);
(*current_endpoint)++;
usb_add_interface_string(*current_interface_string,
repl ? repl_cdc_comm_interface_name : data_cdc_comm_interface_name);
descriptor_buf[CDC_COMM_INTERFACE_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
usb_add_interface_string(*current_interface_string,
repl ? repl_cdc_data_interface_name : data_cdc_data_interface_name);
descriptor_buf[CDC_DATA_INTERFACE_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
return sizeof(usb_midi_descriptor_template); return sizeof(usb_midi_descriptor_template);
} }

View File

@ -34,6 +34,6 @@ extern bool usb_cdc_data_enabled;
void usb_cdc_init(void); void usb_cdc_init(void);
size_t usb_cdc_descriptor_length(void); size_t usb_cdc_descriptor_length(void);
size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8 comm_interface, uint8_t data_interface, uint8_t control_in_endpoint, uint8_t data_in_endpoint, uint8_t data_out_endpoint, uint8_t comm_interface_string, uint8_t data_interface_string); size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string, bool repl);
#endif /* SHARED_MODULE_USB_CDC___INIT___H */ #endif /* SHARED_MODULE_USB_CDC___INIT___H */

View File

@ -24,4 +24,51 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
// Nothing needed here. Tables of HID devices are generated in autogen_usb_descriptor.c at compile-time. static const uint8_t usb_hid_descriptor_template[] = {
0x09, // 0 bLength
0x21, // 1 bDescriptorType (HID)
0x11, 0x01, // 2 bcdHID 1.11
0x00, // 3 bCountryCode
0x01, // 4 bNumDescriptors
0x22, // 5 bDescriptorType[0] (HID)
0xFF, 0xFF, // 6,7 wDescriptorLength[0] [SET AT RUNTIME: lo, hi]
#define HID_DESCRIPTOR_LENGTH_INDEX 6
0x07, // 8 bLength
0x05, // 9 bDescriptorType (Endpoint)
0xFF, // 10 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | endpoint]
#define HID_IN_ENDPOINT_INDEX 10
0x03, // 11 bmAttributes (Interrupt)
0x40, 0x00, // 12,13 wMaxPacketSize 64
0x08, // 14 bInterval 8 (unit depends on device speed)
0x07, // 15 bLength
0x05, // 16 bDescriptorType (Endpoint)
0xFF, // 17 bEndpointAddress (OUT/H2D) [SET AT RUNTIME]
#define HID_OUT_ENDPOINT_INDEX 17
0x03, // 18 bmAttributes (Interrupt)
0x40, 0x00, // 19,20 wMaxPacketSize 64
0x08, // 21 bInterval 8 (unit depends on device speed)
};
// Is the HID device enabled?
bool usb_hid_enabled;
size_t usb_hid_descriptor_length(void) {
return sizeof(usb_hid_descriptor);
}
static const char[] usb_hid_interface_name = USB_INTERFACE_NAME " Mass Storage";
size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string, uint16_t report_descriptor_length) {
memcpy(descriptor_buf, usb_hid_descriptor_template, sizeof(usb_hid_descriptor_template));
descriptor_buf[HID_DESCRIPTOR_LENGTH_INDEX] = report_descriptor_length & 0xFF;
descriptor_buf[HID_DESCRIPTOR_LENGTH_INDEX + 1] = (report_descriptor_length >> 8);
descriptor_buf[HID_IN_ENDPOINT_INDEX] = USB_HID_EP_NUM_IN ? USB_HID_EP_NUM_IN : *current_endpoint;
descriptor_buf[HID_OUT_ENDPOINT_INDEX] = 0x80 | (USB_HID_EP_NUM_OUT ? USB_HID_EP_NUM_OUT : *current_endpoint);
(*current_endpoint)++:
return sizeof(usb_hid_descriptor_template);
}

View File

@ -163,21 +163,41 @@ size_t usb_midi_descriptor_length(void) {
return sizeof(usb_midi_descriptor_template); return sizeof(usb_midi_descriptor_template);
} }
size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, static const char[] midi_streaming_interface_name = USB_INTERFACE_NAME " MIDI";
uint8_t audio_control_interface, uint8_t midi_streaming_interface, uint8_t midi_streaming_in_endpoint, uint8_t midi_streaming_out_endpoint, uint8_t audio_control_interface_string, uint8_t midi_streaming_interface_string, uint8_t in_jack_string, uint8_t out_jack_string) { static const char[] midi_audio_control_interface_name = USB_INTERFACE_NAME " Audio";
static const char[] midi_in_jack_name = USB_INTERFACE_NAME " usb_midi.ports[0]";
static const char[] midi_out_jack_name = USB_INTERFACE_NAME " usb_midi.ports[0]";
size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string) {
memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template)); memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template));
descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = audio_control_interface_number;
descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = audio_control_interface_string;
descriptor_buf[MSC_IN_ENDPOINT_INDEX] = midi_streaming_in_endpoint; descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = *current_interface;
descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | midi_streaming_out_endpoint; (*current_interface)++;
descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = midi_streaming_interface_number; descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint;
descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = midi_streaming_interface_number; descriptor_buf[MSC_OUT_ENDPOINT_INDEX] =
descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = midi_streaming_interface_string; 0x80 | (USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : *current_endpoint);
(*current_endpoint)++;
descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = in_jack_string; descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = *current_interface;
descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = out_jack_string; descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = *current_interface;
(*current_interface)++;
usb_add_interface_string(*current_interface, midi_streaming_interface_name);
descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = *current_interface;
(*current_interface_string)++;
usb_add_interface_string(*current_interface, midi_audio_control_interface_name);
descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = *current_interface;
(*current_interface_string)++;
usb_add_interface_string(*current_interface, midi_in_jack_name);
descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = *current_interface;
(*current_interface_string)++;
usb_add_interface_string(*current_interface, midi_out_jack_name);
descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = *current_interface;
(*current_interface_string)++;
return sizeof(usb_midi_descriptor_template); return sizeof(usb_midi_descriptor_template);
} }

View File

@ -33,6 +33,6 @@ void usb_midi_init(void);
void usb_midi_usb_init(void); void usb_midi_usb_init(void);
size_t usb_midi_descriptor_length(void); size_t usb_midi_descriptor_length(void);
size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t audio_control_interface, uint8_t midi_streaming_interface, uint8_t midi_streaming_in_endpoint, uint8_t midi_streaming_out_endpoint, uint8_t audio_control_interface_string, uint8_t midi_streaming_interface_string, uint8_t in_jack_string, uint8_t out_jack_string); size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string);
#endif /* SHARED_MODULE_USB_MIDI___INIT___H */ #endif /* SHARED_MODULE_USB_MIDI___INIT___H */

View File

@ -51,27 +51,6 @@ extern const tusb_desc_webusb_url_t desc_webusb_url;
static bool web_serial_connected = false; static bool web_serial_connected = false;
#endif #endif
// Serial number as hex characters. This writes directly to the USB
// descriptor.
extern uint16_t usb_serial_number[1 + COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2];
void load_serial_number(void) {
// create serial number based on device unique id
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
usb_serial_number[0] = 0x300 | sizeof(usb_serial_number);
for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) {
for (int j = 0; j < 2; j++) {
uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
// Strings are UTF-16-LE encoded.
usb_serial_number[1 + i * 2 + j] = nibble_to_hex_upper[nibble];
}
}
}
bool usb_enabled(void) { bool usb_enabled(void) {
return tusb_inited(); return tusb_inited();
} }
@ -80,8 +59,13 @@ MP_WEAK void post_usb_init(void) {
} }
void usb_init(void) { void usb_init(void) {
usb_build_device_descriptor();
usb_build_configuration_descriptor();
usb_build_hid_descriptor();
usb_build_string_descriptors();
init_usb_hardware(); init_usb_hardware();
load_serial_number();
tusb_init(); tusb_init();

View File

@ -46,9 +46,22 @@
#include "genhdr/autogen_usb_descriptor.h" #include "genhdr/autogen_usb_descriptor.h"
// ******* TODO PROTECT AGAINST GC.
static uint8_t *device_descriptor; static uint8_t *device_descriptor;
static uint8_t *config_descriptor; static uint8_t *config_descriptor;
// Table for collecting interface strings (interface names) as descriptor is built.
#define MAX_INTERFACE_STRINGS 16
// slot 0 is not used.
static char * collected_interface_strings[];
static uint16_t current_interface_string;
static const char[] manufacturer_name = USB_MANUFACTURER;
static const char[] product_name = USB_PRODUCT;
// Serial number string is UID length * 2 (2 nibbles per byte) + 1 byte for null termination.
static char serial_number_hex_string[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2 + 1];
static const uint8_t device_descriptor_template[] = { static const uint8_t device_descriptor_template[] = {
0x12, // 0 bLength 0x12, // 0 bLength
0x01, // 1 bDescriptorType (Device) 0x01, // 1 bDescriptorType (Device)
@ -87,8 +100,27 @@ static const uint8_t configuration_descriptor_template[] = {
0x32, // 8 bMaxPower 100mA 0x32, // 8 bMaxPower 100mA
}; };
void build_usb_device_descriptor(uint16_t vid, uint16_t pid, uint8_t manufacturer_string_index, uint8_t product_string_index, uint8_t serial_number_string_index) { void usb_desc_init(void) {
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) {
for (int j = 0; j < 2; j++) {
uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
serial_number_hex_string[i * 2 + (1 - j)] = nibble_to_hex_upper[nibble];
}
}
// Null-terminate the string.
serial_number_hex_string[sizeof(serial_number_hex_string)] = '\0';
// Set to zero when allocated; we depend on that.
collected_interface_strings = m_malloc(MAX_INTERFACE_STRINGS + 1, false);
current_interface_string = 1;
}
void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string) {
device_descriptor = m_malloc(sizeof(device_descriptor_template), false); device_descriptor = m_malloc(sizeof(device_descriptor_template), false);
memcpy(device_descriptor, device_descriptor_template, sizeof(device_descriptor_template)); memcpy(device_descriptor, device_descriptor_template, sizeof(device_descriptor_template));
@ -96,12 +128,21 @@ void build_usb_device_descriptor(uint16_t vid, uint16_t pid, uint8_t manufacture
device_descriptor[DEVICE_VID_HI_INDEX] = vid >> 8; device_descriptor[DEVICE_VID_HI_INDEX] = vid >> 8;
device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF; device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF;
device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8; device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8;
device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = manufacturer_string_index;
device_descriptor[DEVICE_PRODUCT_STRING_INDEX] = product_string_index; usb_add_interface_string(*current_interface_string, manufacturer_name);
device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = serial_number_string_index; device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
usb_add_interface_string(*current_interface_string, product_name);
device_descriptor[DEVICE_PRODUCT_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
usb_add_interface_string(*current_interface_string, serial_number_hex_string);
device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = *current_interface_string;
(*current_interface_string)++;
} }
void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) { void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) {
size_t total_descriptor_length = sizeof(configuration_descriptor_template); size_t total_descriptor_length = sizeof(configuration_descriptor_template);
// CDC should be first, for compatibility with Adafruit Windows 7 drivers. // CDC should be first, for compatibility with Adafruit Windows 7 drivers.
@ -143,19 +184,22 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter
configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF; configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF;
// Number interfaces and endpoints. // Number interfaces and endpoints.
// Endpoint 0 is already used for USB control. // Endpoint 0 is already used for USB control, so start with 1.
uint8_t current_interface = 0; uint8_t current_interface = 0;
uint8_t current_endpoint = 1; uint8_t current_endpoint = 1;
uint16_t current_interface_string = 1;
uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template); uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template);
#if CIRCUITPY_USB_CDC #if CIRCUITPY_USB_CDC
if (usb_cdc_repl_enabled) { if (usb_cdc_repl_enabled) {
// Concatenate and fix up the CDC REPL descriptor. // Concatenate and fix up the CDC REPL descriptor.
descriptor_buf_remaining += usb_cdc_add_descriptor(
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string, true);
} }
if (usb_cdc_data_enabled) { if (usb_cdc_data_enabled) {
// Concatenate and fix up the CDC data descriptor. // Concatenate and fix up the CDC data descriptor.
descriptor_buf_remaining += usb_cdc_add_descriptor(
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string, false);
} }
#endif #endif
@ -163,13 +207,7 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter
if (storage_usb_enabled) { if (storage_usb_enabled) {
// Concatenate and fix up the MSC descriptor. // Concatenate and fix up the MSC descriptor.
descriptor_buf_remaining += storage_usb_add_descriptor( descriptor_buf_remaining += storage_usb_add_descriptor(
descriptor_buf_remaining, current_interface, descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
current_endpoint, // in
current_endpoint, // out
current_interface_string_index);
current_interface++;
current_endpoint++;
current_interface_string++;
} }
#endif #endif
@ -177,26 +215,14 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter
if (usb_midi_enabled) { if (usb_midi_enabled) {
// Concatenate and fix up the MIDI descriptor. // Concatenate and fix up the MIDI descriptor.
descriptor_buf_remaining += usb_midi_add_descriptor( descriptor_buf_remaining += usb_midi_add_descriptor(
descriptor_buf_remaining, descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
current_interface, // audio control
current_interface + 1, // MIDI streaming
current_endpoint, // in
current_endpoint, // out
current_interface_string, // audio control
current_interface_string + 1 // MIDI streaming
current_interface_string + 2 // in jack
current_interface_string + 3 // out jack
);
current_interface += 2; // two interfaces: audio control and MIDI streaming
current_endpoint++; // MIDI streaming only (no audio data)
current_interface_string += 4; // two interface names: audio control and MIDI streaming
} }
#endif #endif
#if CIRCUITPY_USB_HID #if CIRCUITPY_USB_HID
if (usb_hid_enabled) { if (usb_hid_enabled) {
// Concatenate and fix up the HID descriptor (not the report descriptors). descriptor_buf_remaining += usb_hid_add_descriptor(
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
} }
#endif #endif
@ -210,13 +236,33 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter
} }
// Invoked when received GET DEVICE DESCRIPTOR void usb_add_interface_string(uint8_t interface_string_index, const char[] str) {
if (interface_string_index > MAX_INTERFACE_STRINGS) {
mp_raise_SystemError("Too many USB interface names");
}
// 2 bytes for String Descriptor header, then 2 bytes for each character
const size_t str_len = strlen(str);
uint8_t descriptor_size = 2 + (str_len * 2);
uint16_t *string_descriptor = (uint16_t *) m_malloc(descriptor_size, false);
string_descriptor[0] = 0x0300 | descriptor_size;
// Convert to le16
for (i = 0; i <= str_len; i++) {
string_descriptor[i + 1] = str[i];
}
collected_interface_strings[interface_string_index] = string_descriptor;
}
void usb_
// Invoked when GET DEVICE DESCRIPTOR is received.
// Application return pointer to descriptor // Application return pointer to descriptor
uint8_t const *tud_descriptor_device_cb(void) { uint8_t const *tud_descriptor_device_cb(void) {
return usb_descriptor_dev; return usb_descriptor_dev;
} }
// Invoked when received GET CONFIGURATION DESCRIPTOR // Invoked when GET CONFIGURATION DESCRIPTOR is received.
// Application return pointer to descriptor // Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete // Descriptor contents must exist long enough for transfer to complete
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
@ -225,7 +271,7 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
} }
#if CIRCUITPY_USB_HID #if CIRCUITPY_USB_HID
// Invoked when received GET HID REPORT DESCRIPTOR // Invoked when GET HID REPORT DESCRIPTOR is received.
// Application return pointer to descriptor // Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete // Descriptor contents must exist long enough for transfer to complete
uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) { uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) {
@ -234,9 +280,11 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) {
} }
#endif #endif
// Invoked when received GET STRING DESCRIPTOR request // Invoked when GET STRING DESCRIPTOR request is received.
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
uint8_t const max_index = sizeof(string_descriptor_arr) / sizeof(string_descriptor_arr[0]); if (index > MAX_INTERFACE_STRINGS) {
return (index < max_index) ? string_descriptor_arr[index] : NULL; return NULL;
}
return collected_interface_strings[index];
} }

View File

@ -76,7 +76,6 @@ else
supervisor/usb.c \ supervisor/usb.c \
supervisor/shared/usb/usb_desc.c \ supervisor/shared/usb/usb_desc.c \
supervisor/shared/usb/usb.c \ supervisor/shared/usb/usb.c \
$(BUILD)/autogen_usb_descriptor.c \
ifeq ($(CIRCUITPY_USB_CDC), 1) ifeq ($(CIRCUITPY_USB_CDC), 1)
SRC_SUPERVISOR += \ SRC_SUPERVISOR += \
@ -159,61 +158,24 @@ USB_HIGHSPEED ?= 0
USB_CDC_EP_NUM_NOTIFICATION ?= 0 USB_CDC_EP_NUM_NOTIFICATION ?= 0
USB_CDC_EP_NUM_DATA_OUT ?= 0 USB_CDC_EP_NUM_DATA_OUT ?= 0
USB_CDC_EP_NUM_DATA_IN ?= 0 USB_CDC_EP_NUM_DATA_IN ?= 0
USB_CDC2_EP_NUM_NOTIFICATION ?= 0
USB_CDC2_EP_NUM_DATA_OUT ?= 0
USB_CDC2_EP_NUM_DATA_IN ?= 0
USB_MSC_EP_NUM_OUT ?= 0 USB_MSC_EP_NUM_OUT ?= 0
USB_MSC_EP_NUM_IN ?= 0 USB_MSC_EP_NUM_IN ?= 0
USB_HID_EP_NUM_OUT ?= 0 USB_HID_EP_NUM_OUT ?= 0
USB_HID_EP_NUM_IN ?= 0 USB_HID_EP_NUM_IN ?= 0
USB_MIDI_EP_NUM_OUT ?= 0 USB_MIDI_EP_NUM_OUT ?= 0
USB_MIDI_EP_NUM_IN ?= 0 USB_MIDI_EP_NUM_IN ?= 0
USB_NUM_EP ?= 0 USB_NUM_EP ?= 0
USB_DESCRIPTOR_ARGS = \
--manufacturer $(USB_MANUFACTURER)\
--product $(USB_PRODUCT)\
--vid $(USB_VID)\
--pid $(USB_PID)\
--serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\
--interface_name_prefix $(USB_INTERFACE_NAME)\
--devices "$(USB_DEVICES)"\
--hid_devices "$(USB_HID_DEVICES)"\
--max_ep $(USB_NUM_EP) \
--cdc_ep_num_notification $(USB_CDC_EP_NUM_NOTIFICATION)\
--cdc_ep_num_data_out $(USB_CDC_EP_NUM_DATA_OUT)\
--cdc_ep_num_data_in $(USB_CDC_EP_NUM_DATA_IN)\
--msc_ep_num_out $(USB_MSC_EP_NUM_OUT)\
--msc_ep_num_in $(USB_MSC_EP_NUM_IN)\
--hid_ep_num_out $(USB_HID_EP_NUM_OUT)\
--hid_ep_num_in $(USB_HID_EP_NUM_IN)\
--midi_ep_num_out $(USB_MIDI_EP_NUM_OUT)\
--midi_ep_num_in $(USB_MIDI_EP_NUM_IN)\
--output_c_file $(BUILD)/autogen_usb_descriptor.c\
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
ifeq ($(CIRCUITPY_USB_VENDOR), 1)
USB_DESCRIPTOR_ARGS += \
--vendor_ep_num_out 0 --vendor_ep_num_in 0 \
--webusb_url $(USB_WEBUSB_URL)
endif
ifeq ($(USB_RENUMBER_ENDPOINTS), 0)
USB_DESCRIPTOR_ARGS += --no-renumber_endpoints
endif
ifeq ($(USB_HIGHSPEED), 1)
USB_DESCRIPTOR_ARGS += --highspeed
endif
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate
.INTERMEDIATE: autogen_usb_descriptor.intermediate
autogen_usb_descriptor.intermediate: ../../tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD)
$(STEPECHO) "GEN $@"
$(Q)install -d $(BUILD)/genhdr
$(Q)$(PYTHON3) ../../tools/gen_usb_descriptor.py $(USB_DESCRIPTOR_ARGS)
CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf" CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf"
$(BUILD)/autogen_display_resources.c: ../../tools/gen_display_resources.py $(HEADER_BUILD)/qstrdefs.generated.h Makefile | $(HEADER_BUILD) $(BUILD)/autogen_display_resources.c: ../../tools/gen_display_resources.py $(HEADER_BUILD)/qstrdefs.generated.h Makefile | $(HEADER_BUILD)

View File

@ -53,6 +53,11 @@ bool usb_enabled(void);
void usb_init(void); void usb_init(void);
void usb_disconnect(void); void usb_disconnect(void);
void usb_add_interface_string(uint8_t interface_string_index, const char[] str);
void usb_desc_init(void);
void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string);
void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces);
// Propagate plug/unplug events to the MSC logic. // Propagate plug/unplug events to the MSC logic.
#if CIRCUITPY_USB_MSC #if CIRCUITPY_USB_MSC
void usb_msc_mount(void); void usb_msc_mount(void);