1212ALL_DEVICES_SET = frozenset (ALL_DEVICES .split (',' ))
1313DEFAULT_DEVICES = 'CDC,MSC,AUDIO,HID'
1414
15- ALL_HID_DEVICES = 'KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD'
15+ ALL_HID_DEVICES = 'KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD,RAW '
1616ALL_HID_DEVICES_SET = frozenset (ALL_HID_DEVICES .split (',' ))
1717# Digitizer works on Linux but conflicts with mouse, so omit it.
1818DEFAULT_HID_DEVICES = 'KEYBOARD,MOUSE,CONSUMER,GAMEPAD'
2828 help = 'product id' )
2929parser .add_argument ('--serial_number_length' , type = int , default = 32 ,
3030 help = 'length needed for the serial number in digits' )
31- parser .add_argument ('--devices' , type = lambda l : frozenset (l .split (',' )), default = DEFAULT_DEVICES ,
31+ parser .add_argument ('--devices' , type = lambda l : tuple (l .split (',' )), default = DEFAULT_DEVICES ,
3232 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 ,
33+ parser .add_argument ('--hid_devices' , type = lambda l : tuple (l .split (',' )), default = DEFAULT_HID_DEVICES ,
3434 help = 'HID devices to include in HID report descriptor' )
3535parser .add_argument ('--output_c_file' , type = argparse .FileType ('w' ), required = True )
3636parser .add_argument ('--output_h_file' , type = argparse .FileType ('w' ), required = True )
3737
3838args = parser .parse_args ()
3939
40- unknown_devices = list (args .devices - ALL_DEVICES_SET )
40+ unknown_devices = list (frozenset ( args .devices ) - ALL_DEVICES_SET )
4141if unknown_devices :
4242 raise ValueError ("Unknown device(s)" , unknown_devices )
4343
44- unknown_hid_devices = list (args .hid_devices - ALL_HID_DEVICES_SET )
44+ unknown_hid_devices = list (frozenset ( args .hid_devices ) - ALL_HID_DEVICES_SET )
4545if unknown_hid_devices :
4646 raise ValueError ("Unknown HID devices(s)" , unknown_hid_devices )
4747
@@ -160,29 +160,27 @@ def strings_in_order(cls):
160160 )
161161]
162162
163- # Sort by Report ID for consistency.
164- hid_devices = sorted (args .hid_devices , key = lambda name : hid_report_descriptors .REPORT_IDS [name ])
163+ # When there's only one hid_device, it shouldn't have a report id.
164+ # Otherwise, report ids are assigned sequentially:
165+ # args.hid_devices[0] has report_id 1
166+ # args.hid_devices[1] has report_id 2
167+ # etc.
165168
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 ]
169+ if len (args .hid_devices ) == 1 :
170+ name = args .hid_devices [0 ]
172171 combined_hid_report_descriptor = hid .ReportDescriptor (
173172 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 }
173+ report_descriptor = bytes (hid_report_descriptors .REPORT_DESCRIPTOR_FUNCTIONS [name ](0 )))
177174else :
175+ report_id = 1
176+ concatenated_descriptors = bytearray ()
177+ for name in args .hid_devices :
178+ concatenated_descriptors .extend (
179+ bytes (hid_report_descriptors .REPORT_DESCRIPTOR_FUNCTIONS [name ](report_id )))
180+ report_id += 1
178181 combined_hid_report_descriptor = hid .ReportDescriptor (
179- description = "MULTIDEVICE" ,
180- report_descriptor = b'' .join (
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 }
183-
184- hid_report_lengths_dict = { name : hid_report_descriptors .REPORT_LENGTHS [name ] for name in hid_devices }
185- hid_max_report_length = max (hid_report_lengths_dict .values ())
182+ description = "MULTIDEVICE" ,
183+ report_descriptor = bytes (concatenated_descriptors ))
186184
187185# ASF4 expects keyboard and generic devices to have both in and out endpoints,
188186# and will fail (possibly silently) if both are not supplied.
@@ -343,6 +341,8 @@ def strings_in_order(cls):
343341c_file .write ("""\
344342 #include <stdint.h>
345343
344+ #include "py/objtuple.h"
345+ #include "shared-bindings/usb_hid/Device.h"
346346#include "{H_FILE_NAME}"
347347
348348""" .format (H_FILE_NAME = h_file .name ))
@@ -461,7 +461,9 @@ def strings_in_order(cls):
461461uint16_t usb_serial_number[{serial_number_length}];
462462uint16_t const * const string_desc_arr [{string_descriptor_length}];
463463
464- const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
464+ const uint8_t hid_report_descriptor[{hid_report_descriptor_length}];
465+
466+ #define USB_HID_NUM_DEVICES {hid_num_devices}
465467
466468// Vendor name included in Inquiry response, max 8 bytes
467469#define CFG_TUD_MSC_VENDOR "{msc_vendor}"
@@ -475,44 +477,67 @@ def strings_in_order(cls):
475477 configuration_length = descriptor_length ,
476478 max_configuration_length = max (hid_descriptor_length , descriptor_length ),
477479 string_descriptor_length = len (pointers_to_strings ),
478- HID_REPORT_DESCRIPTOR_LENGTH = len (bytes (combined_hid_report_descriptor )),
480+ hid_report_descriptor_length = len (bytes (combined_hid_report_descriptor )),
481+ hid_num_devices = len (args .hid_devices ),
479482 msc_vendor = args .manufacturer [:8 ],
480483 msc_product = args .product [:16 ]))
481484
482- # #define the report ID's used in the combined HID descriptor
483- for name , id in hid_report_ids_dict .items ():
484- h_file .write ("""\
485- #define USB_HID_REPORT_ID_{name} {id}
486- """ .format (name = name ,
487- id = id ))
488-
489- h_file .write ("\n " )
490-
491- # #define the report sizes used in the combined HID descriptor
492- for name , length in hid_report_lengths_dict .items ():
493- h_file .write ("""\
494- #define USB_HID_REPORT_LENGTH_{name} {length}
495- """ .format (name = name ,
496- length = length ))
497-
498- h_file .write ("\n " )
499-
500- h_file .write ("""\
501- #define USB_HID_NUM_DEVICES {num_devices}
502- #define USB_HID_MAX_REPORT_LENGTH {max_length}
503- """ .format (num_devices = len (hid_report_lengths_dict ),
504- max_length = hid_max_report_length ))
505-
506-
507-
508485# Write out the report descriptor and info
509486c_file .write ("""\
510487 const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
511488""" .format (HID_DESCRIPTOR_LENGTH = hid_descriptor_length ))
512489
513490for b in bytes (combined_hid_report_descriptor ):
514491 c_file .write ("0x{:02x}, " .format (b ))
492+ c_file .write ("""\
493+ };
494+
495+ """ )
496+
497+ # Write out USB HID report buffer definitions.
498+ for report_id , name in enumerate (args .hid_devices , start = 1 ):
499+ c_file .write ("""\
500+ static uint8_t {name}_report_buffer[{report_length}];
501+ """ .format (name = name .lower (), report_length = hid_report_descriptors .HID_DEVICE_DATA [name ].report_length ))
502+
503+ # Write out table of device objects.
515504c_file .write ("""
505+ usb_hid_device_obj_t usb_hid_devices[] = {
506+ """ );
507+ for report_id , name in enumerate (args .hid_devices , start = 1 ):
508+ device_data = hid_report_descriptors .HID_DEVICE_DATA [name ]
509+ c_file .write ("""\
510+ {{
511+ .base = {{ .type = &usb_hid_device_type }},
512+ .report_buffer = {name}_report_buffer,
513+ .report_id = {report_id:},
514+ .report_length = {report_length},
515+ .usage_page = {usage_page:#04x},
516+ .usage = {usage:#04x},
517+ }},
518+ """ .format (name = name .lower (), report_id = report_id ,
519+ report_length = device_data .report_length ,
520+ usage_page = device_data .usage_page ,
521+ usage = device_data .usage ))
522+ c_file .write ("""\
523+ };
524+ """ )
525+
526+ # Write out tuple of device objects.
527+ c_file .write ("""
528+ mp_obj_tuple_t common_hal_usb_hid_devices = {{
529+ .base = {{
530+ .type = &mp_type_tuple,
531+ }},
532+ .len = {num_devices},
533+ .items = {{
534+ """ .format (num_devices = len (args .hid_devices )))
535+ for idx in range (len (args .hid_devices )):
536+ c_file .write ("""\
537+ (mp_obj_t) &usb_hid_devices[{idx}],
538+ """ .format (idx = idx ))
539+ c_file .write ("""\
540+ },
516541};
517542""" )
518543
0 commit comments