wip: starting to try to compile

This commit is contained in:
Dan Halbert 2021-04-25 23:17:41 -04:00
parent 9d1fcc3b14
commit c26e49c2e6
17 changed files with 149 additions and 2383 deletions

View File

@ -62,33 +62,4 @@ The tinyusb examples already include a "WebUSB serial" example.
Basically, this feature was ported into CircuitPython by pulling code snippets out of the
tinyusb example, and putting them where they best belonged in the CircuitPython codebase.
There was one complication:
tinyusb uses C preprocessor macros to define things like USB descriptors.
CircuitPython uses a Python program (tools/gen_usb_descriptor.py) to create USB descriptors (etc.)
using "helper objects" from another repo (adafruit_usb_descriptor). This means some of the example
code had to be adapted to the new programing model, and gen_usb_descriptor gained new command-line
options to control the generated code.
The generated files go into the "build" directory, look for autogen_usb_descriptor.c and
genhdr/autogen_usb_descriptor.h.
Also worth pointing out - the re-use of the CDC connect/disconnect mechanism is not actually part
of the WebUSB standard, it's more of "common idiom". We make use of it here because we need to know
when we should be paying attention to the WebUSB serial interface, and when we should ignore it..
## Possible future work areas
The current code uses the existing Python infrastructure to create the Interface descriptor, but
simply outputs the code snippets from the original tinyusb demo code to create the WEBUSB_URL,
BOS, and MS_OS_20 descriptors. I suppose additional work could be done to add these to the
adafruit_usb_descriptor project, and then gen_usb_descriptor.py could be modified to make use
of them.
Program gen_usb_descriptor.py creates objects for most interface types, regardless of whether or
not they are actually enabled. This increases the size of a generated string table. I made the
new vendor-interface-related code not do this (because some of the ARM platforms would no longer
build), but I did not go back and do this for the other interface types (CDC, MIDI, HID, etc.)
Some FLASH savings are probably possible if this is done.
### TODO: This needs to be reworked for dynamic USB descriptors.

8
main.c
View File

