WIP: works with just keyboard but not complex report descriptor

This commit is contained in:
Dan Halbert 2018-03-30 23:20:24 -04:00
parent 31f5b6a238
commit df91878d2e
11 changed files with 220 additions and 179 deletions

View File

@ -96,8 +96,8 @@ endif
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
# Turn on Python modules useful for debugging (e.g. uheap, ustack). # Turn on Python modules useful for debugging (e.g. uheap, ustack).
CFLAGS += -ggdb CFLAGS += -ggdb
CFLAGS += -flto ## CFLAGS += -flto
CFLAGS += -fno-inline CFLAGS += -fno-inline -fno-ipa-sra
ifeq ($(CHIP_FAMILY), samd21) ifeq ($(CHIP_FAMILY), samd21)
CFLAGS += -DENABLE_MICRO_TRACE_BUFFER CFLAGS += -DENABLE_MICRO_TRACE_BUFFER
endif endif
@ -193,8 +193,7 @@ SRC_ASF := \
hpl/systick/hpl_systick.c \ hpl/systick/hpl_systick.c \
hpl/usb/hpl_usb.c \ hpl/usb/hpl_usb.c \
usb/class/cdc/device/cdcdf_acm.c \ usb/class/cdc/device/cdcdf_acm.c \
usb/class/hid/device/hiddf_keyboard.c \ usb/class/hid/device/hiddf_generic.c \
usb/class/hid/device/hiddf_mouse.c \
usb/class/msc/device/mscdf.c \ usb/class/msc/device/mscdf.c \
usb/device/usbdc.c \ usb/device/usbdc.c \
usb/usb_protocol.c \ usb/usb_protocol.c \
@ -381,14 +380,19 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(ECHO) "Create $@" $(ECHO) "Create $@"
python2 $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^ python2 $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^
$(BUILD)/autogen_usb_descriptor.c: tools/gen_usb_descriptor.py Makefile $(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
install -d $(BUILD) install -d $(BUILD)
python3 tools/gen_usb_descriptor.py \ python3 tools/gen_usb_descriptor.py \
--manufacturer $(USB_MANUFACTURER)\ --manufacturer $(USB_MANUFACTURER)\
--product $(USB_PRODUCT)\ --product $(USB_PRODUCT)\
--vid $(USB_VID)\ --vid $(USB_VID)\
--pid $(USB_PID)\ --pid $(USB_PID)\
$@ --output_c_file $(BUILD)/autogen_usb_descriptor.c\
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
deploy: $(BUILD)/firmware.bin deploy: $(BUILD)/firmware.bin
$(ECHO) "Writing $< to the board" $(ECHO) "Writing $< to the board"

View File

@ -31,12 +31,11 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/usb_hid/Device.h" #include "shared-bindings/usb_hid/Device.h"
#include "tools/autogen_usb_descriptor.h" #include "genhdr/autogen_usb_descriptor.h"
#include "tick.h" #include "tick.h"
#include "usb/class/hid/device/hiddf_mouse.h" #include "usb/class/hid/device/hiddf_generic.h"
#include "usb/class/hid/device/hiddf_keyboard.h"
static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
@ -60,22 +59,16 @@ static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report,
// Copy the data only when endpoint is ready to send. The previous // Copy the data only when endpoint is ready to send. The previous
// buffer load gets zero'd out when transaction completes, so if // buffer load gets zero'd out when transaction completes, so if
// you copy before it's ready, only zeros will get sent. // you copy before it's ready, only zeros will get sent.
memcpy(self->report_buffer, report, len);
switch (self->kind) { // Prefix with a report id if one is supplied
case USB_HID_MOUSE: if (self->report_id > 0) {
status = hiddf_mouse_write(self->report_buffer, self->report_length); self->report_buffer[0] = self->report_id;
break; memcpy(&(self->report_buffer[1]), report, len);
} else {
case USB_HID_KEYBOARD: memcpy(self->report_buffer, report, len);
status = hiddf_keyboard_write(self->report_buffer, self->report_length);
break;
default:
mp_raise_ValueError("Unknown HID device");
} }
return status; return hiddf_generic_write(self->report_buffer, self->report_length);
} }
void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) {
@ -98,18 +91,14 @@ uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) {
void usb_hid_init() { void usb_hid_init() {
usb_hid_devices[USB_HID_DEVICE_MOUSE].base.type = &usb_hid_device_type;
usb_hid_devices[USB_HID_DEVICE_MOUSE].endpoint = hid_mouse_endpoint_in;
usb_hid_devices[USB_HID_DEVICE_KEYBOARD].base.type = &usb_hid_device_type;
usb_hid_devices[USB_HID_DEVICE_KEYBOARD].endpoint = hid_keyboard_endpoint_in;
} }
void usb_hid_reset() { void usb_hid_reset() {
// We don't actually reset. We just set a report that is empty to prevent // We don't actually reset. We just set a report that is empty to prevent
// long keypresses and such. // long keypresses and such.
uint8_t report[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t report[USB_HID_MAX_REPORT_LENGTH] = {0};
usb_hid_send_report(&usb_hid_devices[USB_HID_DEVICE_MOUSE], report, UDI_HID_MOUSE_REPORT_SIZE); for (size_t i = 0; i < USB_HID_NUM_DEVICES; i++) {
usb_hid_send_report(&usb_hid_devices[USB_HID_DEVICE_KEYBOARD], report, UDI_HID_KBD_REPORT_SIZE); usb_hid_send_report(&usb_hid_devices[i], report, usb_hid_devices[i].report_length);
}
} }

View File

@ -32,30 +32,20 @@
#include "py/obj.h" #include "py/obj.h"
#define UDI_HID_MOUSE_REPORT_SIZE 4 #include "genhdr/autogen_usb_descriptor.h"
#define UDI_HID_KBD_REPORT_SIZE 8
enum usb_hid_device_kind {
USB_HID_UNKNOWN,
USB_HID_MOUSE,
USB_HID_KEYBOARD,
};
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
enum usb_hid_device_kind kind;
uint8_t endpoint;
uint8_t report_length;
uint8_t* report_buffer; uint8_t* report_buffer;
uint8_t endpoint;
uint8_t report_id; // If non-zero, prefix report with given id.
uint8_t report_length; // Length not including Report ID.
uint8_t usage_page; uint8_t usage_page;
uint8_t usage; uint8_t usage;
} usb_hid_device_obj_t; } usb_hid_device_obj_t;
usb_hid_device_obj_t usb_hid_devices[2]; usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES];
// Indices into usb_hid_devices:
#define USB_HID_DEVICE_MOUSE 0
#define USB_HID_DEVICE_KEYBOARD 1
void usb_hid_init(void); void usb_hid_init(void);
void usb_hid_reset(void); void usb_hid_reset(void);

