diff --git a/ports/atmel-samd/common-hal/usb_hid/__init__.c b/ports/atmel-samd/common-hal/usb_hid/__init__.c index 8cbccbb4c41df..c9157519fab5b 100644 --- a/ports/atmel-samd/common-hal/usb_hid/__init__.c +++ b/ports/atmel-samd/common-hal/usb_hid/__init__.c @@ -35,12 +35,27 @@ #include "genhdr/autogen_usb_descriptor.h" // Buffers are report size + 1 to include the Report ID prefix byte if needed. +#ifdef USB_HID_REPORT_LENGTH_KEYBOARD static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD + 1]; +#endif +#ifdef USB_HID_REPORT_ID_MOUSE static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE + 1]; +#endif +#ifdef USB_HID_REPORT_ID_CONSUMER static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER + 1]; +#endif +#ifdef USB_HID_REPORT_ID_SYS_CONTROL static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL + 1]; +#endif +#ifdef USB_HID_REPORT_ID_GAMEPAD +static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD + 1]; +#endif +#ifdef USB_HID_REPORT_ID_DIGITIZER +static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER + 1]; +#endif usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { +#ifdef USB_HID_REPORT_LENGTH_KEYBOARD { .base = { .type = &usb_hid_device_type }, .report_buffer = keyboard_report_buffer, @@ -50,6 +65,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { .usage_page = 0x01, .usage = 0x06, }, +#endif +#ifdef USB_HID_REPORT_ID_MOUSE { .base = { .type = &usb_hid_device_type }, .report_buffer = mouse_report_buffer, @@ -59,6 +76,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { .usage_page = 0x01, .usage = 0x02, }, +#endif +#ifdef USB_HID_REPORT_ID_CONSUMER { .base = { .type = &usb_hid_device_type }, .report_buffer = consumer_report_buffer, @@ -68,6 +87,8 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { .usage_page = 0x0C, .usage = 0x01, }, +#endif +#ifdef USB_HID_REPORT_ID_SYS_CONTROL { .base = { .type = &usb_hid_device_type }, .report_buffer = sys_control_report_buffer, @@ -77,6 +98,29 @@ usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { .usage_page = 0x01, .usage = 0x80, }, +#endif +#ifdef USB_HID_REPORT_ID_GAMEPAD + { + .base = { .type = &usb_hid_device_type }, + .report_buffer = gamepad_report_buffer, + .endpoint = USB_HID_ENDPOINT_IN, + .report_id = USB_HID_REPORT_ID_GAMEPAD, + .report_length = USB_HID_REPORT_LENGTH_GAMEPAD, + .usage_page = 0x01, + .usage = 0x05, + }, +#endif +#ifdef USB_HID_REPORT_ID_DIGITIZER + { + .base = { .type = &usb_hid_device_type }, + .report_buffer = digitizer_report_buffer, + .endpoint = USB_HID_ENDPOINT_IN, + .report_id = USB_HID_REPORT_ID_DIGITIZER, + .report_length = USB_HID_REPORT_LENGTH_DIGITIZER, + .usage_page = 0x0D, + .usage = 0x02, + }, +#endif }; @@ -86,9 +130,23 @@ mp_obj_tuple_t common_hal_usb_hid_devices = { }, .len = USB_HID_NUM_DEVICES, .items = { +#if USB_HID_NUM_DEVICES >= 1 (mp_obj_t) &usb_hid_devices[0], +#endif +#if USB_HID_NUM_DEVICES >= 2 (mp_obj_t) &usb_hid_devices[1], +#endif +#if USB_HID_NUM_DEVICES >= 3 (mp_obj_t) &usb_hid_devices[2], +#endif +#if USB_HID_NUM_DEVICES >= 4 (mp_obj_t) &usb_hid_devices[3], +#endif +#if USB_HID_NUM_DEVICES >= 5 + (mp_obj_t) &usb_hid_devices[4], +#endif +#if USB_HID_NUM_DEVICES >= 6 + (mp_obj_t) &usb_hid_devices[5], +#endif } }; diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/ports/atmel-samd/tools/gen_usb_descriptor.py index 4669110fb7c22..efa8124bfa653 100644 --- a/ports/atmel-samd/tools/gen_usb_descriptor.py +++ b/ports/atmel-samd/tools/gen_usb_descriptor.py @@ -7,6 +7,7 @@ sys.path.append("../../tools/usb_descriptor") from adafruit_usb_descriptor import cdc, hid, msc, standard, util +import hid_report_descriptors parser = argparse.ArgumentParser(description='Generate USB descriptors.') parser.add_argument('--manufacturer', type=str, @@ -122,19 +123,29 @@ def strings_in_order(cls): standard.EndpointDescriptor( description="MSC in", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, - bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + bmAttributes=standard.EndpointDescriptor.TYPE_BULK, + bInterval=0), standard.EndpointDescriptor( description="MSC out", bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=standard.EndpointDescriptor.TYPE_BULK) + bmAttributes=standard.EndpointDescriptor.TYPE_BULK, + bInterval=0) ] ) ] -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()) +# Include only these HID devices. +# DIGITIZER works on Linux but conflicts with MOUSE, so leave it out for now. +hid_devices = ("KEYBOARD", "MOUSE", "CONSUMER", "GAMEPAD") + +combined_hid_report_descriptor = hid.ReportDescriptor( + description="MULTIDEVICE", + report_descriptor=b''.join( + hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor for name in hid_devices )) + +hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices } +hid_report_lengths_dict = { name: hid_report_descriptors.REPORT_LENGTHS[name] for name in hid_devices } +hid_max_report_length = max(hid_report_lengths_dict.values()) # ASF4 expects keyboard and generic devices to have both in and out endpoints, # and will fail (possibly silently) if both are not supplied. @@ -142,12 +153,13 @@ def strings_in_order(cls): description="HID in", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, - bInterval=0x02) + bInterval=10) hid_endpoint_out_descriptor = standard.EndpointDescriptor( description="HID out", bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT) + bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, + bInterval=10) hid_interfaces = [ standard.InterfaceDescriptor( @@ -159,7 +171,7 @@ def strings_in_order(cls): subdescriptors=[ hid.HIDDescriptor( description="HID", - wDescriptorLength=len(bytes(hid_report_descriptor))), + wDescriptorLength=len(bytes(combined_hid_report_descriptor))), hid_endpoint_in_descriptor, hid_endpoint_out_descriptor, ] @@ -274,7 +286,7 @@ def strings_in_order(cls): """ .format(SERIAL_NUMBER_OFFSET=serial_number_offset, SERIAL_NUMBER_LENGTH=args.serial_number_length, - HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(hid_report_descriptor)), + HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)), HID_ENDPOINT_IN_ADDRESS=hex(hid_endpoint_in_descriptor.bEndpointAddress), HID_ENDPOINT_OUT_ADDRESS=hex(hid_endpoint_out_descriptor.bEndpointAddress))) @@ -294,7 +306,7 @@ def strings_in_order(cls): h_file.write("\n") # #define the report ID's used in the combined HID descriptor -for name, id in hid_report_ids.items(): +for name, id in hid_report_ids_dict.items(): h_file.write("""\ #define USB_HID_REPORT_ID_{NAME} {ID} """.format(NAME=name, @@ -303,7 +315,7 @@ def strings_in_order(cls): h_file.write("\n") # #define the report sizes used in the combined HID descriptor -for name, length in hid_report_lengths.items(): +for name, length in hid_report_lengths_dict.items(): h_file.write("""\ #define USB_HID_REPORT_LENGTH_{NAME} {LENGTH} """.format(NAME=name, @@ -314,7 +326,7 @@ def strings_in_order(cls): 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), +""".format(NUM_DEVICES=len(hid_report_lengths_dict), MAX_LENGTH=hid_max_report_length)) @@ -322,9 +334,9 @@ def strings_in_order(cls): # 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)))) +""".format(HID_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)))) -for b in bytes(hid_report_descriptor): +for b in bytes(combined_hid_report_descriptor): c_file.write("0x{:02x}, ".format(b)) c_file.write(""" }; diff --git a/ports/atmel-samd/tools/hid_report_descriptors.py b/ports/atmel-samd/tools/hid_report_descriptors.py new file mode 100644 index 0000000000000..f3b28ebcf38e2 --- /dev/null +++ b/ports/atmel-samd/tools/hid_report_descriptors.py @@ -0,0 +1,239 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Dan Halbert 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. + +import struct + +""" +HID specific descriptors +======================== + +* Author(s): Dan Halbert +""" + +from adafruit_usb_descriptor import hid + +REPORT_IDS = { + "KEYBOARD" : 1, + "MOUSE" : 2, + "CONSUMER" : 3, + "SYS_CONTROL" : 4, + "GAMEPAD" : 5, + "DIGITIZER" : 6, + } + +# Byte count for each kind of report. Length does not include report ID in first byte. +REPORT_LENGTHS = { + "KEYBOARD" : 8, + "MOUSE" : 4, + "CONSUMER" : 2, + "SYS_CONTROL" : 1, + "GAMEPAD" : 6, + "DIGITIZER" : 5, + } + +KEYBOARD_WITH_ID = hid.ReportDescriptor( + description="KEYBOARD", + report_descriptor=bytes([ + # Regular keyboard + 0x05, 0x01, # Usage Page (Generic Desktop) + 0x09, 0x06, # Usage (Keyboard) + 0xA1, 0x01, # Collection (Application) + 0x85, REPORT_IDS["KEYBOARD"], # Report ID (1) + 0x05, 0x07, # Usage Page (Keyboard) + 0x19, 224, # Usage Minimum (224) + 0x29, 231, # Usage Maximum (231) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 0x01, # Logical Maximum (1) + 0x75, 0x01, # Report Size (1) + 0x95, 0x08, # Report Count (8) + 0x81, 0x02, # Input (Data, Variable, Absolute) + 0x81, 0x01, # Input (Constant) + 0x19, 0x00, # Usage Minimum (0) + 0x29, 101, # Usage Maximum (101) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 101, # Logical Maximum (101) + 0x75, 0x08, # Report Size (8) + 0x95, 0x06, # Report Count (6) + 0x81, 0x00, # Input (Data, Array) + 0x05, 0x08, # Usage Page (LED) + 0x19, 0x01, # Usage Minimum (1) + 0x29, 0x05, # Usage Maximum (5) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 0x01, # Logical Maximum (1) + 0x75, 0x01, # Report Size (1) + 0x95, 0x05, # Report Count (5) + 0x91, 0x02, # Output (Data, Variable, Absolute) + 0x95, 0x03, # Report Count (3) + 0x91, 0x01, # Output (Constant) + 0xC0, # End Collection + ])) + +MOUSE_WITH_ID = hid.ReportDescriptor( + description="MOUSE", + report_descriptor=bytes([ + # Regular mouse + 0x05, 0x01, # Usage Page (Generic Desktop) + 0x09, 0x02, # Usage (Mouse) + 0xA1, 0x01, # Collection (Application) + 0x09, 0x01, # Usage (Pointer) + 0xA1, 0x00, # Collection (Physical) + 0x85, REPORT_IDS["MOUSE"], # Report ID (n) + 0x05, 0x09, # Usage Page (Button) + 0x19, 0x01, # Usage Minimum (0x01) + 0x29, 0x05, # Usage Maximum (0x05) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 0x01, # Logical Maximum (1) + 0x95, 0x05, # Report Count (5) + 0x75, 0x01, # Report Size (1) + 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x01, # Report Count (1) + 0x75, 0x03, # Report Size (3) + 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, # Usage Page (Generic Desktop Ctrls) + 0x09, 0x30, # Usage (X) + 0x09, 0x31, # Usage (Y) + 0x15, 0x81, # Logical Minimum (-127) + 0x25, 0x7F, # Logical Maximum (127) + 0x75, 0x08, # Report Size (8) + 0x95, 0x02, # Report Count (2) + 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x38, # Usage (Wheel) + 0x15, 0x81, # Logical Minimum (-127) + 0x25, 0x7F, # Logical Maximum (127) + 0x75, 0x08, # Report Size (8) + 0x95, 0x01, # Report Count (1) + 0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, # End Collection + 0xC0, # End Collection + ])) + +CONSUMER_WITH_ID = hid.ReportDescriptor( + description="CONSUMER", + report_descriptor=bytes([ + # Consumer ("multimedia") keys + 0x05, 0x0C, # Usage Page (Consumer) + 0x09, 0x01, # Usage (Consumer Control) + 0xA1, 0x01, # Collection (Application) + 0x85, REPORT_IDS["CONSUMER"], # Report ID (n) + 0x75, 0x10, # Report Size (16) + 0x95, 0x01, # Report Count (1) + 0x15, 0x01, # Logical Minimum (1) + 0x26, 0x8C, 0x02, # Logical Maximum (652) + 0x19, 0x01, # Usage Minimum (Consumer Control) + 0x2A, 0x8C, 0x02, # Usage Maximum (AC Send) + 0x81, 0x00, # Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, # End Collection + ])) + +SYS_CONTROL_WITH_ID = hid.ReportDescriptor( + description="SYS_CONTROL", + report_descriptor=bytes([ + # Power controls + 0x05, 0x01, # Usage Page (Generic Desktop Ctrls) + 0x09, 0x80, # Usage (Sys Control) + 0xA1, 0x01, # Collection (Application) + 0x85, REPORT_IDS["SYS_CONTROL"], # Report ID (n) + 0x75, 0x02, # Report Size (2) + 0x95, 0x01, # Report Count (1) + 0x15, 0x01, # Logical Minimum (1) + 0x25, 0x03, # Logical Maximum (3) + 0x09, 0x82, # Usage (Sys Sleep) + 0x09, 0x81, # Usage (Sys Power Down) + 0x09, 0x83, # Usage (Sys Wake Up) + 0x81, 0x60, # Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State) + 0x75, 0x06, # Report Size (6) + 0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, # End Collection + ])) + +GAMEPAD_WITH_ID = hid.ReportDescriptor( + description="GAMEPAD", + report_descriptor=bytes([ + # Gamepad with 16 buttons and two joysticks + 0x05, 0x01, # Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, # Usage (Game Pad) + 0xA1, 0x01, # Collection (Application) + 0x85, REPORT_IDS["GAMEPAD"], # Report ID (n) + 0x05, 0x09, # Usage Page (Button) + 0x19, 0x01, # Usage Minimum (Button 1) + 0x29, 0x10, # Usage Maximum (Button 16) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 0x01, # Logical Maximum (1) + 0x75, 0x01, # Report Size (1) + 0x95, 0x10, # Report Count (16) + 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, # Usage Page (Generic Desktop Ctrls) + 0x15, 0x81, # Logical Minimum (-127) + 0x25, 0x7F, # Logical Maximum (127) + 0x09, 0x30, # Usage (X) + 0x09, 0x31, # Usage (Y) + 0x09, 0x32, # Usage (Z) + 0x09, 0x35, # Usage (Rz) + 0x75, 0x08, # Report Size (8) + 0x95, 0x04, # Report Count (4) + 0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, # End Collection + ])) + +DIGITIZER_WITH_ID = hid.ReportDescriptor( + description="DIGITIZER", + report_descriptor=bytes([ + # Digitizer (used as an absolute pointer) + 0x05, 0x0D, # Usage Page (Digitizers) + 0x09, 0x02, # Usage (Pen) + 0xA1, 0x01, # Collection (Application) + 0x85, REPORT_IDS["DIGITIZER"], # Report ID (n) + 0x09, 0x01, # Usage (Stylus) + 0xA1, 0x00, # Collection (Physical) + 0x09, 0x32, # Usage (In-Range) + 0x09, 0x42, # Usage (Tip Switch) + 0x09, 0x44, # Usage (Barrel Switch) + 0x09, 0x45, # Usage (Eraser Switch) + 0x15, 0x00, # Logical Minimum (0) + 0x25, 0x01, # Logical Maximum (1) + 0x75, 0x01, # Report Size (1) + 0x95, 0x04, # Report Count (4) + 0x81, 0x02, # Input (Data,Var,Abs) + 0x75, 0x04, # Report Size (4) -- Filler + 0x95, 0x01, # Report Count (1) -- Filler + 0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, # Usage Page (Generic Desktop Ctrls) + 0x15, 0x00, # Logical Minimum (0) + 0x26, 0xff, 0x7f, # Logical Maximum (32767) + 0x09, 0x30, # Usage (X) + 0x09, 0x31, # Usage (Y) + 0x75, 0x10, # Report Size (16) + 0x95, 0x02, # Report Count (2) + 0x81, 0x02, # Input (Data,Var,Abs) + 0xC0, # End Collection + 0xC0, # End Collection + ])) + +# Byte count for each kind of report. Length does not include report ID in first byte. +REPORT_DESCRIPTORS = { + "KEYBOARD" : KEYBOARD_WITH_ID, + "MOUSE" : MOUSE_WITH_ID, + "CONSUMER" : CONSUMER_WITH_ID, + "SYS_CONTROL" : SYS_CONTROL_WITH_ID, + "GAMEPAD" : GAMEPAD_WITH_ID, + "DIGITIZER" : DIGITIZER_WITH_ID, + } diff --git a/tools/usb_descriptor b/tools/usb_descriptor index 0ccd1935d666b..2507847031a03 160000 --- a/tools/usb_descriptor +++ b/tools/usb_descriptor @@ -1 +1 @@ -Subproject commit 0ccd1935d666bcffc3fd5941ba06bd9273d72e0c +Subproject commit 2507847031a0395465956539253cbfa27f87511e
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: