diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 71acca18ed..49823c0de1 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -96,8 +96,8 @@ endif ifeq ($(DEBUG), 1) # Turn on Python modules useful for debugging (e.g. uheap, ustack). CFLAGS += -ggdb - CFLAGS += -flto - CFLAGS += -fno-inline +## CFLAGS += -flto + CFLAGS += -fno-inline -fno-ipa-sra ifeq ($(CHIP_FAMILY), samd21) CFLAGS += -DENABLE_MICRO_TRACE_BUFFER endif @@ -193,8 +193,7 @@ SRC_ASF := \ hpl/systick/hpl_systick.c \ hpl/usb/hpl_usb.c \ usb/class/cdc/device/cdcdf_acm.c \ - usb/class/hid/device/hiddf_keyboard.c \ - usb/class/hid/device/hiddf_mouse.c \ + usb/class/hid/device/hiddf_generic.c \ usb/class/msc/device/mscdf.c \ usb/device/usbdc.c \ usb/usb_protocol.c \ @@ -381,14 +380,19 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(ECHO) "Create $@" 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) python3 tools/gen_usb_descriptor.py \ --manufacturer $(USB_MANUFACTURER)\ --product $(USB_PRODUCT)\ --vid $(USB_VID)\ --pid $(USB_PID)\ - $@ + --output_c_file $(BUILD)/autogen_usb_descriptor.c\ + --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h deploy: $(BUILD)/firmware.bin $(ECHO) "Writing $< to the board" diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.c b/ports/atmel-samd/common-hal/usb_hid/Device.c index 9568a27ef1..226d92e90e 100644 --- a/ports/atmel-samd/common-hal/usb_hid/Device.c +++ b/ports/atmel-samd/common-hal/usb_hid/Device.c @@ -31,12 +31,11 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/usb_hid/Device.h" -#include "tools/autogen_usb_descriptor.h" +#include "genhdr/autogen_usb_descriptor.h" #include "tick.h" -#include "usb/class/hid/device/hiddf_mouse.h" -#include "usb/class/hid/device/hiddf_keyboard.h" +#include "usb/class/hid/device/hiddf_generic.h" 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 // buffer load gets zero'd out when transaction completes, so if // you copy before it's ready, only zeros will get sent. - memcpy(self->report_buffer, report, len); - switch (self->kind) { - case USB_HID_MOUSE: - status = hiddf_mouse_write(self->report_buffer, self->report_length); - break; - - case USB_HID_KEYBOARD: - status = hiddf_keyboard_write(self->report_buffer, self->report_length); - break; - - default: - mp_raise_ValueError("Unknown HID device"); + // Prefix with a report id if one is supplied + if (self->report_id > 0) { + self->report_buffer[0] = self->report_id; + memcpy(&(self->report_buffer[1]), report, len); + } else { + memcpy(self->report_buffer, report, len); } - 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) { @@ -98,18 +91,14 @@ uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) { 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() { // We don't actually reset. We just set a report that is empty to prevent // 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); - usb_hid_send_report(&usb_hid_devices[USB_HID_DEVICE_KEYBOARD], report, UDI_HID_KBD_REPORT_SIZE); + for (size_t i = 0; i < USB_HID_NUM_DEVICES; i++) { + usb_hid_send_report(&usb_hid_devices[i], report, usb_hid_devices[i].report_length); + } } diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.h b/ports/atmel-samd/common-hal/usb_hid/Device.h index d4d016009b..f85522d657 100644 --- a/ports/atmel-samd/common-hal/usb_hid/Device.h +++ b/ports/atmel-samd/common-hal/usb_hid/Device.h @@ -32,30 +32,20 @@ #include "py/obj.h" -#define UDI_HID_MOUSE_REPORT_SIZE 4 -#define UDI_HID_KBD_REPORT_SIZE 8 - -enum usb_hid_device_kind { - USB_HID_UNKNOWN, - USB_HID_MOUSE, - USB_HID_KEYBOARD, -}; +#include "genhdr/autogen_usb_descriptor.h" typedef struct { mp_obj_base_t base; - enum usb_hid_device_kind kind; - uint8_t endpoint; - uint8_t report_length; 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; } usb_hid_device_obj_t; -usb_hid_device_obj_t usb_hid_devices[2]; -// Indices into usb_hid_devices: -#define USB_HID_DEVICE_MOUSE 0 -#define USB_HID_DEVICE_KEYBOARD 1 +usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES]; void usb_hid_init(void); void usb_hid_reset(void); diff --git a/ports/atmel-samd/common-hal/usb_hid/__init__.c b/ports/atmel-samd/common-hal/usb_hid/__init__.c index 3b49d35761..7d5946877c 100644 --- a/ports/atmel-samd/common-hal/usb_hid/__init__.c +++ b/ports/atmel-samd/common-hal/usb_hid/__init__.c @@ -32,37 +32,63 @@ #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]; -static uint8_t kbd_report_buffer[UDI_HID_KBD_REPORT_SIZE]; +// Buffers are report size + 1 to include the Report ID prefix byte +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, - .report_length = UDI_HID_MOUSE_REPORT_SIZE, + .base = { .type = &usb_hid_device_type }, + .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, + .endpoint = USB_HID_ENDPOINT_IN, + .report_id = USB_HID_REPORT_ID_MOUSE, + .report_length = USB_HID_REPORT_LENGTH_MOUSE, .usage_page = 0x01, .usage = 0x02, }, { - .kind = USB_HID_KEYBOARD, - .report_length = UDI_HID_KBD_REPORT_SIZE, - .report_buffer = kbd_report_buffer, + .base = { .type = &usb_hid_device_type }, + .report_buffer = consumer_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 = 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_tuple2_t common_hal_usb_hid_devices = { + +mp_obj_tuple_t common_hal_usb_hid_devices = { .base = { .type = &mp_type_tuple, }, - .len = 2, + .len = USB_HID_NUM_DEVICES, .items = { - (mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_MOUSE], - (mp_obj_t) &usb_hid_devices[USB_HID_DEVICE_KEYBOARD], + (mp_obj_t) &usb_hid_devices[0], + (mp_obj_t) &usb_hid_devices[1], + (mp_obj_t) &usb_hid_devices[2], + (mp_obj_t) &usb_hid_devices[3], } }; diff --git a/ports/atmel-samd/supervisor/serial.c b/ports/atmel-samd/supervisor/serial.c index 9461381b30..4917dfb5b2 100644 --- a/ports/atmel-samd/supervisor/serial.c +++ b/ports/atmel-samd/supervisor/serial.c @@ -31,7 +31,7 @@ #include "common-hal/usb_hid/Device.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 // descriptor. diff --git a/ports/atmel-samd/tools/autogen_usb_descriptor.h b/ports/atmel-samd/tools/autogen_usb_descriptor.h deleted file mode 100644 index a1f4f9ba0e..0000000000 --- a/ports/atmel-samd/tools/autogen_usb_descriptor.h +++ /dev/null @@ -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 diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/ports/atmel-samd/tools/gen_usb_descriptor.py index fb8bf2bbe5..82f374bdcf 100644 --- a/ports/atmel-samd/tools/gen_usb_descriptor.py +++ b/ports/atmel-samd/tools/gen_usb_descriptor.py @@ -19,7 +19,8 @@ parser.add_argument('--pid', type=lambda x: int(x, 16), help='product id') parser.add_argument('--serial_number_length', type=int, default=32, 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() @@ -33,6 +34,7 @@ strings = [langid, manufacturer, product, serial_number] # pid = 0x8021 device = standard.DeviceDescriptor( + description="top", idVendor=args.vid, idProduct=args.pid, iManufacturer=strings.index(manufacturer), @@ -43,6 +45,7 @@ device = standard.DeviceDescriptor( # until core.join_interfaces renumbers them. cdc_interfaces = [ standard.InterfaceDescriptor( + description="CDC comm", bInterfaceClass=cdc.CDC_CLASS_COMM, # Communications Device Class bInterfaceSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model bInterfaceProtocol=cdc.CDC_PROTOCOL_V25TER, # Common AT Commands @@ -53,12 +56,22 @@ cdc_interfaces = [ # 05 24 01 03 01 call manage # 04 24 02 06 acm # 05 24 06 00 01 union - cdc.Header(bcdCDC=0x0110), - cdc.CallManagement(bmCapabilities=0x03, bDataInterface=0x01), - cdc.AbstractControlManagement(bmCapabilities=0x02), - cdc.Union(bMasterInterface=0x00, - bSlaveInterface_list=[0x01]), + cdc.Header( + description="CDC comm", + bcdCDC=0x0110), + cdc.CallManagement( + 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( + description="CDC comm in", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, wMaxPacketSize=0x0040, @@ -66,12 +79,15 @@ cdc_interfaces = [ ] ), standard.InterfaceDescriptor( + description="CDC data", bInterfaceClass=cdc.CDC_CLASS_DATA, subdescriptors=[ standard.EndpointDescriptor( + description="CDC data in", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bmAttributes=standard.EndpointDescriptor.TYPE_BULK), standard.EndpointDescriptor( + description="CDC data out", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, bmAttributes=standard.EndpointDescriptor.TYPE_BULK) ] @@ -80,66 +96,69 @@ cdc_interfaces = [ msc_interfaces = [ standard.InterfaceDescriptor( + description="MSC", bInterfaceClass=msc.MSC_CLASS, bInterfaceSubClass=msc.MSC_SUBCLASS_TRANSPARENT, bInterfaceProtocol=msc.MSC_PROTOCOL_BULK, subdescriptors=[ standard.EndpointDescriptor( + description="MSC in", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bmAttributes=standard.EndpointDescriptor.TYPE_BULK), standard.EndpointDescriptor( + description="MSC out", bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT, bmAttributes=standard.EndpointDescriptor.TYPE_BULK) ] ) ] -hid_report_descriptors = [ - hid.ReportDescriptor.GENERIC_MOUSE_REPORT, - hid.ReportDescriptor.GENERIC_KEYBOARD_REPORT, -] +hid_report_descriptor = hid.ReportDescriptor.MOUSE_KEYBOARD_CONSUMER_SYS_CONTROL_REPORT +hid_report_ids = hid.ReportDescriptor.REPORT_IDS +hid_report_lengths = hid.ReportDescriptor.REPORT_LENGTHS +hid_max_report_length = max(hid_report_lengths.values()) -mouse_endpoint_descriptor = standard.EndpointDescriptor( - bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, - bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, - wMaxPacketSize=8, # mouse report is small - bInterval=0x0a) +# ASF4 expects keyboard and generic devices to have both in and out endpoints, +# and will fail in mysterious ways if you only supply one. +hid_endpoint_in_descriptor = standard.EndpointDescriptor( + description="HID in", + 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( - bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, - bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, - wMaxPacketSize=8, # keyboard report is 8 bytes - bInterval=0x02) +hid_endpoint_out_descriptor = standard.EndpointDescriptor( + description="HID out", + bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT, + bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT) hid_interfaces = [ standard.InterfaceDescriptor( - bInterfaceClass = hid.HID_CLASS, - bInterfaceSubClass = hid.HID_SUBCLASS_BOOT, - bInterfaceProtocol = hid.HID_PROTOCOL_MOUSE, + description="HID Keyboard", + bInterfaceClass=hid.HID_CLASS, + bInterfaceSubClass=hid.HID_SUBCLASS_NOBOOT, + bInterfaceProtocol=hid.HID_PROTOCOL_KEYBOARD, subdescriptors=[ - mouse_endpoint_descriptor, - hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptors[0]))), - ] - ), - 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]))), + hid.HIDDescriptor(wDescriptorLength=len(bytes(hid_report_descriptor))), + hid_endpoint_in_descriptor, + hid_endpoint_out_descriptor, ] ), + # 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. -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, hid_interfaces) -print(mouse_endpoint_descriptor.bEndpointAddress, keyboard_endpoint_descriptor.bEndpointAddress) - +interfaces = util.join_interfaces(cdc_interfaces, msc_interfaces, hid_interfaces) cdc_function = standard.InterfaceAssociationDescriptor( + description="CDC function", bFirstInterface=interfaces.index(cdc_interfaces[0]), bInterfaceCount=len(cdc_interfaces), bFunctionClass=0x2, # Communications Device Class @@ -147,6 +166,7 @@ cdc_function = standard.InterfaceAssociationDescriptor( bFunctionProtocol=0x1) # Common AT Commands configuration = standard.ConfigurationDescriptor( + description="CDC configuration", wTotalLength=(standard.ConfigurationDescriptor.bLength + cdc_function.bLength + sum([len(bytes(x)) for x in interfaces])), @@ -154,56 +174,115 @@ configuration = standard.ConfigurationDescriptor( descriptor_list = [device, configuration, cdc_function] descriptor_list.extend(interfaces) -##descriptor_list.extend(hid_report_descriptors) 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 -#include "tools/autogen_usb_descriptor.h" +#include "{H_FILE_NAME}" +""".format(H_FILE_NAME=h_file.name)) + +c_file.write("""\ uint8_t usb_descriptors[] = { """) +# Write out all the regular descriptors as one long array (that's how ASF4 does it). descriptor_length = 0 serial_number_offset = None for descriptor in descriptor_list: - print(str(descriptor)) - print([hex(x) for x in bytes(descriptor)]) - output_file.write("// " + str(descriptor) + "\n") + c_file.write("""\ +// {DESCRIPTION} : {CLASS} +""".format(DESCRIPTION=descriptor.description, + CLASS=descriptor.__class__)) + b = bytes(descriptor) i = 0 + 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 + # This prints each subdescriptor on a separate line. while i < len(b): length = b[i] for j in range(length): - output_file.write("0x{:02x}, ".format(b[i + j])) - output_file.write("\n") + c_file.write("0x{:02x}, ".format(b[i + j])) + c_file.write("\n") i += 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)}}; 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}; -uint8_t hid_keyboard_endpoint_in = {KEYBOARD_ENDPOINT_ADDRESS}; -""".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 - ) -) +h_file.write("""\ +#endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H +""") diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c index bc7313fdcb..02642df6f3 100644 --- a/ports/atmel-samd/usb.c +++ b/ports/atmel-samd/usb.c @@ -34,8 +34,7 @@ #include "hal/include/hal_gpio.h" #include "usb/class/cdc/device/cdcdf_acm.h" -#include "usb/class/hid/device/hiddf_mouse.h" -#include "usb/class/hid/device/hiddf_keyboard.h" +#include "usb/class/hid/device/hiddf_generic.h" #include "usb/class/composite/device/composite_desc.h" #include "usb/class/msc/device/mscdf.h" #include "peripheral_clk_config.h" @@ -43,7 +42,7 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "lib/utils/interrupt_char.h" -#include "tools/autogen_usb_descriptor.h" +#include "genhdr/autogen_usb_descriptor.h" #include "reset.h" #include "usb_mass_storage.h" @@ -203,7 +202,7 @@ void init_usb(void) { usbdc_init(ctrl_buffer); - /* usbdc_register_funcion inside */ + /* usbdc_register_function inside */ cdcdf_acm_init(); 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_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable); - hiddf_mouse_init(); - hiddf_keyboard_init(); + hiddf_generic_init(hid_report_descriptor, sizeof(hid_report_descriptor)); usbdc_start(&descriptor_bounds); usbdc_attach(); + + } static bool cdc_enabled(void) { diff --git a/py/objtuple.h b/py/objtuple.h index bcf0c9ed4f..7f20ab7b6f 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -34,13 +34,6 @@ typedef struct _mp_obj_tuple_t { mp_obj_t items[]; } 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 { mp_obj_base_t base; size_t len; diff --git a/shared-bindings/usb_hid/__init__.h b/shared-bindings/usb_hid/__init__.h index ff478d0836..3d56fbfd02 100644 --- a/shared-bindings/usb_hid/__init__.h +++ b/shared-bindings/usb_hid/__init__.h @@ -30,8 +30,6 @@ #include #include -// 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. -extern mp_obj_tuple2_t common_hal_usb_hid_devices; +extern mp_obj_tuple_t common_hal_usb_hid_devices; #endif // SHARED_BINDINGS_USB_HID_H diff --git a/tools/usb_descriptor b/tools/usb_descriptor index a04341153b..b4aca689fd 160000 --- a/tools/usb_descriptor +++ b/tools/usb_descriptor @@ -1 +1 @@ -Subproject commit a04341153b41b4728f9b42a77cbd51c495362287 +Subproject commit b4aca689fd234b4e6ae37030f0815fbb519ce62d