View File

@ -32,37 +32,63 @@
#include "shared-bindings/usb_hid/Device.h" #include "shared-bindings/usb_hid/Device.h"
#include "tools/autogen_usb_descriptor.h" #include "genhdr/autogen_usb_descriptor.h"
static uint8_t mouse_report_buffer[UDI_HID_MOUSE_REPORT_SIZE]; // Buffers are report size + 1 to include the Report ID prefix byte
static uint8_t kbd_report_buffer[UDI_HID_KBD_REPORT_SIZE]; static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD + 1];
static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE + 1];
static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER + 1];
static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL + 1];
usb_hid_device_obj_t usb_hid_devices[2] = { usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = {
{ {
.kind = USB_HID_MOUSE, .base = { .type = &usb_hid_device_type },
.report_length = UDI_HID_MOUSE_REPORT_SIZE, .report_buffer = keyboard_report_buffer,
.endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_KEYBOARD,
.report_length = USB_HID_REPORT_LENGTH_KEYBOARD,
.usage_page = 0x01,
.usage = 0x06,
},
{
.base = { .type = &usb_hid_device_type },
.report_buffer = mouse_report_buffer, .report_buffer = mouse_report_buffer,
.endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_MOUSE,
.report_length = USB_HID_REPORT_LENGTH_MOUSE,
.usage_page = 0x01, .usage_page = 0x01,
.usage = 0x02, .usage = 0x02,
}, },
{ {
.kind = USB_HID_KEYBOARD, .base = { .type = &usb_hid_device_type },
.report_length = UDI_HID_KBD_REPORT_SIZE, .report_buffer = consumer_report_buffer,
.report_buffer = kbd_report_buffer, .endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_CONSUMER,
.report_length = USB_HID_REPORT_LENGTH_CONSUMER,
.usage_page = 0x0C,
.usage = 0x01,
},
{
.base = { .type = &usb_hid_device_type },
.report_buffer = sys_control_report_buffer,
.endpoint = USB_HID_ENDPOINT_IN,
.report_id = USB_HID_REPORT_ID_SYS_CONTROL,
.report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL,
.usage_page = 0x01, .usage_page = 0x01,
.usage = 0x06, .usage = 0x80,
} },
}; };
// TODO(tannewt): Make this a mp_obj_tuple_t when it is dynamically allocated.
// until then we hard code it to two entries so LTO is happy. mp_obj_tuple_t common_hal_usb_hid_devices = {
mp_obj_tuple2_t common_hal_usb_hid_devices = {
.base = { .base = {
.type = &mp_type_tuple, .type = &mp_type_tuple,
}, },
.len = 2, .len = USB_HID_NUM_DEVICES,
.items = { .items = {
(mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_MOUSE], (mp_obj_t) &usb_hid_devices[0],
(mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_KEYBOARD], (mp_obj_t) &usb_hid_devices[1],
(mp_obj_t) &usb_hid_devices[2],
(mp_obj_t) &usb_hid_devices[3],
} }
}; };