@ -518,7 +518,6 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
}
#endif
// TODO(tannewt): Allocate temporary space to hold custom usb descriptors.
filesystem_flush();
supervisor_allocation* heap = allocate_remaining_memory();
start_mp(heap);
@ -535,6 +534,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
boot_output_file = NULL;
#endif
#if CIRCUITPY_USB
// Remember USB settings done during boot.py.
// Call this before the boot.py heap is destroyed.
usb_post_boot_py();
#endif
cleanup_after_vm(heap);
}
}
@ -588,6 +593,7 @@ int __attribute__((used)) main(void) {
// Port-independent devices, like CIRCUITPY_BLEIO_HCI.
reset_devices();
reset_board();
reset_usb();
// This is first time we are running CircuitPython after a reset or power-up.
supervisor_set_run_reason(RUN_REASON_STARTUP);

View File

@ -2,60 +2,29 @@
#ifndef HPL_USB_CONFIG_H
#define HPL_USB_CONFIG_H
// CIRCUITPY:
// CIRCUITPY: Since we have dynamic USB descriptors, we may end up using all endpoints.
// So provide cache space for all of them.
// Use 64-byte USB buffers for endpoint directions that are in use. They're set to 0 below otherwise.
#include "genhdr/autogen_usb_descriptor.h"
#if defined(USB_ENDPOINT_1_OUT_USED) && USB_ENDPOINT_1_OUT_USED
#define CONF_USB_EP1_CACHE 64
#endif
#if defined(USB_ENDPOINT_1_IN_USED) && USB_ENDPOINT_1_IN_USED
#define CONF_USB_EP1_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_OUT_USED) && USB_ENDPOINT_2_OUT_USED
#define CONF_USB_EP2_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_IN_USED) && USB_ENDPOINT_2_IN_USED
#define CONF_USB_EP2_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_OUT_USED) && USB_ENDPOINT_3_OUT_USED
#define CONF_USB_EP3_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_IN_USED) && USB_ENDPOINT_3_IN_USED
#define CONF_USB_EP3_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_OUT_USED) && USB_ENDPOINT_4_OUT_USED
#define CONF_USB_EP4_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_IN_USED) && USB_ENDPOINT_4_IN_USED
#define CONF_USB_EP4_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_OUT_USED) && USB_ENDPOINT_5_OUT_USED
#define CONF_USB_EP5_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_IN_USED) && USB_ENDPOINT_5_IN_USED
#define CONF_USB_EP5_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_OUT_USED) && USB_ENDPOINT_6_OUT_USED
#define CONF_USB_EP6_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_IN_USED) && USB_ENDPOINT_6_IN_USED
#define CONF_USB_EP6_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_OUT_USED) && USB_ENDPOINT_7_OUT_USED
#define CONF_USB_EP7_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_IN_USED) && USB_ENDPOINT_7_IN_USED
#define CONF_USB_EP7_I_CACHE 64
#endif
// <<< Use Configuration Wizard in Context Menu >>>

View File

@ -2,60 +2,29 @@
#ifndef HPL_USB_CONFIG_H
#define HPL_USB_CONFIG_H
// CIRCUITPY:
// CIRCUITPY: Since we have dynamic USB descriptors, we may end up using all endpoints.
// So provide cache space for all of them.
// Use 64-byte USB buffers for endpoint directions that are in use. They're set to 0 below otherwise.
#include "genhdr/autogen_usb_descriptor.h"
#if defined(USB_ENDPOINT_1_OUT_USED) && USB_ENDPOINT_1_OUT_USED
#define CONF_USB_EP1_CACHE 64
#endif
#if defined(USB_ENDPOINT_1_IN_USED) && USB_ENDPOINT_1_IN_USED
#define CONF_USB_EP1_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_OUT_USED) && USB_ENDPOINT_2_OUT_USED
#define CONF_USB_EP2_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_IN_USED) && USB_ENDPOINT_2_IN_USED
#define CONF_USB_EP2_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_OUT_USED) && USB_ENDPOINT_3_OUT_USED
#define CONF_USB_EP3_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_IN_USED) && USB_ENDPOINT_3_IN_USED
#define CONF_USB_EP3_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_OUT_USED) && USB_ENDPOINT_4_OUT_USED
#define CONF_USB_EP4_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_IN_USED) && USB_ENDPOINT_4_IN_USED
#define CONF_USB_EP4_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_OUT_USED) && USB_ENDPOINT_5_OUT_USED
#define CONF_USB_EP5_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_IN_USED) && USB_ENDPOINT_5_IN_USED
#define CONF_USB_EP5_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_OUT_USED) && USB_ENDPOINT_6_OUT_USED
#define CONF_USB_EP6_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_IN_USED) && USB_ENDPOINT_6_IN_USED
#define CONF_USB_EP6_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_OUT_USED) && USB_ENDPOINT_7_OUT_USED
#define CONF_USB_EP7_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_IN_USED) && USB_ENDPOINT_7_IN_USED
#define CONF_USB_EP7_I_CACHE 64
#endif
// <<< Use Configuration Wizard in Context Menu >>>

View File

@ -2,60 +2,29 @@
#ifndef HPL_USB_CONFIG_H
#define HPL_USB_CONFIG_H
// CIRCUITPY:
// CIRCUITPY: Since we have dynamic USB descriptors, we may end up using all endpoints.
// So provide cache space for all of them.
// Use 64-byte USB buffers for endpoint directions that are in use. They're set to 0 below otherwise.
#include "genhdr/autogen_usb_descriptor.h"
#if defined(USB_ENDPOINT_1_OUT_USED) && USB_ENDPOINT_1_OUT_USED
#define CONF_USB_EP1_CACHE 64
#endif
#if defined(USB_ENDPOINT_1_IN_USED) && USB_ENDPOINT_1_IN_USED
#define CONF_USB_EP1_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_OUT_USED) && USB_ENDPOINT_2_OUT_USED
#define CONF_USB_EP2_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_IN_USED) && USB_ENDPOINT_2_IN_USED
#define CONF_USB_EP2_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_OUT_USED) && USB_ENDPOINT_3_OUT_USED
#define CONF_USB_EP3_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_IN_USED) && USB_ENDPOINT_3_IN_USED
#define CONF_USB_EP3_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_OUT_USED) && USB_ENDPOINT_4_OUT_USED
#define CONF_USB_EP4_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_IN_USED) && USB_ENDPOINT_4_IN_USED
#define CONF_USB_EP4_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_OUT_USED) && USB_ENDPOINT_5_OUT_USED
#define CONF_USB_EP5_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_IN_USED) && USB_ENDPOINT_5_IN_USED
#define CONF_USB_EP5_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_OUT_USED) && USB_ENDPOINT_6_OUT_USED
#define CONF_USB_EP6_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_IN_USED) && USB_ENDPOINT_6_IN_USED
#define CONF_USB_EP6_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_OUT_USED) && USB_ENDPOINT_7_OUT_USED
#define CONF_USB_EP7_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_IN_USED) && USB_ENDPOINT_7_IN_USED
#define CONF_USB_EP7_I_CACHE 64
#endif
// <<< Use Configuration Wizard in Context Menu >>>

View File

@ -2,60 +2,29 @@
#ifndef HPL_USB_CONFIG_H
#define HPL_USB_CONFIG_H
// CIRCUITPY:
// CIRCUITPY: Since we have dynamic USB descriptors, we may end up using all endpoints.
// So provide cache space for all of them.
// Use 64-byte USB buffers for endpoint directions that are in use. They're set to 0 below otherwise.
#include "genhdr/autogen_usb_descriptor.h"
#if defined(USB_ENDPOINT_1_OUT_USED) && USB_ENDPOINT_1_OUT_USED
#define CONF_USB_EP1_CACHE 64
#endif
#if defined(USB_ENDPOINT_1_IN_USED) && USB_ENDPOINT_1_IN_USED
#define CONF_USB_EP1_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_OUT_USED) && USB_ENDPOINT_2_OUT_USED
#define CONF_USB_EP2_CACHE 64
#endif
#if defined(USB_ENDPOINT_2_IN_USED) && USB_ENDPOINT_2_IN_USED
#define CONF_USB_EP2_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_OUT_USED) && USB_ENDPOINT_3_OUT_USED
#define CONF_USB_EP3_CACHE 64
#endif
#if defined(USB_ENDPOINT_3_IN_USED) && USB_ENDPOINT_3_IN_USED
#define CONF_USB_EP3_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_OUT_USED) && USB_ENDPOINT_4_OUT_USED
#define CONF_USB_EP4_CACHE 64
#endif
#if defined(USB_ENDPOINT_4_IN_USED) && USB_ENDPOINT_4_IN_USED
#define CONF_USB_EP4_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_OUT_USED) && USB_ENDPOINT_5_OUT_USED
#define CONF_USB_EP5_CACHE 64
#endif
#if defined(USB_ENDPOINT_5_IN_USED) && USB_ENDPOINT_5_IN_USED
#define CONF_USB_EP5_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_OUT_USED) && USB_ENDPOINT_6_OUT_USED
#define CONF_USB_EP6_CACHE 64
#endif
#if defined(USB_ENDPOINT_6_IN_USED) && USB_ENDPOINT_6_IN_USED
#define CONF_USB_EP6_I_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_OUT_USED) && USB_ENDPOINT_7_OUT_USED
#define CONF_USB_EP7_CACHE 64
#endif
#if defined(USB_ENDPOINT_7_IN_USED) && USB_ENDPOINT_7_IN_USED
#define CONF_USB_EP7_I_CACHE 64
#endif
// <<< Use Configuration Wizard in Context Menu >>>

View File

@ -308,6 +308,9 @@ CFLAGS += -DCIRCUITPY_STRUCT=$(CIRCUITPY_STRUCT)
CIRCUITPY_SUPERVISOR ?= 1
CFLAGS += -DCIRCUITPY_SUPERVISOR=$(CIRCUITPY_SUPERVISOR)
CIRCUITPY_SYNTHIO ?= $(CIRCUITPY_AUDIOCORE)
CFLAGS += -DCIRCUITPY_SYNTHIO=$(CIRCUITPY_SYNTHIO)
CIRCUITPY_TERMINALIO ?= $(CIRCUITPY_DISPLAYIO)
CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO)
@ -325,39 +328,34 @@ CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO)
CIRCUITPY_UHEAP ?= 0
CFLAGS += -DCIRCUITPY_UHEAP=$(CIRCUITPY_UHEAP)
# Secondary CDC is usually available if there are at least 8 endpoints.
CIRCUITPY_USB_CDC ?= $(shell expr $(USB_NUM_EP) '>=' 8)
CIRCUITPY_USB ?= 1
CFLAGS += -DCIRCUITPY_USB=$(CIRCUITPY_USB)
# If you need to count endpoints, do:
# $(shell expr $(USB_NUM_EP) '>=' 8)
CIRCUITPY_USB_CDC ?= 1
CFLAGS += -DCIRCUITPY_USB_CDC=$(CIRCUITPY_USB_CDC)
CIRCUITPY_USB_CDC_REPL_ENABLED ?= 1
CFLAGS += -DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT)
CIRCUITPY_USB_CDC_DATA_ENABLED ?= 0
CFLAGS += -DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT)
CIRCUITPY_USB_HID ?= 1
CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID)
CIRCUITPY_USB_HID_ENABLED_DEFAULT = $(CIRCUITPY_USB_HID)
CFLAGS += -DCIRCUITPY_USB_HID_ENABLED_DEFAULT=$(CIRCUITPY_USB_HID_ENABLED_DEFAULT)
CIRCUITPY_USB_HID_CONSUMER ?= 1
CFLAGS += -DCIRCUITPY_USB_HID_CONSUMER=$(CIRCUITPY_USB_HID_CONSUMER)
CIRCUITPY_USB_HID_DIGITIZER ?= 0
CFLAGS += -DCIRCUITPY_USB_HID_DIGITIZER=$(CIRCUITPY_USB_HID_DIGITIZER)
CIRCUITPY_USB_HID_GAMEPAD ?= 1
CFLAGS += -DCIRCUITPY_USB_HID_GAMEPAD=$(CIRCUITPY_USB_HID_GAMEPAD)
CIRCUITPY_USB_HID_KEYBOARD ?= 1
CFLAGS += -DCIRCUITPY_USB_HID_KEYBOARD=$(CIRCUITPY_USB_HID_KEYBOARD)
CIRCUITPY_USB_HID_MOUSE ?= 1
CFLAGS += -DCIRCUITPY_USB_HID_MOUSE=$(CIRCUITPY_USB_HID_MOUSE)
CIRCUITPY_USB_HID_SYS_CONTROL ?= 0
CFLAGS += -DCIRCUITPY_USB_HID_SYS_CONTROL=$(CIRCUITPY_USB_HID_SYS_CONTROL)
CIRCUITPY_USB_HID_XAC_COMPATIBLE_GAMEPAD ?= 0
CFLAGS += -DCIRCUITPY_USB_HID_XAC_COMPATIBLE_GAMEPAD=$(CIRCUITPY_USB_HID_XAC_COMPATIBLE_GAMEPAD)
CIRCUITPY_USB_MIDI ?= 1
# MIDI is usually available if there are at least 8 endpoints.
CIRCUITPY_USB_MIDI ?= $(shell expr $(USB_NUM_EP) '>=' 8)
CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI)
CIRCUITPY_USB_MIDI_ENABLED_DEFAULT = $(CIRCUITPY_USB_MIDI)
CFLAGS += -DCIRCUITPY_USB_MIDI_ENABLED_DEFAULT=$(CIRCUITPY_USB_MIDI_ENABLED_DEFAULT)
CIRCUITPY_USB_MSC ?= 1
CFLAGS += -DCIRCUITPY_USB_MSC=$(CIRCUITPY_USB_MSC)
CIRCUITPY_USB_MSC_ENABLED_DEFAULT = $(CIRCUITPY_USB_MSC)
CFLAGS += -DCIRCUITPY_USB_MSC_ENABLED_DEFAULT=$(CIRCUITPY_USB_MSC_ENABLED_DEFAULT)
# Defaulting this to OFF initially because it has only been tested on a
# limited number of platforms, and the other platforms do not have this

