|
8 | 8 | from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util |
9 | 9 | import hid_report_descriptors |
10 | 10 |
|
| 11 | +ALL_DEVICES='CDC,MSC,AUDIO,HID' |
| 12 | +ALL_DEVICES_SET=frozenset(ALL_DEVICES.split(',')) |
| 13 | +DEFAULT_DEVICES='CDC,MSC,AUDIO,HID' |
| 14 | + |
| 15 | +ALL_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD' |
| 16 | +ALL_HID_DEVICES_SET=frozenset(ALL_HID_DEVICES.split(',')) |
| 17 | +# Digitizer works on Linux but conflicts with mouse, so omit it. |
| 18 | +DEFAULT_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,GAMEPAD' |
| 19 | + |
11 | 20 | parser = argparse.ArgumentParser(description='Generate USB descriptors.') |
12 | 21 | parser.add_argument('--manufacturer', type=str, |
13 | 22 | help='manufacturer of the device') |
|
19 | 28 | help='product id') |
20 | 29 | parser.add_argument('--serial_number_length', type=int, default=32, |
21 | 30 | help='length needed for the serial number in digits') |
| 31 | +parser.add_argument('--devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_DEVICES, |
| 32 | + help='devices to include in descriptor (AUDIO includes MIDI support)') |
| 33 | +parser.add_argument('--hid_devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_HID_DEVICES, |
| 34 | + help='HID devices to include in HID report descriptor') |
22 | 35 | parser.add_argument('--output_c_file', type=argparse.FileType('w'), required=True) |
23 | 36 | parser.add_argument('--output_h_file', type=argparse.FileType('w'), required=True) |
24 | 37 |
|
25 | 38 | args = parser.parse_args() |
26 | 39 |
|
| 40 | +unknown_devices = list(args.devices - ALL_DEVICES_SET) |
| 41 | +if unknown_devices: |
| 42 | + raise ValueError("Unknown device(s)", unknown_devices) |
| 43 | + |
| 44 | +unknown_hid_devices = list(args.hid_devices - ALL_HID_DEVICES_SET) |
| 45 | +if unknown_hid_devices: |
| 46 | + raise ValueError("Unknown HID devices(s)", unknown_hid_devices) |
| 47 | + |
| 48 | + |
27 | 49 | class StringIndex: |
28 | 50 | """Assign a monotonically increasing index to each unique string. Start with 0.""" |
29 | 51 | string_to_index = {} |
@@ -138,16 +160,27 @@ def strings_in_order(cls): |
138 | 160 | ) |
139 | 161 | ] |
140 | 162 |
|
141 | | -# Include only these HID devices. |
142 | | -# DIGITIZER works on Linux but conflicts with MOUSE, so leave it out for now. |
143 | | -hid_devices = ("KEYBOARD", "MOUSE", "CONSUMER", "GAMEPAD") |
144 | | - |
145 | | -combined_hid_report_descriptor = hid.ReportDescriptor( |
| 163 | +# Sort by Report ID for consistency. |
| 164 | +hid_devices = sorted(args.hid_devices, key=lambda name: hid_report_descriptors.REPORT_IDS[name]) |
| 165 | + |
| 166 | +# When there's only one hid_device, it can't be in a composite descriptor. |
| 167 | +# It has no report id (indicated by 0), so remove the existing one. |
| 168 | + |
| 169 | +#if len(hid_devices) == 1: |
| 170 | +if False: |
| 171 | + name = hid_devices[0] |
| 172 | + combined_hid_report_descriptor = hid.ReportDescriptor( |
| 173 | + description=name, |
| 174 | + report_descriptor=hid_report_descriptors.remove_report_id( |
| 175 | + hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor)) |
| 176 | + hid_report_ids_dict = { name : 0 } |
| 177 | +else: |
| 178 | + combined_hid_report_descriptor = hid.ReportDescriptor( |
146 | 179 | description="MULTIDEVICE", |
147 | 180 | report_descriptor=b''.join( |
148 | 181 | hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor for name in hid_devices )) |
| 182 | + hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices } |
149 | 183 |
|
150 | | -hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices } |
151 | 184 | hid_report_lengths_dict = { name: hid_report_descriptors.REPORT_LENGTHS[name] for name in hid_devices } |
152 | 185 | hid_max_report_length = max(hid_report_lengths_dict.values()) |
153 | 186 |
|
@@ -271,19 +304,27 @@ def strings_in_order(cls): |
271 | 304 | bFunctionProtocol=cdc.CDC_PROTOCOL_NONE) |
272 | 305 |
|
273 | 306 | descriptor_list = [] |
274 | | -descriptor_list.append(cdc_iad) |
275 | | -descriptor_list.extend(cdc_interfaces) |
276 | | -descriptor_list.extend(msc_interfaces) |
277 | | -# Only add the control interface because other audio interfaces are managed by it to ensure the |
278 | | -# correct ordering. |
279 | | -descriptor_list.append(audio_control_interface) |
280 | | -# Put the CDC IAD just before the CDC interfaces. |
281 | | -# There appears to be a bug in the Windows composite USB driver that requests the |
282 | | -# HID report descriptor with the wrong interface number if the HID interface is not given |
283 | | -# first. However, it still fetches the descriptor anyway. We could reorder the interfaces but |
284 | | -# the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it |
285 | | -# there for backwards compatibility. |
286 | | -descriptor_list.extend(hid_interfaces) |
| 307 | + |
| 308 | +if 'CDC' in args.devices: |
| 309 | + # Put the CDC IAD just before the CDC interfaces. |
| 310 | + # There appears to be a bug in the Windows composite USB driver that requests the |
| 311 | + # HID report descriptor with the wrong interface number if the HID interface is not given |
| 312 | + # first. However, it still fetches the descriptor anyway. We could reorder the interfaces but |
| 313 | + # the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it |
| 314 | + # there for backwards compatibility. |
| 315 | + descriptor_list.append(cdc_iad) |
| 316 | + descriptor_list.extend(cdc_interfaces) |
| 317 | + |
| 318 | +if 'MSC' in args.devices: |
| 319 | + descriptor_list.extend(msc_interfaces) |
| 320 | + |
| 321 | +if 'AUDIO' in args.devices: |
| 322 | + # Only add the control interface because other audio interfaces are managed by it to ensure the |
| 323 | + # correct ordering. |
| 324 | + descriptor_list.append(audio_control_interface) |
| 325 | + |
| 326 | +if 'HID' in args.devices: |
| 327 | + descriptor_list.extend(hid_interfaces) |
287 | 328 |
|
288 | 329 | configuration = standard.ConfigurationDescriptor( |
289 | 330 | description="Composite configuration", |
|
0 commit comments