View File

@ -31,7 +31,7 @@
#include "common-hal/usb_hid/Device.h" #include "common-hal/usb_hid/Device.h"
#include "usb.h" #include "usb.h"
#include "tools/autogen_usb_descriptor.h" #include "genhdr/autogen_usb_descriptor.h"
// Serial number as hex characters. This writes directly to the USB // Serial number as hex characters. This writes directly to the USB
// descriptor. // descriptor.

View File

@ -1,38 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H
#define MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H
#include "usb/device/usbdc.h"
struct usbd_descriptors descriptor_bounds;
uint8_t* serial_number;
uint8_t serial_number_length;
uint8_t hid_mouse_endpoint_in;
uint8_t hid_keyboard_endpoint_in;
#endif // MICROPY_INCLUDED_ATMEL_SAMD_TOOLS_AUTOGEN_USB_DESCRIPTOR_H

View File

@ -19,7 +19,8 @@ parser.add_argument('--pid', type=lambda x: int(x, 16),
help='product id') help='product id')
parser.add_argument('--serial_number_length', type=int, default=32, parser.add_argument('--serial_number_length', type=int, default=32,
help='length needed for the serial number in digits') help='length needed for the serial number in digits')
parser.add_argument('output_file', type=argparse.FileType('w')) parser.add_argument('--output_c_file', type=argparse.FileType('w'), required=True)
parser.add_argument('--output_h_file', type=argparse.FileType('w'), required=True)
args = parser.parse_args() args = parser.parse_args()
@ -33,6 +34,7 @@ strings = [langid, manufacturer, product, serial_number]
# pid = 0x8021 # pid = 0x8021
device = standard.DeviceDescriptor( device = standard.DeviceDescriptor(
description="top",
idVendor=args.vid, idVendor=args.vid,
idProduct=args.pid, idProduct=args.pid,
iManufacturer=strings.index(manufacturer), iManufacturer=strings.index(manufacturer),
@ -43,6 +45,7 @@ device = standard.DeviceDescriptor(
# until core.join_interfaces renumbers them. # until core.join_interfaces renumbers them.
cdc_interfaces = [ cdc_interfaces = [
standard.InterfaceDescriptor( standard.InterfaceDescriptor(
description="CDC comm",
bInterfaceClass=cdc.CDC_CLASS_COMM, # Communications Device Class bInterfaceClass=cdc.CDC_CLASS_COMM, # Communications Device Class
bInterfaceSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model bInterfaceSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model
bInterfaceProtocol=cdc.CDC_PROTOCOL_V25TER, # Common AT Commands bInterfaceProtocol=cdc.CDC_PROTOCOL_V25TER, # Common AT Commands
@ -53,12 +56,22 @@ cdc_interfaces = [
# 05 24 01 03 01 call manage # 05 24 01 03 01 call manage
# 04 24 02 06 acm # 04 24 02 06 acm
# 05 24 06 00 01 union # 05 24 06 00 01 union
cdc.Header(bcdCDC=0x0110), cdc.Header(
cdc.CallManagement(bmCapabilities=0x03, bDataInterface=0x01), description="CDC comm",
cdc.AbstractControlManagement(bmCapabilities=0x02), bcdCDC=0x0110),
cdc.Union(bMasterInterface=0x00, cdc.CallManagement(
bSlaveInterface_list=[0x01]), description="CDC comm",
bmCapabilities=0x03,
bDataInterface=0x01),
cdc.AbstractControlManagement(
description="CDC comm",
bmCapabilities=0x02),
cdc.Union(
description="CDC comm",
bMasterInterface=0x00,
bSlaveInterface_list=[0x01]),
standard.EndpointDescriptor( standard.EndpointDescriptor(
description="CDC comm in",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT,
wMaxPacketSize=0x0040, wMaxPacketSize=0x0040,
@ -66,12 +79,15 @@ cdc_interfaces = [
] ]
), ),
standard.InterfaceDescriptor( standard.InterfaceDescriptor(
description="CDC data",
bInterfaceClass=cdc.CDC_CLASS_DATA, bInterfaceClass=cdc.CDC_CLASS_DATA,
subdescriptors=[ subdescriptors=[
standard.EndpointDescriptor( standard.EndpointDescriptor(
description="CDC data in",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK), bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
standard.EndpointDescriptor( standard.EndpointDescriptor(
description="CDC data out",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK) bmAttributes=standard.EndpointDescriptor.TYPE_BULK)
] ]
@ -80,66 +96,69 @@ cdc_interfaces = [
msc_interfaces = [ msc_interfaces = [
standard.InterfaceDescriptor( standard.InterfaceDescriptor(
description="MSC",
bInterfaceClass=msc.MSC_CLASS, bInterfaceClass=msc.MSC_CLASS,
bInterfaceSubClass=msc.MSC_SUBCLASS_TRANSPARENT, bInterfaceSubClass=msc.MSC_SUBCLASS_TRANSPARENT,
bInterfaceProtocol=msc.MSC_PROTOCOL_BULK, bInterfaceProtocol=msc.MSC_PROTOCOL_BULK,
subdescriptors=[ subdescriptors=[
standard.EndpointDescriptor( standard.EndpointDescriptor(
description="MSC in",
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK), bmAttributes=standard.EndpointDescriptor.TYPE_BULK),
standard.EndpointDescriptor( standard.EndpointDescriptor(
description="MSC out",
bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT, bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT,
bmAttributes=standard.EndpointDescriptor.TYPE_BULK) bmAttributes=standard.EndpointDescriptor.TYPE_BULK)
] ]
) )
] ]
hid_report_descriptors = [ hid_report_descriptor = hid.ReportDescriptor.MOUSE_KEYBOARD_CONSUMER_SYS_CONTROL_REPORT
hid.ReportDescriptor.GENERIC_MOUSE_REPORT, hid_report_ids = hid.ReportDescriptor.REPORT_IDS
hid.ReportDescriptor.GENERIC_KEYBOARD_REPORT, hid_report_lengths = hid.ReportDescriptor.REPORT_LENGTHS
] hid_max_report_length = max(hid_report_lengths.values())
mouse_endpoint_descriptor = standard.EndpointDescriptor( # ASF4 expects keyboard and generic devices to have both in and out endpoints,
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, # and will fail in mysterious ways if you only supply one.
bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, hid_endpoint_in_descriptor = standard.EndpointDescriptor(
wMaxPacketSize=8, # mouse report is small description="HID in",
bInterval=0x0a) bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN,
bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT,
wMaxPacketSize=hid_max_report_length + 1, # +1 for the Report ID
bInterval=0x02)
keyboard_endpoint_descriptor = standard.EndpointDescriptor( hid_endpoint_out_descriptor = standard.EndpointDescriptor(
bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, description="HID out",
bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT,
wMaxPacketSize=8, # keyboard report is 8 bytes bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT)
bInterval=0x02)
hid_interfaces = [ hid_interfaces = [
standard.InterfaceDescriptor( standard.InterfaceDescriptor(
bInterfaceClass = hid.HID_CLASS, description="HID Keyboard",
bInterfaceSubClass = hid.HID_SUBCLASS_BOOT, bInterfaceClass=hid.HID_CLASS,
bInterfaceProtocol = hid.HID_PROTOCOL_MOUSE, bInterfaceSubClass=hid.HID_SUBCLASS_NOBOOT,
bInterfaceProtocol=hid.HID_PROTOCOL_KEYBOARD,
subdescriptors=[ subdescriptors=[
mouse_endpoint_descriptor, hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptor))),
hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptors[0]))), hid_endpoint_in_descriptor,
] hid_endpoint_out_descriptor,
),
standard.InterfaceDescriptor(
bInterfaceClass = hid.HID_CLASS,
bInterfaceSubClass = hid.HID_SUBCLASS_NOBOOT,
bInterfaceProtocol = hid.HID_PROTOCOL_KEYBOARD,
subdescriptors=[
keyboard_endpoint_descriptor,
hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptors[1]))),
] ]
), ),
# bInterfaceClass = hid.HID_CLASS,
# bInterfaceSubClass = hid.HID_SUBCLASS_NOBOOT,
# bInterfaceProtocol=hid.HID_PROTOCOL_MOUSE,
# subdescriptors=[
# hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptor))),
# hid_endpoint_descriptor,
# ]
# ),
] ]
# This will renumber the endpoints to make them unique across descriptors. # This will renumber the endpoints to make them unique across descriptors.
print(mouse_endpoint_descriptor.bEndpointAddress, keyboard_endpoint_descriptor.bEndpointAddress) interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces)
###interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces)
interfaces = util.join_interfaces(cdc_interfaces, hid_interfaces)
print(mouse_endpoint_descriptor.bEndpointAddress, keyboard_endpoint_descriptor.bEndpointAddress)
cdc_function = standard.InterfaceAssociationDescriptor( cdc_function = standard.InterfaceAssociationDescriptor(
description="CDC function",
bFirstInterface=interfaces.index(cdc_interfaces[0]), bFirstInterface=interfaces.index(cdc_interfaces[0]),
bInterfaceCount=len(cdc_interfaces), bInterfaceCount=len(cdc_interfaces),
bFunctionClass=0x2, # Communications Device Class bFunctionClass=0x2, # Communications Device Class
@ -147,6 +166,7 @@ cdc_function = standard.InterfaceAssociationDescriptor(
bFunctionProtocol=0x1) # Common AT Commands bFunctionProtocol=0x1) # Common AT Commands
configuration = standard.ConfigurationDescriptor( configuration = standard.ConfigurationDescriptor(
description="CDC configuration",
wTotalLength=(standard.ConfigurationDescriptor.bLength + wTotalLength=(standard.ConfigurationDescriptor.bLength +
cdc_function.bLength + cdc_function.bLength +
sum([len(bytes(x)) for x in interfaces])), sum([len(bytes(x)) for x in interfaces])),
@ -154,56 +174,115 @@ configuration = standard.ConfigurationDescriptor(
descriptor_list = [device, configuration, cdc_function] descriptor_list = [device, configuration, cdc_function]
descriptor_list.extend(interfaces) descriptor_list.extend(interfaces)
##descriptor_list.extend(hid_report_descriptors)
descriptor_list.extend(strings) descriptor_list.extend(strings)
output_file = args.output_file c_file = args.output_c_file
h_file = args.output_h_file
output_file.write("""
c_file.write("""\
#include <stdint.h> #include <stdint.h>
#include "tools/autogen_usb_descriptor.h" #include "{H_FILE_NAME}"
""".format(H_FILE_NAME=h_file.name))
c_file.write("""\
uint8_t usb_descriptors[] = { uint8_t usb_descriptors[] = {
""") """)
# Write out all the regular descriptors as one long array (that's how ASF4 does it).
descriptor_length = 0 descriptor_length = 0
serial_number_offset = None serial_number_offset = None
for descriptor in descriptor_list: for descriptor in descriptor_list:
print(str(descriptor)) c_file.write("""\
print([hex(x) for x in bytes(descriptor)]) // {DESCRIPTION} : {CLASS}
output_file.write("// " + str(descriptor) + "\n") """.format(DESCRIPTION=descriptor.description,
CLASS=descriptor.__class__))
b = bytes(descriptor) b = bytes(descriptor)
i = 0 i = 0
if descriptor == serial_number: if descriptor == serial_number:
# Add two for the length and descriptor type bytes. # Add two for bLength and bDescriptorType.
serial_number_offset = descriptor_length + 2 serial_number_offset = descriptor_length + 2
# This prints each subdescriptor on a separate line. # This prints each subdescriptor on a separate line.
while i < len(b): while i < len(b):
length = b[i] length = b[i]
for j in range(length): for j in range(length):
output_file.write("0x{:02x}, ".format(b[i + j])) c_file.write("0x{:02x}, ".format(b[i + j]))
output_file.write("\n") c_file.write("\n")
i += length i += length
descriptor_length += length descriptor_length += length
output_file.write(""" c_file.write("""\
}; };
""") """)
output_file.write(""" # Now we values we need for the .h file.
h_file.write("""\
#ifndef MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H
#define MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H
#include "usb/device/usbdc.h"
struct usbd_descriptors descriptor_bounds;
#define SERIAL_NUMBER_OFFSET {SERIAL_NUMBER_OFFSET}
#define SERIAL_NUMBER_LENGTH {SERIAL_NUMBER_LENGTH}
uint8_t* serial_number;
uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
#define USB_HID_ENDPOINT_IN {HID_ENDPOINT_IN_ADDRESS}
#define USB_HID_ENDPOINT_OUT {HID_ENDPOINT_OUT_ADDRESS}
"""
.format(SERIAL_NUMBER_OFFSET=serial_number_offset,
SERIAL_NUMBER_LENGTH=args.serial_number_length,
HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(hid_report_descriptor)),
HID_ENDPOINT_IN_ADDRESS=hex(hid_endpoint_in_descriptor.bEndpointAddress),
HID_ENDPOINT_OUT_ADDRESS=hex(hid_endpoint_out_descriptor.bEndpointAddress)))
# #define the report ID's used in the combined HID descriptor
for name, id in hid_report_ids.items():
h_file.write("""\
#define USB_HID_REPORT_ID_{NAME} {ID}
""".format(NAME=name,
ID = id))
# #define the report sizes used in the combined HID descriptor
for name, length in hid_report_lengths.items():
h_file.write("""\
#define USB_HID_REPORT_LENGTH_{NAME} {LENGTH}
""".format(NAME=name,
LENGTH=length))
h_file.write("""\
#define USB_HID_NUM_DEVICES {NUM_DEVICES}
#define USB_HID_MAX_REPORT_LENGTH {MAX_LENGTH}
""".format(NUM_DEVICES=len(hid_report_lengths),
MAX_LENGTH=hid_max_report_length))
# Write out the report descriptor and info
c_file.write("""\
uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
""".format(HID_DESCRIPTOR_LENGTH=len(bytes(hid_report_descriptor))))
for b in bytes(hid_report_descriptor):
c_file.write("0x{:02x}, ".format(b))
c_file.write("""
};
""")
c_file.write("""\
struct usbd_descriptors descriptor_bounds = {{usb_descriptors, usb_descriptors + sizeof(usb_descriptors)}}; struct usbd_descriptors descriptor_bounds = {{usb_descriptors, usb_descriptors + sizeof(usb_descriptors)}};
uint8_t* serial_number = usb_descriptors + {SERIAL_NUMBER_OFFSET}; uint8_t* serial_number = usb_descriptors + {SERIAL_NUMBER_OFFSET};
uint8_t serial_number_length = {SERIAL_NUMBER_LENGTH}; """.format(SERIAL_NUMBER_OFFSET=serial_number_offset))
uint8_t hid_mouse_endpoint_in = {MOUSE_ENDPOINT_ADDRESS}; h_file.write("""\
uint8_t hid_keyboard_endpoint_in = {KEYBOARD_ENDPOINT_ADDRESS}; #endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H
""".format(SERIAL_NUMBER_OFFSET=serial_number_offset, """)
SERIAL_NUMBER_LENGTH=args.serial_number_length,
MOUSE_ENDPOINT_ADDRESS=mouse_endpoint_descriptor.bEndpointAddress,
KEYBOARD_ENDPOINT_ADDRESS=keyboard_endpoint_descriptor.bEndpointAddress
)
)

View File

@ -34,8 +34,7 @@
#include "hal/include/hal_gpio.h" #include "hal/include/hal_gpio.h"
#include "usb/class/cdc/device/cdcdf_acm.h" #include "usb/class/cdc/device/cdcdf_acm.h"
#include "usb/class/hid/device/hiddf_mouse.h" #include "usb/class/hid/device/hiddf_generic.h"
#include "usb/class/hid/device/hiddf_keyboard.h"
#include "usb/class/composite/device/composite_desc.h" #include "usb/class/composite/device/composite_desc.h"
#include "usb/class/msc/device/mscdf.h" #include "usb/class/msc/device/mscdf.h"
#include "peripheral_clk_config.h" #include "peripheral_clk_config.h"
@ -43,7 +42,7 @@
#include "hpl/gclk/hpl_gclk_base.h" #include "hpl/gclk/hpl_gclk_base.h"
#include "lib/utils/interrupt_char.h" #include "lib/utils/interrupt_char.h"
#include "tools/autogen_usb_descriptor.h" #include "genhdr/autogen_usb_descriptor.h"
#include "reset.h" #include "reset.h"
#include "usb_mass_storage.h" #include "usb_mass_storage.h"
@ -203,7 +202,7 @@ void init_usb(void) {
usbdc_init(ctrl_buffer); usbdc_init(ctrl_buffer);
/* usbdc_register_funcion inside */ /* usbdc_register_function inside */
cdcdf_acm_init(); cdcdf_acm_init();
pending_read = false; pending_read = false;
@ -217,12 +216,13 @@ void init_usb(void) {
mscdf_register_callback(MSCDF_CB_XFER_BLOCKS_DONE, (FUNC_PTR)usb_msc_xfer_done); mscdf_register_callback(MSCDF_CB_XFER_BLOCKS_DONE, (FUNC_PTR)usb_msc_xfer_done);
mscdf_register_callback(MSCDF_CB_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable); mscdf_register_callback(MSCDF_CB_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable);
hiddf_mouse_init(); hiddf_generic_init(hid_report_descriptor, sizeof(hid_report_descriptor));
hiddf_keyboard_init();
usbdc_start(&descriptor_bounds); usbdc_start(&descriptor_bounds);
usbdc_attach(); usbdc_attach();
} }
static bool cdc_enabled(void) { static bool cdc_enabled(void) {

View File

@ -34,13 +34,6 @@ typedef struct _mp_obj_tuple_t {
mp_obj_t items[]; mp_obj_t items[];
} mp_obj_tuple_t; } mp_obj_tuple_t;
// TODO(tannewt): Remove this when we no longer hard code the usb hid tuple.
typedef struct _mp_obj_tuple2_t {
mp_obj_base_t base;
size_t len;
mp_obj_t items[2];
} mp_obj_tuple2_t;
typedef struct _mp_rom_obj_tuple_t { typedef struct _mp_rom_obj_tuple_t {
mp_obj_base_t base; mp_obj_base_t base;
size_t len; size_t len;

View File

@ -30,8 +30,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
// TODO(tannewt): Make this a mp_obj_tuple_t when it is dynamically allocated. extern mp_obj_tuple_t common_hal_usb_hid_devices;
// until then we hard code it to two entries so LTO is happy.
extern mp_obj_tuple2_t common_hal_usb_hid_devices;
#endif // SHARED_BINDINGS_USB_HID_H #endif // SHARED_BINDINGS_USB_HID_H

@ -1 +1 @@
Subproject commit a04341153b41b4728f9b42a77cbd51c495362287 Subproject commit b4aca689fd234b4e6ae37030f0815fbb519ce62d