@@ -53,14 +53,18 @@ static const uint8_t usb_hid_descriptor_template[] = {
5353
5454// Is the HID device enabled?
5555bool usb_hid_enabled ;
56- mp_obj_t usb_hid_devices ;
56+ supervisor_allocation * combined_hid_report_descriptor_allocation ;
57+ supervisor_allocation * devices_allocation ;
5758
59+
60+ // This is the interface descriptor, not the report descriptor.
5861size_t usb_hid_descriptor_length (void ) {
5962 return sizeof (usb_hid_descriptor );
6063}
6164
62- static const char [] usb_hid_interface_name = USB_INTERFACE_NAME " Mass Storage " ;
65+ static const char [] usb_hid_interface_name = USB_INTERFACE_NAME " HID " ;
6366
67+ // This is the interface descriptor, nto the report descriptor.
6468size_t usb_hid_add_descriptor (uint8_t * descriptor_buf , uint8_t * current_interface , uint8_t * current_endpoint , uint8_t * current_interface_string , uint16_t report_descriptor_length ) {
6569 memcpy (descriptor_buf , usb_hid_descriptor_template , sizeof (usb_hid_descriptor_template ));
6670
@@ -74,23 +78,79 @@ size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfac
7478 return sizeof (usb_hid_descriptor_template );
7579}
7680
77- void usb_hid_build_report_descriptor () {
78- }
79-
80- bool common_hal_usb_hid_configure_usb (mp_obj_t devices ) {
81+ usb_hid_configure_status common_hal_usb_hid_configure_usb (mp_obj_t devices ) {
8182 // We can't change the devices once we're connected.
8283 if (tud_connected ()) {
83- return false ;
84+ return USB_CONFIG_TOO_LATE ;
8485 }
8586
8687 // Assume no devices to start.
8788 usb_hid_enabled = false;
8889 if (devices == mp_const_none ) {
89- return true ;
90+ return USB_CONFIG_OK ;
9091 }
91- }
9292
93- void usb_hid_build_report
93+ size_t total_report_descriptors_length = 0 ;
94+
95+ // Build a combined report descriptor
96+
97+ mp_int_t len = mp_obj_get_int (mp_obj_len (devices ));
98+
99+ // First get the total size.
100+ for (size_t i = 0 ; i < len ; i ++ ) {
101+ mp_obj_t item = mp_obj_subscr (devices , mp_obj_new_small_int (i ), MP_OBJ_SENTINEL );
102+ if (!MP_OBJ_IS_TYPE (item , & usb_hid_device_type )) {
103+ return USB_CONFIG_NON_DEVICE ; for (size_t i = 0 ; i < len ; i ++ ) {
104+ mp_obj_t item = (devices , mp_obj_new_small_int (i ), MP_OBJ_SENTINEL );
105+ if (!MP_OBJ_IS_TYPE (item , & usb_hid_device_type )) {
106+ return USB_CONFIG_NON_DEVICE ;
107+ }
108+ total_report_descriptors_length += device -> report_descriptor_length ;
109+ }
110+
111+ }
112+ total_report_descriptors_length += device -> report_descriptor_length ;
113+ }
114+ if (len == 1 ) {
115+ // Don't need space for a report id if there's only one device.
116+ total_report_descriptors_length -= 2 ;
117+ }
118+
119+ // Allocate storage that persists across VMs to build the combined descriptor
120+ // and to remember the device details.
121+
122+ // allocate_memory(length, highaddress=false, movable=true)
123+ combined_hid_report_descriptor_allocation = allocate_memory (total_report_descriptors_length , false, true);
124+
125+ devices_allocation = allocate_memory (sizeof (usb_hid_device_obj_t ) * len );
126+ usb_hid_device_obj_t devices [] = (devices []) device_details_allocation -> ptr ;
127+
128+ uint8_t * descriptor_start = combined_hid_report_descriptor_allocation -> ptr ;
129+
130+ for (size_t i = 0 ; i < len ; i ++ ) {
131+ usb_hid_device_obj_t * device = MP_OBJ_TO_PTR (devices , mp_obj_new_small_int (i ), MP_OBJ_SENTINEL );
132+
133+ // Copy the report descriptor for this device.
134+ if (len == 1 ) {
135+ // Theres only one device, so it shouldn't have a report ID.
136+ // Copy the descriptor, but splice out the report id indicator and value (2 bytes).
137+ memcpy (descriptor_start , device -> descriptor , device -> report_id_index - 1 );
138+ descriptor_start += device -> report_id_index - 1 ;
139+ memcpy (descriptor_start , device -> descriptor + device -> report_id_index + 1 ,
140+ device -> report_descriptor_length - device -> report_id_index - 1 );
141+ } else {
142+ // Copy the whole descriptor and fill in the report id.
143+ memcpy (descriptor_start , device -> descriptor , device -> descriptor_len );
144+ descriptor_start [device -> report_id_index ] = i + 1 ;
145+ descriptor_start += device -> descriptor_len ;
146+ }
147+
148+ // Copy the device data and discard any descriptor-bytes object pointer.
149+ memcpy (& devices [i ], device , sizeof (usb_hid_device_obj_t ));
150+ devices [i ].descriptor_obj = mp_const_none ;
151+ }
152+
153+ }
94154
95155void usb_hid_gc_collect (void ) {
96156 // Once tud_mounted() is true, we're done with the constructed descriptors.
0 commit comments