View File

@ -53,23 +53,19 @@
STATIC mp_obj_t usb_hid_configure_usb(mp_obj_t devices) {
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(devices, &iter_buf);
mp_obj_t device;
while ((device = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
const mp_int_t len = mp_obj_get_int(mp_obj_len(devices_seq));
for (size_t i = 0; i < len; i++) {
mp_obj_t item = mp_obj_subscr(devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL);
if (!MP_OBJ_IS_TYPE(item, &usb_hid_device_type)) {
mp_raise_ValueError_varg(translate("non-Device in %q", MP_QSTR_devices));
}
}
switch (common_hal_usb_hid_configure_usb(descriptors)) {
case USB_CONFIG_TOO_LATE:
mp_raise_RuntimeError(translate("Cannot change USB devices now"));
break;
case USB_CONFIG_NON_DEVICE:
mp_raise_ValueError_varg(translate("non-Device in %q", MP_QSTR_devices));
break;
default:
if (!common_hal_usb_hid_configure_usb(descriptors)) {
mp_raise_RuntimeError(translate("Cannot change USB devices now"));
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(usb_hid_configure_usb_obj, usb_hid_configure_usb);

View File

@ -32,10 +32,7 @@
extern mp_obj_tuple_t common_hal_usb_hid_devices;
typedef enum {
USB_CONFIG_OK = 0,
USB_CONFIG_TOO_LATE = 1,
USB_CONFIG_NON_DEVICE = 2,
} usb_hid_configure_status;
void common_hal_usb_hid_configure_usb_defaults(void);
usb_hid_configure_status common_hal_usb_hid_configure_usb(mp_obj_t devices_seq);
usb_hid_configure_status common_hal_usb_hid_configure_usb(mp_obj_t devices_seqf // SHARED_BINDINGS_USB_HID_H
#endif // SHARED_BINDINGS_USB_HID_H

View File

@ -24,7 +24,6 @@
* THE SOFTWARE.
*/
#include "genhdr/autogen_usb_descriptor.h"
#include "py/gc.h"
#include "py/obj.h"
#include "py/mphal.h"

View File

@ -51,6 +51,9 @@ static const uint8_t usb_hid_descriptor_template[] = {
0x08, // 21 bInterval 8 (unit depends on device speed)
};
// Sequence of devices to configure.
static mp_obj_t hid_devices_seq;
// Is the HID device enabled?
bool usb_hid_enabled;
supervisor_allocation *hid_report_descriptor_allocation;
@ -78,23 +81,35 @@ size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfac
return sizeof(usb_hid_descriptor_template);
}
usb_hid_configure_status common_hal_usb_hid_configure_usb(mp_obj_t devices_seq) {
static mp_obj_t default_hid_devices[] = {
MP_OBJ_FROM_PTR(usb_hid_device_keyboard_obj),
MP_OBJ_FROM_PTR(usb_hid_device_mouse_obj),
};
// Set the default list of devices that will be included. Called before boot.py runs, in the boot.py VM.
void common_hal_usb_hid_configure_usb_defaults(void) {
common_hal_usb_hid_configure_usb(mp_obj_new_tuple(sizeof(default_hid_devices), default_hid_devices));
}
bool common_hal_usb_hid_configure_usb(mp_obj_t devices_seq) {
// We can't change the devices once we're connected.
if (tud_connected()) {
return USB_CONFIG_TOO_LATE;
return false;
}
// Assume no devices to start.
usb_hid_enabled = false;
if (devices_seq == mp_const_none) {
return USB_CONFIG_OK;
}
// Remember the devices for use in usb_hid_post_boot_py.
hid_devices_seq = devices_seq;
return true;
}
// Build the combined HID report descriptor and save the chosen devices.
// Both are saved in supervisor allocations.
void usb_hid_post_boot_py(void) {
size_t total_report_descriptors_length = 0;
// Build a combined report descriptor
mp_int_t len = mp_obj_get_int(mp_obj_len(devices_seq));
mp_int_t len = mp_obj_get_int(mp_obj_len(hid_devices_seq));
// First get the total size.
for (size_t i = 0; i < len; i++) {
@ -128,7 +143,7 @@ usb_hid_configure_status common_hal_usb_hid_configure_usb(mp_obj_t devices_seq)
uint8_t *descriptor_start = (uint8_t *) hid_report_descriptor_allocation->ptr;
for (size_t i = 0; i < len; i++) {
usb_hid_device_obj_t *device = MP_OBJ_TO_PTR(devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL);
usb_hid_device_obj_t *device = MP_OBJ_TO_PTR(hid_devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL);
// Copy the report descriptor for this device.
if (len == 1) {
@ -150,6 +165,8 @@ usb_hid_configure_status common_hal_usb_hid_configure_usb(mp_obj_t devices_seq)
hid_devices[i].descriptor_obj = mp_const_none;
}
// No longer keeping the Python object of devices to configure.
hid_devices_seq = MP_OBJ_NULL;
}
void usb_hid_gc_collect(void) {
@ -158,7 +175,8 @@ void usb_hid_gc_collect(void) {
free_memory(hid_report_descriptor_allocation);
free_memory(usb_hid_devices_allocation);
} else {
gc_collect_ptr(hid_devices_seq);
gc_collect_ptr(hid_report_descriptor_allocation->ptr);
gc_collect_ptr(usb_hid_devices_allocation);
gc_collect_ptr(usb_hid_devices_allocation_ptr);
}
}

View File

@ -26,7 +26,6 @@
#include "shared-bindings/usb_midi/__init__.h"
#include "genhdr/autogen_usb_descriptor.h"
#include "py/obj.h"
#include "py/mphal.h"
#include "py/runtime.h"

View File

@ -38,8 +38,6 @@
#ifndef _TUSB_CONFIG_H_
#define _TUSB_CONFIG_H_
#include "genhdr/autogen_usb_descriptor.h"
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -41,7 +41,6 @@
#include "tusb.h"
#if CIRCUITPY_USB_VENDOR
#include "genhdr/autogen_usb_descriptor.h"
// The WebUSB support being conditionally added to this file is based on the
// tinyusb demo examples/device/webusb_serial.
@ -55,15 +54,17 @@ bool usb_enabled(void) {
return tusb_inited();
}
// Initialization done only once, before boot.py is run.
void reset_usb(void) {
reset_usb_desc();
}
MP_WEAK void post_usb_init(void) {
}
void usb_init(void) {
usb_build_device_descriptor();
usb_build_configuration_descriptor();
usb_build_hid_descriptor();
usb_build_string_descriptors();
usb_desc_init();
init_usb_hardware();
@ -82,6 +83,13 @@ void usb_init(void) {
#endif
}
// Remember USB settings done during boot.py.
// The boot.py heap is still valid at this point.
void usb_post_boot_py(void) {
usb_desc_post_boot_py();
}
void usb_disconnect(void) {
tud_disconnect();
}

View File

@ -44,10 +44,8 @@
#include "shared-module/usb_hid/Device.h"
#include "genhdr/autogen_usb_descriptor.h"
supervisor_allocation *device_descriptor_allocation;
supervisor_allocation *config_descriptor_allocation;
uint8_t *device_descriptor;
uint8_t *config_descriptor;
// Table for collecting interface strings (interface names) as descriptor is built.
#define MAX_INTERFACE_STRINGS 16
@ -99,31 +97,31 @@ static const uint8_t configuration_descriptor_template[] = {
0x32, // 8 bMaxPower 100mA
};
void usb_desc_init(void) {
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
common_hal_mcu_processor_get_uid(raw_id);
// Initialization done before boot.py is run.
// Turn on or off various USB devices. On devices with limited endpoints,
// some may be off by default.
void reset_usb_desc(void) {
// Set defaults for enabling/disabling of various USB devices.
#if CIRCUITPY_USB_CDC
common_hal_usb_cdc_configure_usb(
(bool) CIRCUITPY_USB_CDC_REPL_ENABLED_DEFAULT,
(bool) CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT);
#endif
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];
}
}
#if CIRCUITPY_USB_MSC
common_hal_storage_configure_usb((bool) CIRCUITPY_USB_MSC_ENABLED_DEFAULT);
#endif
// Null-terminate the string.
serial_number_hex_string[sizeof(serial_number_hex_string)] = '\0';
#if CIRCUITPY_USB_MIDI
common_hal_usb_midi_configure_usb((bool) CIRCUITPY_USB_MIDI_ENABLED_DEFAULT);
#endif
// Memory is cleared to zero when allocated; we depend on that.
collected_interface_strings = m_malloc(MAX_INTERFACE_STRINGS + 1, false);
current_interface_string = 1;
#if CIRCUITPY_USB_HID
common_hal_usb_hid_configure_usb_default();
#endif
}
void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string) {
device_descriptor_allocation =
allocate_memory(sizeof(device_descriptor_template), false /*highaddress*/, true /*movable*/);
uint8_t *device_descriptor = (uint8_t *) device_descriptor_allocation->ptr;
static void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string) {
memcpy(device_descriptor, device_descriptor_template, sizeof(device_descriptor_template));
device_descriptor[DEVICE_VID_LO_INDEX] = vid & 0xFF;
@ -144,7 +142,7 @@ void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_in
(*current_interface_string)++;
}
void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) {
static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) {
size_t total_descriptor_length = sizeof(configuration_descriptor_template);
// CDC should be first, for compatibility with Adafruit Windows 7 drivers.
@ -178,11 +176,6 @@ void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_inter
#endif
// Now we now how big the configuration descriptor will be.
configuration_descriptor_allocation =
allocate_memory(sizeof(configuration_descriptor_template), false /*highaddress*/, true /*movable*/);
uint8_t *configuration_descriptor = (uint8_t *) device_descriptor_allocation->ptr;
// Copy the top-level template, and fix up its length.
memcpy(config_descriptor, configuration_descriptor_template, sizeof(configuration_descriptor_template));
configuration_descriptor[CONFIG_TOTAL_LENGTH_LO_INDEX] = total_descriptor_length & 0xFF;
@ -241,7 +234,7 @@ void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_inter
}
void usb_add_interface_string(uint8_t interface_string_index, const char[] str) {
static 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");
}
@ -259,15 +252,45 @@ void usb_add_interface_string(uint8_t interface_string_index, const char[] str)
}
// Remember USB information that must persist from the boot.py VM to the next VM.
// Some of this is already remembered in globals, for example, usb_midi_enabled and similar bools.
void usb_desc_post_boot_py(void) {
usb_hid_post_boot_py();
}
// Called in a the new VM created after boot.py is run. The USB devices to be used are now chosen.
static 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';
// Memory is cleared to zero when allocated; we depend on that.
collected_interface_strings = m_malloc(MAX_INTERFACE_STRINGS + 1, false);
current_interface_string = 1;
usb_build_device_descriptor();
usb_build_configuration_descriptor();
usb_build_hid_descriptor();
usb_build_string_descriptors();
}
void usb_desc_gc_collect(void) {
// Once tud_mounted() is true, we're done with the constructed descriptors.
if (tud_mounted()) {
// GC will pick up the inaccessible blocks.
free_memory(device_descriptor_allocation);
free_memory(configuration_descriptor_allocation);
gc_free(device_descriptor_allocation);
gc_free(configuration_descriptor);
} else {
gc_collect_ptr(device_descriptor_allocation->ptr);
gc_collect_ptr(configuration_descriptor_allocation->ptr);
gc_collect_ptr(device_descriptor);
gc_collect_ptr(configuration_descriptor);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff