wip: compiles
This commit is contained in:
parent
7a40b4daec
commit
f98a54628b
@ -91,10 +91,6 @@ msgstr ""
|
||||
msgid "%q must be 1-255"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/usb_hid/Device.c
|
||||
msgid "%q must be > 1-255"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/memorymonitor/AllocationAlarm.c
|
||||
msgid "%q must be >= 0"
|
||||
msgstr ""
|
||||
@ -111,10 +107,6 @@ msgstr ""
|
||||
msgid "%q must be None or 1-255"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/usb_hid/Device.c
|
||||
msgid "%q must be None or > 1-255"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/vectorio/Polygon.c
|
||||
msgid "%q must be a tuple of length 2"
|
||||
msgstr ""
|
||||
@ -1643,6 +1635,10 @@ msgstr ""
|
||||
msgid "Not connected"
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/usb/usb_desc.c
|
||||
msgid "Not enough USB endpoints"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
|
||||
#: shared-bindings/audiopwmio/PWMAudioOut.c
|
||||
msgid "Not playing"
|
||||
@ -2149,6 +2145,10 @@ msgstr ""
|
||||
msgid "To exit, please reset the board without "
|
||||
msgstr ""
|
||||
|
||||
#: supervisor/shared/usb/usb_desc.c
|
||||
msgid "Too many USB interface names"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
|
||||
#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c
|
||||
msgid "Too many channels in sample."
|
||||
|
8
main.c
8
main.c
@ -103,6 +103,10 @@
|
||||
#include "shared-module/usb_cdc/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
#include "shared-module/usb_hid/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MIDI
|
||||
#include "shared-module/usb_midi/__init__.h"
|
||||
#endif
|
||||
@ -189,6 +193,10 @@ STATIC void start_mp(supervisor_allocation* heap) {
|
||||
usb_cdc_init();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
usb_hid_init();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MIDI
|
||||
usb_midi_init();
|
||||
#endif
|
||||
|
@ -36,6 +36,13 @@
|
||||
|
||||
#define MICROPY_BYTES_PER_GC_BLOCK (32)
|
||||
|
||||
// CXD56 architecture uses fixed endpoint numbers
|
||||
#define USB_CDC_EP_NUM_NOTIFICATION (3)
|
||||
#define USB_CDC_EP_NUM_DATA_OUT (2)
|
||||
#define USB_CDC_EP_NUM_DATA_IN (2)
|
||||
#define USB_MSC_EP_NUM_OUT (5)
|
||||
#define USB_MSC_EP_NUM_IN (4)
|
||||
|
||||
#define MICROPY_PORT_ROOT_POINTERS \
|
||||
CIRCUITPY_COMMON_ROOT_POINTERS \
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
USB_HIGHSPEED = 1
|
||||
USB_RENUMBER_ENDPOINTS = 0
|
||||
USB_CDC_EP_NUM_NOTIFICATION = 3
|
||||
USB_CDC_EP_NUM_DATA_OUT = 2
|
||||
USB_CDC_EP_NUM_DATA_IN = 1
|
||||
USB_MSC_EP_NUM_OUT = 5
|
||||
USB_MSC_EP_NUM_IN = 4
|
||||
|
||||
# Number of USB endpoint pairs.
|
||||
USB_NUM_EP = 6
|
||||
|
@ -992,4 +992,57 @@ void supervisor_run_background_tasks_if_tick(void);
|
||||
|
||||
#define CIRCUITPY_VERBOSE_BLE 0
|
||||
|
||||
// USB settings
|
||||
|
||||
// If the port requires certain USB endpoint numbers, define these in mpconfigport.h.
|
||||
|
||||
#ifndef USB_CDC_EP_NUM_NOTIFICATION
|
||||
#define USB_CDC_EP_NUM_NOTIFICATION (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_EP_NUM_DATA_OUT
|
||||
#define USB_CDC_EP_NUM_DATA_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_EP_NUM_DATA_IN
|
||||
#define USB_CDC_EP_NUM_DATA_IN (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC2_EP_NUM_NOTIFICATION
|
||||
#define USB_CDC2_EP_NUM_NOTIFICATION (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC2_EP_NUM_DATA_OUT
|
||||
#define USB_CDC2_EP_NUM_DATA_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC2_EP_NUM_DATA_IN
|
||||
#define USB_CDC2_EP_NUM_DATA_IN (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_MSC_EP_NUM_OUT
|
||||
#define USB_MSC_EP_NUM_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_MSC_EP_NUM_IN
|
||||
#define USB_MSC_EP_NUM_IN (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_HID_EP_NUM_OUT
|
||||
#define USB_HID_EP_NUM_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_HID_EP_NUM_IN
|
||||
#define USB_HID_EP_NUM_IN (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_MIDI_EP_NUM_OUT
|
||||
#define USB_MIDI_EP_NUM_OUT (0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_MIDI_EP_NUM_IN
|
||||
#define USB_MIDI_EP_NUM_IN (0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __INCLUDED_MPCONFIG_CIRCUITPY_H
|
||||
|
@ -271,6 +271,9 @@ CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX)
|
||||
CIRCUITPY_ROTARYIO ?= 1
|
||||
CFLAGS += -DCIRCUITPY_ROTARYIO=$(CIRCUITPY_ROTARYIO)
|
||||
|
||||
CIRCUITPY_ROTARYIO_SOFTENCODER ?= 0
|
||||
CFLAGS += -DCIRCUITPY_ROTARYIO_SOFTENCODER=$(CIRCUITPY_ROTARYIO_SOFTENCODER)
|
||||
|
||||
CIRCUITPY_RTC ?= 1
|
||||
CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
|
||||
|
||||
@ -366,6 +369,7 @@ CFLAGS += -DCIRCUITPY_USB_VENDOR=$(CIRCUITPY_USB_VENDOR)
|
||||
ifndef USB_NUM_EP
|
||||
$(error "USB_NUM_EP (number of USB endpoint pairs)must be defined")
|
||||
endif
|
||||
CFLAGS += -DUSB_NUM_EP=$(USB_NUM_EP)
|
||||
|
||||
# For debugging.
|
||||
CIRCUITPY_USTACK ?= 0
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "shared-module/storage/__init__.h"
|
||||
|
||||
void common_hal_storage_mount(mp_obj_t vfs_obj, const char *path, bool readonly);
|
||||
void common_hal_storage_umount_path(const char *path);
|
||||
void common_hal_storage_umount_object(mp_obj_t vfs_obj);
|
||||
|
@ -44,7 +44,7 @@
|
||||
//| """Create a description of a USB HID device. To create an actual device,
|
||||
//| pass a `Device` to `usb_hid.configure_usb()`.
|
||||
//|
|
||||
//| :param ReadableBuffer descriptor: The USB HID Report descriptor bytes. The descriptor is not
|
||||
//| :param ReadableBuffer report_descriptor: The USB HID Report descriptor bytes. The descriptor is not
|
||||
//| not verified for correctness; it is up to you to make sure it is not malformed.
|
||||
//| :param int usage_page: The Usage Page value from the descriptor. Must match what is in the descriptor.
|
||||
//| :param int usage: The Usage value from the descriptor. Must match what is in the descriptor.
|
||||
@ -60,9 +60,9 @@
|
||||
STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
usb_hid_device_obj_t *self = m_new_obj(usb_hid_device_obj_t);
|
||||
self->base.type = &usb_hid_device_type;
|
||||
enum { ARG_descriptor, ARG_usage, ARG_usage_page, ARG_in_report_length, ARG_out_report_length, ARG_report_id_index };
|
||||
enum { ARG_report_descriptor, ARG_usage, ARG_usage_page, ARG_in_report_length, ARG_out_report_length, ARG_report_id_index };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_report_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_usage_page, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_usage, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_in_report_length, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT } ,
|
||||
@ -74,7 +74,7 @@ STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_descriptor].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
mp_get_buffer_raise(args[ARG_report_descriptor].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
mp_obj_t descriptor = mp_obj_new_bytearray(bufinfo.len, bufinfo.buf);
|
||||
|
||||
const mp_int_t usage_page_arg = args[ARG_usage_page].u_int;
|
||||
|
@ -67,17 +67,25 @@ STATIC mp_obj_t usb_hid_configure_usb(mp_obj_t devices) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(usb_hid_configure_usb_obj, usb_hid_configure_usb);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t usb_hid_module_globals_table[] = {
|
||||
// usb_hid.devices is set once the usb devices are determined, after boot.py runs.
|
||||
STATIC mp_map_elem_t usb_hid_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_configure_usb), MP_OBJ_FROM_PTR(&usb_hid_configure_usb_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_devices), MP_ROM_PTR(&common_hal_usb_hid_devices) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&usb_hid_device_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_devices), mp_const_none },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Device), MP_OBJ_FROM_PTR(&usb_hid_device_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(usb_hid_module_globals, usb_hid_module_globals_table);
|
||||
STATIC MP_DEFINE_MUTABLE_DICT(usb_hid_module_globals, usb_hid_module_globals_table);
|
||||
|
||||
const mp_obj_module_t usb_hid_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&usb_hid_module_globals,
|
||||
};
|
||||
|
||||
void usb_hid_set_devices(mp_obj_t devices) {
|
||||
mp_map_elem_t *elem =
|
||||
mp_map_lookup(&usb_hid_module_globals.map, MP_ROM_QSTR(MP_QSTR_devices), MP_MAP_LOOKUP);
|
||||
if (elem) {
|
||||
elem->value = devices;
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,12 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "shared-module/usb_hid/__init__.h"
|
||||
|
||||
extern mp_obj_tuple_t common_hal_usb_hid_devices;
|
||||
|
||||
void usb_hid_set_devices(mp_obj_t devices);
|
||||
|
||||
void common_hal_usb_hid_configure_usb_defaults(void);
|
||||
bool common_hal_usb_hid_configure_usb(mp_obj_t devices_seq);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "shared-module/usb_midi/__init__.h"
|
||||
|
||||
extern mp_obj_dict_t usb_midi_module_globals;
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "supervisor/usb.h"
|
||||
#include "tusb.h"
|
||||
|
||||
static const uint8_t storage_usb_msc_descriptor_template[] = {
|
||||
static const uint8_t usb_msc_descriptor_template[] = {
|
||||
// MSC Interface Descriptor
|
||||
0x09, // 0 bLength
|
||||
0x04, // 1 bDescriptorType (Interface)
|
||||
@ -75,28 +75,32 @@ static const uint8_t storage_usb_msc_descriptor_template[] = {
|
||||
};
|
||||
|
||||
// Is the MSC device enabled?
|
||||
bool storage_usb_enabled;
|
||||
bool storage_usb_is_enabled;
|
||||
|
||||
size_t storage_usb_descriptor_length(void) {
|
||||
return sizeof(usb_msc_descriptor);
|
||||
bool storage_usb_enabled(void) {
|
||||
return storage_usb_is_enabled;
|
||||
}
|
||||
|
||||
static const char[] storage_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " Mass Storage";
|
||||
size_t storage_usb_descriptor_length(void) {
|
||||
return sizeof(usb_msc_descriptor_template);
|
||||
}
|
||||
|
||||
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, usb_msc_descriptor_template, sizeof(usb_msc_descriptor_template));
|
||||
descriptor_buf[MSC_INTERFACE_INDEX] = *current_interface;
|
||||
(*current_interface)++;
|
||||
|
||||
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)++:
|
||||
(*current_endpoint)++;
|
||||
|
||||
usb_add_interface_string(*current_interface_string,);
|
||||
usb_add_interface_string(*current_interface_string, storage_interface_name);
|
||||
descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string;
|
||||
(*current_interface_string)++;
|
||||
|
||||
return sizeof(storage_usb_msc_descriptor_template);
|
||||
return sizeof(usb_msc_descriptor_template);
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +122,7 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_
|
||||
}
|
||||
|
||||
void storage_init(void) {
|
||||
storage_usb_enabled = true;
|
||||
storage_usb_is_enabled = true;
|
||||
}
|
||||
|
||||
void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool readonly) {
|
||||
@ -238,6 +242,6 @@ bool common_hal_storage_configure_usb(bool enabled) {
|
||||
if (tud_connected()) {
|
||||
return false;
|
||||
}
|
||||
storage_usb_enabled = enabled;
|
||||
storage_usb_is_enabled = enabled;
|
||||
return true;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifndef SHARED_MODULE_STORAGE___INIT___H
|
||||
#define SHARED_MODULE_STORAGE___INIT___H
|
||||
|
||||
extern bool storage_usb_enabled;
|
||||
bool storage_usb_enabled(void);
|
||||
|
||||
void storage_init(void);
|
||||
size_t storage_usb_descriptor_length(void);
|
||||
|
@ -37,9 +37,6 @@
|
||||
#error CFG_TUD_CDC must be exactly 2
|
||||
#endif
|
||||
|
||||
bool usb_cdc_repl_enabled;
|
||||
bool usb_cdc_data_enabled;
|
||||
|
||||
static const uint8_t usb_cdc_descriptor_template[] = {
|
||||
// CDC IAD Descriptor
|
||||
0x08, // 0 bLength
|
||||
@ -135,10 +132,10 @@ static const uint8_t usb_cdc_descriptor_template[] = {
|
||||
0x00, // 65 bInterval 0 (unit depends on device speed)
|
||||
};
|
||||
|
||||
static const char[] repl_cdc_comm_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC control";
|
||||
static const char[] data_cdc_comm_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC2 control";
|
||||
static const char[] repl_cdc_data_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC data";
|
||||
static const char[] data_cdc_data_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC2 data";
|
||||
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";
|
||||
|
||||
static usb_cdc_serial_obj_t usb_cdc_repl_obj = {
|
||||
.base.type = &usb_cdc_serial_type,
|
||||
@ -154,6 +151,17 @@ static usb_cdc_serial_obj_t usb_cdc_data_obj = {
|
||||
.idx = 1,
|
||||
};
|
||||
|
||||
static bool usb_cdc_repl_is_enabled;
|
||||
static bool usb_cdc_data_is_enabled;
|
||||
|
||||
bool usb_cdc_repl_enabled(void) {
|
||||
return usb_cdc_repl_is_enabled;
|
||||
}
|
||||
|
||||
bool usb_cdc_data_enabled(void) {
|
||||
return usb_cdc_data_enabled;
|
||||
}
|
||||
|
||||
size_t usb_cdc_descriptor_length(void) {
|
||||
return sizeof(usb_cdc_descriptor_template);
|
||||
}
|
||||
@ -200,8 +208,8 @@ size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfac
|
||||
}
|
||||
|
||||
void usb_cdc_init(void) {
|
||||
usb_cdc_repl_enabled = true;
|
||||
usb_cdc_data_enabled = false;
|
||||
usb_cdc_repl_is_enabled = true;
|
||||
usb_cdc_data_is_enabled = false;
|
||||
}
|
||||
|
||||
bool common_hal_usb_cdc_configure_usb(bool repl_enabled, bool data_enabled) {
|
||||
|
@ -29,8 +29,8 @@
|
||||
|
||||
#include "py/objtuple.h"
|
||||
|
||||
extern bool usb_cdc_repl_enabled;
|
||||
extern bool usb_cdc_data_enabled;
|
||||
bool usb_cdc_repl_enabled(void);
|
||||
bool usb_cdc_data_enabled(void);
|
||||
|
||||
void usb_cdc_init(void);
|
||||
size_t usb_cdc_descriptor_length(void);
|
||||
|
@ -28,12 +28,13 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/usb_hid/Device.h"
|
||||
#include "shared-module/usb_hid/__init__.h"
|
||||
#include "shared-module/usb_hid/Device.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
#include "tusb.h"
|
||||
|
||||
static const uint8_t keyboard_descriptor[] = {
|
||||
static const uint8_t keyboard_report_descriptor[] = {
|
||||
0x05, 0x01, // 0,1 Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x06, // 2,3 Usage (Keyboard)
|
||||
0xA1, 0x01, // 4,5 Collection (Application)
|
||||
@ -69,9 +70,9 @@ static const uint8_t keyboard_descriptor[] = {
|
||||
};
|
||||
|
||||
const usb_hid_device_obj_t usb_hid_device_keyboard_obj = {
|
||||
.descriptor = keyboard_descriptor,
|
||||
.descriptor_length = sizeof(keyboard_descriptor),
|
||||
.usage_page = 0x01
|
||||
.report_descriptor = keyboard_report_descriptor,
|
||||
.report_descriptor_length = sizeof(keyboard_report_descriptor),
|
||||
.usage_page = 0x01,
|
||||
.usage = 0x06,
|
||||
.in_report_length = 8,
|
||||
.out_report_length = 1,
|
||||
@ -79,7 +80,7 @@ const usb_hid_device_obj_t usb_hid_device_keyboard_obj = {
|
||||
|
||||
};
|
||||
|
||||
static const uint8_t mouse_descriptor[] = {
|
||||
static const uint8_t mouse_report_descriptor[] = {
|
||||
0x05, 0x01, // 0,1 Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x02, // 2,3 Usage (Mouse)
|
||||
0xA1, 0x01, // 4,5 Collection (Application)
|
||||
@ -117,17 +118,16 @@ static const uint8_t mouse_descriptor[] = {
|
||||
};
|
||||
|
||||
const usb_hid_device_obj_t usb_hid_device_mouse_obj = {
|
||||
.descriptor = mouse_descriptor,
|
||||
.descriptor_length = sizeof(mouse_descriptor),
|
||||
.usage_page = 0x01
|
||||
.report_descriptor = mouse_report_descriptor,
|
||||
.report_descriptor_length = sizeof(mouse_report_descriptor),
|
||||
.usage_page = 0x01,
|
||||
.usage = 0x02,
|
||||
.in_report_length = 4,
|
||||
.out_report_length = 0,
|
||||
.descriptor = {
|
||||
.report_id_index = MOUSE_REPORT_ID_INDEX,
|
||||
};
|
||||
|
||||
static const uint8_t consumer_control_descriptor[] = {
|
||||
static const uint8_t consumer_control_report_descriptor[] = {
|
||||
0x05, 0x0C, // 0,1 Usage Page (Consumer)
|
||||
0x09, 0x01, // 2,3 Usage (Consumer Control)
|
||||
0xA1, 0x01, // 4,5 Collection (Application)
|
||||
@ -144,9 +144,9 @@ static const uint8_t consumer_control_descriptor[] = {
|
||||
};
|
||||
|
||||
const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = {
|
||||
.descriptor = consumer_control_descriptor,
|
||||
.descriptor_length = sizeof(consumer_control_descriptor),
|
||||
.usage_page = 0x0C
|
||||
.report_descriptor = consumer_control_report_descriptor,
|
||||
.report_descriptor_length = sizeof(consumer_control_report_descriptor),
|
||||
.usage_page = 0x0C,
|
||||
.usage = 0x01,
|
||||
.in_report_length = 2,
|
||||
.out_report_length = 0,
|
||||
@ -154,14 +154,14 @@ const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = {
|
||||
};
|
||||
|
||||
|
||||
void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t descriptor, uint8_t usage_page, uint8_t usage, uint8_t in_report_length, uint8_t out_report_length, uint8_t report_id_index) {
|
||||
void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t report_descriptor, uint8_t usage_page, uint8_t usage, uint8_t in_report_length, uint8_t out_report_length, uint8_t report_id_index) {
|
||||
// report buffer pointers are NULL at start, and are created on demand.
|
||||
self->descriptor_obj = descriptor;
|
||||
self->report_descriptor_obj = report_descriptor;
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(descriptor, &bufinfo, MP_BUFFER_READ);
|
||||
self->descriptor = bufinfo.buf;
|
||||
self->descriptor_length = bufinfo.len;
|
||||
mp_get_buffer_raise(report_descriptor, &bufinfo, MP_BUFFER_READ);
|
||||
self->report_descriptor = bufinfo.buf;
|
||||
self->report_descriptor_length = bufinfo.len;
|
||||
|
||||
self->usage_page = usage_page;
|
||||
self->usage = usage;
|
||||
@ -195,20 +195,11 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t *
|
||||
|
||||
memcpy(self->in_report_buffer, report, len);
|
||||
|
||||
if (!tud_hid_report(self->in_report_id, self->in_report_buffer, len)) {
|
||||
if (!tud_hid_report(self->report_id, self->in_report_buffer, len)) {
|
||||
mp_raise_msg(&mp_type_OSError, translate("USB Error"));
|
||||
}
|
||||
}
|
||||
|
||||
static usb_hid_device_obj_t *get_hid_device(uint8_t report_id) {
|
||||
for (uint8_t i = 0; i < USB_HID_NUM_DEVICES; i++) {
|
||||
if (usb_hid_devices[i].report_id == report_id) {
|
||||
return &usb_hid_devices[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Callbacks invoked when receive Get_Report request through control endpoint
|
||||
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) {
|
||||
(void)itf;
|
||||
@ -218,7 +209,7 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
|
||||
}
|
||||
|
||||
// fill buffer with current report
|
||||
memcpy(buffer, get_hid_device(report_id)->in_report_buffer, reqlen);
|
||||
memcpy(buffer, usb_hid_get_device_with_report_id(report_id)->in_report_buffer, reqlen);
|
||||
return reqlen;
|
||||
}
|
||||
|
||||
@ -233,7 +224,7 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
|
||||
return;
|
||||
}
|
||||
|
||||
usb_hid_device_obj_t *hid_device = get_hid_device(report_id);
|
||||
usb_hid_device_obj_t *hid_device = usb_hid_get_device_with_report_id(report_id);
|
||||
|
||||
if (hid_device && hid_device->out_report_length >= bufsize) {
|
||||
memcpy(hid_device->out_report_buffer, buffer, bufsize);
|
||||
|
@ -35,13 +35,13 @@
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
// If not MP_OBJ_NULL, points to Python array object whose contents are the descriptor.
|
||||
mp_obj_t descriptor_obj;
|
||||
mp_obj_t report_descriptor_obj;
|
||||
// If not NULL, points to raw bytes that are the descriptor.
|
||||
uint8_t *descriptor;
|
||||
const uint8_t *report_descriptor;
|
||||
uint8_t *in_report_buffer;
|
||||
uint8_t *out_report_buffer;
|
||||
uint16_t report_id_index;
|
||||
uint16_t descriptor_length;
|
||||
uint16_t report_descriptor_length;
|
||||
uint8_t usage_page;
|
||||
uint8_t usage;
|
||||
uint8_t report_id;
|
||||
@ -49,8 +49,8 @@ typedef struct {
|
||||
uint8_t out_report_length;
|
||||
} usb_hid_device_obj_t;
|
||||
|
||||
extern usb_hid_device_obj_t usb_hid_device_keyboard_obj;
|
||||
extern usb_hid_device_obj_t usb_hid_device_mouse_obj;
|
||||
extern usb_hid_device_obj_t usb_hid_device_consumer_control_obj;
|
||||
extern const usb_hid_device_obj_t usb_hid_device_keyboard_obj;
|
||||
extern const usb_hid_device_obj_t usb_hid_device_mouse_obj;
|
||||
extern const usb_hid_device_obj_t usb_hid_device_consumer_control_obj;
|
||||
|
||||
#endif /* SHARED_MODULE_USB_HID_DEVICE_H */
|
||||
|
@ -26,70 +26,106 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "shared-module/usb_hid/__init__.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "shared-bindings/usb_hid/__init__.h"
|
||||
#include "shared-module/usb_hid/Device.h"
|
||||
#include "supervisor/memory.h"
|
||||
#include "supervisor/usb.h"
|
||||
|
||||
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)
|
||||
0x04, // 1 bDescriptorType (Interface)
|
||||
0xFF, // 2 bInterfaceNumber 3
|
||||
#define HID_DESCRIPTOR_INTERFACE_INDEX (2)
|
||||
0x00, // 3 bAlternateSetting
|
||||
0x02, // 4 bNumEndpoints 2
|
||||
0x03, // 5 bInterfaceClass: HID
|
||||
0x00, // 6 bInterfaceSubClass: NOBOOT
|
||||
0x00, // 7 bInterfaceProtocol: NONE
|
||||
0xFF, // 8 iInterface (String Index) [SET AT RUNTIME]
|
||||
#define HID_DESCRIPTOR_INTERFACE_STRING_INDEX (8)
|
||||
|
||||
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)
|
||||
0x09, // 9 bLength
|
||||
0x21, // 10 bDescriptorType (HID)
|
||||
0x11, 0x01, // 11,12 bcdHID 1.11
|
||||
0x00, // 13 bCountryCode
|
||||
0x01, // 14 bNumDescriptors
|
||||
0x22, // 15 bDescriptorType[0] (HID)
|
||||
0xFF, 0xFF, // 16,17 wDescriptorLength[0] [SET AT RUNTIME: lo, hi]
|
||||
#define HID_DESCRIPTOR_LENGTH_INDEX (16)
|
||||
|
||||
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)
|
||||
0x07, // 18 bLength
|
||||
0x05, // 19 bDescriptorType (Endpoint)
|
||||
0xFF, // 20 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | endpoint]
|
||||
#define HID_IN_ENDPOINT_INDEX (20)
|
||||
0x03, // 21 bmAttributes (Interrupt)
|
||||
0x40, 0x00, // 22,23 wMaxPacketSize 64
|
||||
0x08, // 24 bInterval 8 (unit depends on device speed)
|
||||
|
||||
0x07, // 25 bLength
|
||||
0x05, // 26 bDescriptorType (Endpoint)
|
||||
0xFF, // 27 bEndpointAddress (OUT/H2D) [SET AT RUNTIME]
|
||||
#define HID_OUT_ENDPOINT_INDEX (26)
|
||||
0x03, // 28 bmAttributes (Interrupt)
|
||||
0x40, 0x00, // 29,30 wMaxPacketSize 64
|
||||
0x08, // 31 bInterval 8 (unit depends on device speed)
|
||||
};
|
||||
|
||||
// Sequence of devices to configure.
|
||||
// Sequence of devices to configure. Passed to usb_hid.configure_usb().
|
||||
// Not used after boot.py finishes and VM restarts.
|
||||
static mp_obj_t hid_devices_seq;
|
||||
|
||||
// Is the HID device enabled?
|
||||
bool usb_hid_enabled;
|
||||
supervisor_allocation *hid_report_descriptor_allocation;
|
||||
supervisor_allocation *hid_devices_allocation;
|
||||
static bool usb_hid_is_enabled;
|
||||
|
||||
static supervisor_allocation *hid_report_descriptor_allocation;
|
||||
static size_t total_hid_report_descriptor_length;
|
||||
static supervisor_allocation *hid_devices_allocation;
|
||||
static mp_int_t hid_devices_num;
|
||||
|
||||
// This is the interface descriptor, not the report descriptor.
|
||||
size_t usb_hid_descriptor_length(void) {
|
||||
return sizeof(usb_hid_descriptor_template);
|
||||
}
|
||||
|
||||
static const char usb_hid_interface_name[] = MP_STRINGIFY(USB_INTERFACE_NAME) " HID";
|
||||
// Total length of the report descriptor, with all configured devices.
|
||||
size_t usb_hid_report_descriptor_length(void) {
|
||||
return total_hid_report_descriptor_length;
|
||||
}
|
||||
|
||||
bool usb_hid_enabled(void) {
|
||||
return usb_hid_is_enabled;
|
||||
}
|
||||
|
||||
static const char usb_hid_interface_name[] = USB_INTERFACE_NAME " HID";
|
||||
|
||||
// This is the interface descriptor, not the report descriptor.
|
||||
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_INTERFACE_INDEX] = *current_interface;
|
||||
(*current_interface)++;
|
||||
|
||||
usb_add_interface_string(*current_interface, usb_hid_interface_name);
|
||||
descriptor_buf[HID_DESCRIPTOR_INTERFACE_STRING_INDEX] = *current_interface_string;
|
||||
(*current_interface_string)++;
|
||||
|
||||
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)++:
|
||||
(*current_endpoint)++;
|
||||
|
||||
return sizeof(usb_hid_descriptor_template);
|
||||
}
|
||||
|
||||
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),
|
||||
MP_OBJ_FROM_PTR(usb_hid_device_consumer_control_obj),
|
||||
MP_OBJ_FROM_PTR(&usb_hid_device_keyboard_obj),
|
||||
MP_OBJ_FROM_PTR(&usb_hid_device_mouse_obj),
|
||||
MP_OBJ_FROM_PTR(&usb_hid_device_consumer_control_obj),
|
||||
};
|
||||
|
||||
// Set the default list of devices that will be included. Called before boot.py runs, in the boot.py VM.
|
||||
@ -97,78 +133,79 @@ 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) {
|
||||
bool common_hal_usb_hid_configure_usb(mp_obj_t devices) {
|
||||
// We can't change the devices once we're connected.
|
||||
if (tud_connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember the devices for use in usb_hid_post_boot_py.
|
||||
hid_devices_seq = devices_seq;
|
||||
hid_devices_seq = devices;
|
||||
return true;
|
||||
}
|
||||
|
||||
void usb_hid_init(void) {
|
||||
usb_hid_is_enabled = 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(hid_devices_seq));
|
||||
hid_devices_num = mp_obj_get_int(mp_obj_len(hid_devices_seq));
|
||||
|
||||
// First get the total size.
|
||||
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)) {
|
||||
return USB_CONFIG_NON_DEVICE; for (size_t i = 0; i < len; i++) {
|
||||
mp_obj_t item = (devices, mp_obj_new_small_int(i), MP_OBJ_SENTINEL);
|
||||
if (!MP_OBJ_IS_TYPE(item, &usb_hid_device_type)) {
|
||||
return USB_CONFIG_NON_DEVICE;
|
||||
}
|
||||
total_report_descriptors_length += device->report_descriptor_length;
|
||||
total_hid_report_descriptor_length = 0;
|
||||
for (mp_int_t i = 0; i < hid_devices_num; i++) {
|
||||
// hid_devices_seq has already been validated to contain only usb_hid_device_obj_t objects.
|
||||
usb_hid_device_obj_t *device =
|
||||
MP_OBJ_TO_PTR(mp_obj_subscr(hid_devices_seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
total_hid_report_descriptor_length += device->report_descriptor_length;
|
||||
}
|
||||
|
||||
}
|
||||
total_report_descriptors_length += device->report_descriptor_length;
|
||||
}
|
||||
if (len == 1) {
|
||||
// Don't need space for a report id if there's only one device.
|
||||
total_report_descriptors_length -= 2;
|
||||
// Don't need space for a report id if there's only one device.
|
||||
if (hid_devices_num == 1) {
|
||||
total_hid_report_descriptor_length -= 2;
|
||||
}
|
||||
|
||||
// Allocate storage that persists across VMs to build the combined descriptor
|
||||
// and to remember the device details.
|
||||
|
||||
hid_report_descriptor_allocation =
|
||||
allocate_memory(total_report_descriptors_length, false /*highaddress*/, true /*movable*/);
|
||||
allocate_memory(align32_size(total_hid_report_descriptor_length),
|
||||
false /*highaddress*/, true /*movable*/);
|
||||
|
||||
hid_devices_allocation = allocate_memory(sizeof(usb_hid_device_obj_t) * len);
|
||||
usb_hid_device_obj_t hid_devices[] = (usb_hid_device_obj_t[]) hid_devices_allocation->ptr;
|
||||
hid_devices_allocation =
|
||||
allocate_memory(align32_size(sizeof(usb_hid_device_obj_t) * hid_devices_num),
|
||||
false /*highaddress*/, true /*movable*/);
|
||||
usb_hid_device_obj_t *hid_devices = (usb_hid_device_obj_t *) hid_devices_allocation->ptr;
|
||||
|
||||
uint8_t *descriptor_start = (uint8_t *) hid_report_descriptor_allocation->ptr;
|
||||
uint8_t *report_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(hid_devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL);
|
||||
for (mp_int_t i = 0; i < hid_devices_num; i++) {
|
||||
usb_hid_device_obj_t *device =
|
||||
MP_OBJ_TO_PTR(mp_obj_subscr(hid_devices_seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
|
||||
// Copy the report descriptor for this device.
|
||||
if (len == 1) {
|
||||
if (hid_devices_num == 1) {
|
||||
// Theres only one device, so it shouldn't have a report ID.
|
||||
// Copy the descriptor, but splice out the report id indicator and value (2 bytes).
|
||||
memcpy(descriptor_start, device->descriptor, device->report_id_index - 1);
|
||||
descriptor_start += device->report_id_index - 1;
|
||||
memcpy(descriptor_start, device->descriptor + device->report_id_index + 1,
|
||||
memcpy(report_descriptor_start, device->report_descriptor, device->report_id_index - 1);
|
||||
report_descriptor_start += device->report_id_index - 1;
|
||||
memcpy(report_descriptor_start, device->report_descriptor + device->report_id_index + 1,
|
||||
device->report_descriptor_length - device->report_id_index - 1);
|
||||
} else {
|
||||
// Copy the whole descriptor and fill in the report id.
|
||||
memcpy(descriptor_start, device->descriptor, device->descriptor_len);
|
||||
descriptor_start[device->report_id_index] = i + 1;
|
||||
descriptor_start += device->descriptor_len;
|
||||
memcpy(report_descriptor_start, device->report_descriptor, device->report_descriptor_length);
|
||||
report_descriptor_start[device->report_id_index] = i + 1;
|
||||
report_descriptor_start += device->report_descriptor_length;
|
||||
}
|
||||
|
||||
// Copy the device data and discard any descriptor-bytes object pointer.
|
||||
memcpy(&hid_devices[i], device, sizeof(usb_hid_device_obj_t));
|
||||
hid_devices[i].descriptor_obj = mp_const_none;
|
||||
hid_devices[i].report_descriptor_obj = mp_const_none;
|
||||
}
|
||||
|
||||
// No longer keeping the Python object of devices to configure.
|
||||
@ -176,13 +213,31 @@ void usb_hid_post_boot_py(void) {
|
||||
}
|
||||
|
||||
void usb_hid_gc_collect(void) {
|
||||
// Once tud_mounted() is true, we're done with the constructed descriptors.
|
||||
if (tud_mounted()) {
|
||||
// Once tud_mounted() is true, we're done with the constructed descriptors.
|
||||
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_ptr);
|
||||
}
|
||||
|
||||
gc_collect_ptr(hid_devices_seq);
|
||||
gc_collect_ptr(hid_report_descriptor_allocation->ptr);
|
||||
gc_collect_ptr(hid_devices_allocation->ptr);
|
||||
}
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
// Invoked when GET HID REPORT DESCRIPTOR is received.
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) {
|
||||
return (uint8_t *) hid_report_descriptor_allocation->ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_hid_device_obj_t *usb_hid_get_device_with_report_id(uint8_t report_id) {
|
||||
for (uint8_t i = 0; i < hid_devices_num; i++) {
|
||||
usb_hid_device_obj_t *hid_devices = (usb_hid_device_obj_t *) hid_devices_allocation->ptr;
|
||||
if (hid_devices[i].report_id == report_id) {
|
||||
return &hid_devices[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -29,10 +29,19 @@
|
||||
|
||||
#include "shared-module/usb_hid/Device.h"
|
||||
|
||||
extern bool usb_hid_enabled;
|
||||
extern usb_hid_device_obj_t usb_hid_devices[];
|
||||
|
||||
bool usb_hid_enabled(void);
|
||||
|
||||
void usb_hid_init(void);
|
||||
void usb_hid_post_boot_py(void);
|
||||
|
||||
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);
|
||||
size_t usb_hid_descriptor_length(void);
|
||||
size_t usb_hid_report_descriptor_length(void);
|
||||
|
||||
usb_hid_device_obj_t *usb_hid_get_device_with_report_id(uint8_t report_id);
|
||||
|
||||
void usb_hid_gc_collect(void);
|
||||
|
||||
|
||||
#endif // SHARED_MODULE_USB_HID___INIT___H
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "shared-bindings/usb_midi/PortIn.h"
|
||||
#include "shared-bindings/usb_midi/PortOut.h"
|
||||
#include "supervisor/memory.h"
|
||||
#include "supervisor/usb.h"
|
||||
#include "tusb.h"
|
||||
|
||||
supervisor_allocation *usb_midi_allocation;
|
||||
@ -79,7 +80,7 @@ static const uint8_t usb_midi_descriptor_template[] = {
|
||||
0x24, // 28 bDescriptorType: CLASS SPECIFIC INTERFACE
|
||||
0x01, // 29 bDescriptorSubtype: MIDI STREAMING HEADER
|
||||
0x00, 0x01, // 30,31 bsdMSC (MIDI STREAMING) version 1.0
|
||||
0x25, 0x00 // 32,33 wLength
|
||||
0x25, 0x00, // 32,33 wLength
|
||||
|
||||
// MIDI Embedded In Jack Descriptor
|
||||
0x06, // 34 bLength
|
||||
@ -155,17 +156,21 @@ static const uint8_t usb_midi_descriptor_template[] = {
|
||||
};
|
||||
|
||||
// Is the USB MIDI device enabled?
|
||||
bool usb_midi_enabled;
|
||||
static bool usb_midi_is_enabled;
|
||||
|
||||
bool usb_midi_enabled(void) {
|
||||
return usb_midi_is_enabled;
|
||||
}
|
||||
|
||||
|
||||
size_t usb_midi_descriptor_length(void) {
|
||||
return sizeof(usb_midi_descriptor_template);
|
||||
}
|
||||
|
||||
static const char[] midi_streaming_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " MIDI";
|
||||
static const char[] midi_audio_control_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " Audio";
|
||||
static const char[] midi_in_jack_name = MP_STRINGIFY(USB_INTERFACE_NAME) " usb_midi.ports[0]";
|
||||
static const char[] midi_out_jack_name = MP_STRINGIFY(USB_INTERFACE_NAME) " usb_midi.ports[0]";
|
||||
static const char midi_streaming_interface_name[] = USB_INTERFACE_NAME " MIDI";
|
||||
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));
|
||||
@ -173,8 +178,9 @@ size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfa
|
||||
descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = *current_interface;
|
||||
(*current_interface)++;
|
||||
|
||||
descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint;
|
||||
descriptor_buf[MSC_OUT_ENDPOINT_INDEX] =
|
||||
descriptor_buf[MIDI_STREAMING_IN_ENDPOINT_INDEX] =
|
||||
USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint;
|
||||
descriptor_buf[MIDI_STREAMING_OUT_ENDPOINT_INDEX] =
|
||||
0x80 | (USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : *current_endpoint);
|
||||
(*current_endpoint)++;
|
||||
|
||||
@ -203,13 +209,13 @@ size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfa
|
||||
|
||||
|
||||
void usb_midi_init(void) {
|
||||
usb_midi_enabled = true;
|
||||
usb_midi_is_enabled = true;
|
||||
}
|
||||
|
||||
void usb_midi_usb_init(void) {
|
||||
mp_obj_tuple_t *ports;
|
||||
|
||||
if (usb_midi_enabled) {
|
||||
if (usb_midi_is_enabled) {
|
||||
// TODO(tannewt): Make this dynamic.
|
||||
size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t *) * 2);
|
||||
size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t));
|
||||
@ -241,6 +247,6 @@ bool common_hal_usb_midi_configure_usb(bool enabled) {
|
||||
if (tud_connected()) {
|
||||
return false;
|
||||
}
|
||||
usb_midi_enabled = enabled;
|
||||
usb_midi_is_enabled = enabled;
|
||||
return true;
|
||||
}
|
||||
|
@ -27,11 +27,11 @@
|
||||
#ifndef SHARED_MODULE_USB_MIDI___INIT___H
|
||||
#define SHARED_MODULE_USB_MIDI___INIT___H
|
||||
|
||||
extern bool usb_midi_enabled;
|
||||
|
||||
void usb_midi_init(void);
|
||||
void usb_midi_usb_init(void);
|
||||
|
||||
bool usb_midi_enabled(void);
|
||||
size_t usb_midi_descriptor_length(void);
|
||||
size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string);
|
||||
|
||||
|
@ -26,6 +26,9 @@
|
||||
|
||||
#include "lib/tinyusb/src/tusb.h"
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/usb.h"
|
||||
|
||||
#if CIRCUITPY_USB_CDC
|
||||
@ -44,20 +47,17 @@
|
||||
#include "shared-bindings/storage/__init__.h"
|
||||
#endif
|
||||
|
||||
// For COMMON_HAL_MCU_PROCESSOR_UID_LENGTH
|
||||
#include "common-hal/microcontroller/Processor.h"
|
||||
#include "shared-bindings/microcontroller/Processor.h"
|
||||
|
||||
uint8_t *device_descriptor;
|
||||
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 uint16_t **collected_interface_strings;
|
||||
static uint8_t current_interface_string;
|
||||
|
||||
static const char manufacturer_name[] = MP_STRINGIFY(USB_MANUFACTURER);
|
||||
static const char product_name[] = MP_STRINGIFY(USB_PRODUCT);
|
||||
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];
|
||||
@ -86,6 +86,8 @@ static const uint8_t device_descriptor_template[] = {
|
||||
0x01, // 17 bNumConfigurations 1
|
||||
};
|
||||
|
||||
static uint8_t device_descriptor[sizeof(device_descriptor_template)];
|
||||
|
||||
static const uint8_t configuration_descriptor_template[] = {
|
||||
0x09, // 0 bLength
|
||||
0x02, // 1 bDescriptorType (Configuration)
|
||||
@ -100,6 +102,8 @@ static const uint8_t configuration_descriptor_template[] = {
|
||||
0x32, // 8 bMaxPower 100mA
|
||||
};
|
||||
|
||||
static uint8_t configuration_descriptor[sizeof(configuration_descriptor_template)];
|
||||
|
||||
// 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.
|
||||
@ -132,55 +136,53 @@ static void usb_build_device_descriptor(uint16_t vid, uint16_t pid) {
|
||||
device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF;
|
||||
device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8;
|
||||
|
||||
usb_add_interface_string(*current_interface_string, manufacturer_name);
|
||||
device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = *current_interface_string;
|
||||
(*current_interface_string)++;
|
||||
usb_add_interface_string(current_interface_string, manufacturer_name);
|
||||
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, 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)++;
|
||||
usb_add_interface_string(current_interface_string, serial_number_hex_string);
|
||||
device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = current_interface_string;
|
||||
current_interface_string++;
|
||||
}
|
||||
|
||||
static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) {
|
||||
static void usb_build_configuration_descriptor(void) {
|
||||
size_t total_descriptor_length = sizeof(configuration_descriptor_template);
|
||||
|
||||
// CDC should be first, for compatibility with Adafruit Windows 7 drivers.
|
||||
// In the past, the order has been CDC, MSC, MIDI, HID, so preserve
|
||||
// that order.
|
||||
// In the past, the order has been CDC, MSC, MIDI, HID, so preserve that order.
|
||||
#if CIRCUITPY_USB_CDC
|
||||
if (usb_cdc_repl_enabled) {
|
||||
if (usb_cdc_repl_enabled()) {
|
||||
total_descriptor_length += usb_cdc_descriptor_length();
|
||||
}
|
||||
if (usb_cdc_data_enabled) {
|
||||
if (usb_cdc_data_enabled()) {
|
||||
total_descriptor_length += usb_cdc_descriptor_length();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MSC
|
||||
if (storage_usb_enabled) {
|
||||
if (storage_usb_enabled()) {
|
||||
total_descriptor_length += storage_usb_descriptor_length();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MIDI
|
||||
if (usb_midi_enabled) {
|
||||
if (usb_midi_enabled()) {
|
||||
total_descriptor_length += usb_midi_descriptor_length();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
if (usb_hid_enabled) {
|
||||
if (usb_hid_enabled()) {
|
||||
total_descriptor_length += usb_hid_descriptor_length();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now we now how big the configuration descriptor will be.
|
||||
// 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;
|
||||
configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF;
|
||||
|
||||
@ -192,38 +194,39 @@ static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t nu
|
||||
uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template);
|
||||
|
||||
#if CIRCUITPY_USB_CDC
|
||||
if (usb_cdc_repl_enabled) {
|
||||
if (usb_cdc_repl_enabled()) {
|
||||
// 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);
|
||||
descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, true);
|
||||
}
|
||||
if (usb_cdc_data_enabled) {
|
||||
if (usb_cdc_data_enabled()) {
|
||||
// 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);
|
||||
descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MSC
|
||||
if (storage_usb_enabled) {
|
||||
if (storage_usb_enabled()) {
|
||||
// Concatenate and fix up the MSC descriptor.
|
||||
descriptor_buf_remaining += storage_usb_add_descriptor(
|
||||
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
|
||||
descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_MIDI
|
||||
if (usb_midi_enabled) {
|
||||
if (usb_midi_enabled()) {
|
||||
// Concatenate and fix up the MIDI descriptor.
|
||||
descriptor_buf_remaining += usb_midi_add_descriptor(
|
||||
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
|
||||
descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
if (usb_hid_enabled) {
|
||||
if (usb_hid_enabled()) {
|
||||
descriptor_buf_remaining += usb_hid_add_descriptor(
|
||||
descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string);
|
||||
descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string,
|
||||
usb_hid_report_descriptor_length());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -232,14 +235,14 @@ static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t nu
|
||||
|
||||
// Did we run out of endpoints?
|
||||
if (current_endpoint - 1 > USB_NUM_EP) {
|
||||
mp_raise_SystemError("Not enough USB endpoints");
|
||||
mp_raise_RuntimeError(translate("Not enough USB endpoints"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void usb_add_interface_string(uint8_t interface_string_index, const char[] str) {
|
||||
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");
|
||||
mp_raise_RuntimeError(translate("Too many USB interface names"));
|
||||
}
|
||||
// 2 bytes for String Descriptor header, then 2 bytes for each character
|
||||
const size_t str_len = strlen(str);
|
||||
@ -247,7 +250,7 @@ void usb_add_interface_string(uint8_t interface_string_index, const char[] str)
|
||||
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++) {
|
||||
for (size_t i = 0; i <= str_len; i++) {
|
||||
string_descriptor[i + 1] = str[i];
|
||||
}
|
||||
|
||||
@ -261,8 +264,8 @@ 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) {
|
||||
// Called in the new VM created after boot.py is run. The USB devices to be used are now chosen.
|
||||
void usb_desc_init(void) {
|
||||
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
|
||||
common_hal_mcu_processor_get_uid(raw_id);
|
||||
|
||||
@ -282,14 +285,12 @@ static void usb_desc_init(void) {
|
||||
|
||||
usb_build_device_descriptor(USB_VID, USB_PID);
|
||||
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_free(device_descriptor_allocation);
|
||||
gc_free(device_descriptor);
|
||||
gc_free(configuration_descriptor);
|
||||
} else {
|
||||
gc_collect_ptr(device_descriptor);
|
||||
@ -301,7 +302,7 @@ void usb_desc_gc_collect(void) {
|
||||
// Invoked when GET DEVICE DESCRIPTOR is received.
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const *tud_descriptor_device_cb(void) {
|
||||
return usb_descriptor_dev;
|
||||
return device_descriptor;
|
||||
}
|
||||
|
||||
// Invoked when GET CONFIGURATION DESCRIPTOR is received.
|
||||
@ -309,18 +310,9 @@ uint8_t const *tud_descriptor_device_cb(void) {
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
|
||||
(void)index; // for multiple configurations
|
||||
return config_desc;
|
||||
return configuration_descriptor;
|
||||
}
|
||||
|
||||
#if CIRCUITPY_USB_HID
|
||||
// Invoked when GET HID REPORT DESCRIPTOR is received.
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) {
|
||||
return hid_report_descriptor;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Invoked when GET STRING DESCRIPTOR request is received.
|
||||
// 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) {
|
||||
|
@ -134,14 +134,16 @@ ifeq ($(CIRCUITPY_DISPLAYIO), 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Preserve double quotes in these values by single-quoting them.
|
||||
|
||||
USB_INTERFACE_NAME ?= "CircuitPython"
|
||||
CFLAGS += -DUSB_INTERFACE_NAME=$(USB_INTERFACE_NAME)
|
||||
CFLAGS += -DUSB_INTERFACE_NAME='$(USB_INTERFACE_NAME)'
|
||||
|
||||
ifneq ($(USB_VID),)
|
||||
CFLAGS += -DUSB_VID=$(USB_VID)
|
||||
CFLAGS += -DSUB_PID=$(USB_PID)
|
||||
CFLAGS += -DUSB_MANUFACTURER=$(USB_MANUFACTURER)
|
||||
CFLAGS += -DUSB_PRODUCT=$(USB_PRODUCT)
|
||||
CFLAGS += -DUSB_PID=$(USB_PID)
|
||||
CFLAGS += -DUSB_MANUFACTURER='$(USB_MANUFACTURER)'
|
||||
CFLAGS += -DUSB_PRODUCT='$(USB_PRODUCT)'
|
||||
endif
|
||||
|
||||
# In the following URL, don't include the https:// prefix.
|
||||
@ -149,39 +151,12 @@ endif
|
||||
USB_WEBUSB_URL ?= "circuitpython.org"
|
||||
|
||||
ifeq ($(CIRCUITPY_USB_CDC),1)
|
||||
# Inform TinyUSB there are two CDC devices.
|
||||
# Inform TinyUSB there will be up to two CDC devices.
|
||||
CFLAGS += -DCFG_TUD_CDC=2
|
||||
endif
|
||||
|
||||
USB_HIGHSPEED ?= 0
|
||||
|
||||
************ move these from make variables to cpp only ???
|
||||
USB_CDC_EP_NUM_NOTIFICATION ?= 0
|
||||
CFLAGS += -DUSB_CDC_EP_NUM_NOTIFICATION=$(USB_CDC_EP_NUM_NOTIFICATION)
|
||||
USB_CDC_EP_NUM_DATA_OUT ?= 0
|
||||
CFLAGS += -DUSB_CDC_EP_NUM_DATA_OUT=$(USB_CDC_EP_NUM_DATA_OUT)
|
||||
USB_CDC_EP_NUM_DATA_IN ?= 0
|
||||
CFLAGS += -DUSB_CDC_EP_NUM_DATA_IN=$(USB_CDC_EP_NUM_DATA_IN)
|
||||
|
||||
USB_CDC2_EP_NUM_NOTIFICATION ?= 0
|
||||
CFLAGS += -DUSB_CDC2_EP_NUM_NOTIFICATION=$(USB_CDC2_EP_NUM_NOTIFICATION)
|
||||
USB_CDC2_EP_NUM_DATA_OUT ?= 0
|
||||
CFLAGS += -DUSB_CDC2_EP_NUM_DATA_OUT=$(USB_CDC2_EP_NUM_DATA_OUT)
|
||||
USB_CDC2_EP_NUM_DATA_IN ?= 0
|
||||
CFLAGS += -DUSB_CDC2_EP_NUM_DATA_IN=$(USB_CDC2_EP_NUM_DATA_IN)
|
||||
|
||||
USB_MSC_EP_NUM_OUT ?= 0
|
||||
CFLAGS += -DUSB
|
||||
USB_MSC_EP_NUM_IN ?= 0
|
||||
|
||||
USB_HID_EP_NUM_OUT ?= 0
|
||||
USB_HID_EP_NUM_IN ?= 0
|
||||
|
||||
USB_MIDI_EP_NUM_OUT ?= 0
|
||||
USB_MIDI_EP_NUM_IN ?= 0
|
||||
|
||||
USB_NUM_EP ?= 0
|
||||
|
||||
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
|
||||
|
||||
CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf"
|
||||
|
Loading…
Reference in New Issue
Block a user