summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-09-03 14:44:46 -0400
committerDan Halbert <halbert@halwitz.org>2019-09-03 14:44:46 -0400
commit42f5edbd331b27c7096f57da2affd7561287c17f (patch)
treea7d86861f2b2e64ea673ec658f503eb8857d15e8 /tools
parent1d973a08038148ce20aaa43863721df6328318b7 (diff)
WIP
Diffstat (limited to 'tools')
-rw-r--r--tools/gen_usb_descriptor.py79
-rw-r--r--tools/hid_report_descriptors.py60
2 files changed, 120 insertions, 19 deletions
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 10bbf5066..f782f9afc 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -8,6 +8,15 @@ sys.path.append("../../tools/usb_descriptor")
from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util
import hid_report_descriptors
+ALL_DEVICES='CDC,MSC,AUDIO,HID'
+ALL_DEVICES_SET=frozenset(ALL_DEVICES.split(','))
+DEFAULT_DEVICES='CDC,MSC,AUDIO,HID'
+
+ALL_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD'
+ALL_HID_DEVICES_SET=frozenset(ALL_HID_DEVICES.split(','))
+# Digitizer works on Linux but conflicts with mouse, so omit it.
+DEFAULT_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,GAMEPAD'
+
parser = argparse.ArgumentParser(description='Generate USB descriptors.')
parser.add_argument('--manufacturer', type=str,
help='manufacturer of the device')
@@ -19,11 +28,24 @@ 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('--devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_DEVICES,
+ help='devices to include in descriptor (AUDIO includes MIDI support)')
+parser.add_argument('--hid_devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_HID_DEVICES,
+ help='HID devices to include in HID report descriptor')
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()
+unknown_devices = list(args.devices - ALL_DEVICES_SET)
+if unknown_devices:
+ raise ValueError("Unknown device(s)", unknown_devices)
+
+unknown_hid_devices = list(args.hid_devices - ALL_HID_DEVICES_SET)
+if unknown_hid_devices:
+ raise ValueError("Unknown HID devices(s)", unknown_hid_devices)
+
+
class StringIndex:
"""Assign a monotonically increasing index to each unique string. Start with 0."""
string_to_index = {}
@@ -138,16 +160,27 @@ msc_interfaces = [
)
]
-# 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(
+# Sort by Report ID for consistency.
+hid_devices = sorted(args.hid_devices, key=lambda name: hid_report_descriptors.REPORT_IDS[name])
+
+# When there's only one hid_device, it can't be in a composite descriptor.
+# It has no report id (indicated by 0), so remove the existing one.
+
+#if len(hid_devices) == 1:
+if False:
+ name = hid_devices[0]
+ combined_hid_report_descriptor = hid.ReportDescriptor(
+ description=name,
+ report_descriptor=hid_report_descriptors.remove_report_id(
+ hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor))
+ hid_report_ids_dict = { name : 0 }
+else:
+ 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_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())
@@ -271,19 +304,27 @@ cdc_iad = standard.InterfaceAssociationDescriptor(
bFunctionProtocol=cdc.CDC_PROTOCOL_NONE)
descriptor_list = []
-descriptor_list.append(cdc_iad)
-descriptor_list.extend(cdc_interfaces)
-descriptor_list.extend(msc_interfaces)
-# Only add the control interface because other audio interfaces are managed by it to ensure the
-# correct ordering.
-descriptor_list.append(audio_control_interface)
-# Put the CDC IAD just before the CDC interfaces.
-# There appears to be a bug in the Windows composite USB driver that requests the
-# HID report descriptor with the wrong interface number if the HID interface is not given
-# first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
-# the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
-# there for backwards compatibility.
-descriptor_list.extend(hid_interfaces)
+
+if 'CDC' in args.devices:
+ # Put the CDC IAD just before the CDC interfaces.
+ # There appears to be a bug in the Windows composite USB driver that requests the
+ # HID report descriptor with the wrong interface number if the HID interface is not given
+ # first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
+ # the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
+ # there for backwards compatibility.
+ descriptor_list.append(cdc_iad)
+ descriptor_list.extend(cdc_interfaces)
+
+if 'MSC' in args.devices:
+ descriptor_list.extend(msc_interfaces)
+
+if 'AUDIO' in args.devices:
+ # Only add the control interface because other audio interfaces are managed by it to ensure the
+ # correct ordering.
+ descriptor_list.append(audio_control_interface)
+
+if 'HID' in args.devices:
+ descriptor_list.extend(hid_interfaces)
configuration = standard.ConfigurationDescriptor(
description="Composite configuration",
diff --git a/tools/hid_report_descriptors.py b/tools/hid_report_descriptors.py
index f3b28ebcf..4902657af 100644
--- a/tools/hid_report_descriptors.py
+++ b/tools/hid_report_descriptors.py
@@ -31,6 +31,11 @@ HID specific descriptors
from adafruit_usb_descriptor import hid
+def remove_report_id(report_descriptor_bytes):
+ #return report_descriptor_bytes
+ report_id_pos = report_descriptor_bytes.index(0x85)
+ return report_descriptor_bytes[:report_id_pos] + report_descriptor_bytes[report_id_pos + 2:]
+
REPORT_IDS = {
"KEYBOARD" : 1,
"MOUSE" : 2,
@@ -38,6 +43,9 @@ REPORT_IDS = {
"SYS_CONTROL" : 4,
"GAMEPAD" : 5,
"DIGITIZER" : 6,
+ "XAC_COMPATIBLE_GAMEPAD" : 7,
+ # RAW must not have a report ID, so it can't be used with other devices.
+ "RAW" : 0,
}
# Byte count for each kind of report. Length does not include report ID in first byte.
@@ -48,6 +56,8 @@ REPORT_LENGTHS = {
"SYS_CONTROL" : 1,
"GAMEPAD" : 6,
"DIGITIZER" : 5,
+ "XAC_COMPATIBLE_GAMEPAD" : 3,
+ "RAW" : 64,
}
KEYBOARD_WITH_ID = hid.ReportDescriptor(
@@ -228,6 +238,54 @@ DIGITIZER_WITH_ID = hid.ReportDescriptor(
0xC0, # End Collection
]))
+XAC_COMPATIBLE_GAMEPAD_WITH_ID = hid.ReportDescriptor(
+ description="XAC",
+ report_descriptor=bytes([
+ # This descriptor mimics the simple joystick from PDP that the XBox likes
+ 0x05, 0x01, # Usage Page (Desktop),
+ 0x09, 0x05, # Usage (Gamepad),
+ 0xA1, 0x01, # Collection (Application),
+ 0x85, REPORT_IDS["XAC_COMPATIBLE_GAMEPAD"], # Report ID (n)
+ 0x15, 0x00, # Logical Minimum (0),
+ 0x25, 0x01, # Logical Maximum (1),
+ 0x35, 0x00, # Physical Minimum (0),
+ 0x45, 0x01, # Physical Maximum (1),
+ 0x75, 0x01, # Report Size (1),
+ 0x95, 0x08, # Report Count (8),
+ 0x05, 0x09, # Usage Page (Button),
+ 0x19, 0x01, # Usage Minimum (01h),
+ 0x29, 0x08, # Usage Maximum (08h),
+ 0x81, 0x02, # Input (Variable),
+ 0x05, 0x01, # Usage Page (Desktop),
+ 0x26, 0xFF, 0x00, # Logical Maximum (255),
+ 0x46, 0xFF, 0x00, # Physical Maximum (255),
+ 0x09, 0x30, # Usage (X),
+ 0x09, 0x31, # Usage (Y),
+ 0x75, 0x08, # Report Size (8),
+ 0x95, 0x02, # Report Count (2),
+ 0x81, 0x02, # Input (Variable),
+ 0xC0 # End Collection
+ ]))
+
+RAW = hid.ReportDescriptor(
+ description="RAW",
+ report_descriptor=bytes([
+ # Provide vendor-defined
+ 0x06, 0xAF, 0xFF, # Usage Page (Vendor 0xFFAF "Adafruit"),
+ 0x09, 0xAF, # Usage (AF),
+ 0xA1, 0x01, # Collection (Application),
+ 0x75, 0x08, # Report Size (8),
+ 0x15, 0x00, # Logical Minimum (0),
+ 0x26, 0xFF, 0x00 # Logical Maximum (255),
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x01 # Usage(xxx)
+ 0x81, 0x02 # Input (Variable)
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x02, # Usage(xxx)
+ 0x91, 0x02, # Input (Variable)
+ 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,
@@ -236,4 +294,6 @@ REPORT_DESCRIPTORS = {
"SYS_CONTROL" : SYS_CONTROL_WITH_ID,
"GAMEPAD" : GAMEPAD_WITH_ID,
"DIGITIZER" : DIGITIZER_WITH_ID,
+ "XAC_COMPATIBLE_GAMEPAD" : XAC_COMPATIBLE_GAMEPAD_WITH_ID,
+ "RAW" : RAW_WITH_ID,
}