@@ -45,7 +45,6 @@ static volatile uint_fast8_t gpio_irq_consumer = 0;
4545// SETTINGS
4646volatile bool xlat_initialized = false;
4747static xlat_mode_t xlat_mode = XLAT_MODE_CLICK ;
48- static bool hid_using_reportid = false;
4948static bool auto_trigger_level_high = false;
5049
5150// The Razer optical switches will constantly trigger the GPIO interrupt, while pressed
@@ -66,9 +65,13 @@ static TimerHandle_t xlat_timer_handle;
6665///////////////////////
6766
6867// Locations of the clicks and X Y motion bytes in the HID report
69- hid_data_location_t button_location ;
70- hid_data_location_t x_location ;
71- hid_data_location_t y_location ;
68+ #define REPORT_LEN 64
69+ uint8_t prev_report [REPORT_LEN ];
70+ uint8_t button_mask [REPORT_LEN ];
71+ uint8_t motion_mask [REPORT_LEN ];
72+ uint16_t button_bits ;
73+ uint16_t motion_bits ;
74+ uint8_t report_id ;
7275
7376static inline void hidreport_print_item (HID_ReportItem_t * item )
7477{
@@ -157,39 +160,39 @@ static inline void hidreport_print_item(HID_ReportItem_t *item)
157160
158161static void hidreport_check_item (HID_ReportItem_t * item )
159162{
160- switch (item -> Attributes .Usage .Page ) {
161- case 0x01 :
162- switch (item -> Attributes .Usage .Usage ) {
163- case 0x30 :
164- printf (" Usage.Usage: X (0x0030)\n" );
165- if (!x_location .found ) {
166- x_location .found = true;
167- x_location .bit_index = item -> BitOffset ;
168- x_location .bit_size = item -> Attributes .BitSize ;
169- }
170- break ;
163+ if (item -> ItemType != HID_REPORT_ITEM_In ) {
164+ return ;
165+ }
171166
172- case 0x31 :
173- printf (" Usage.Usage: Y (0x0031)\n" );
174- if (!y_location .found ) {
175- y_location .found = true;
176- y_location .bit_index = item -> BitOffset ;
177- y_location .bit_size = item -> Attributes .BitSize ;
178- }
179- break ;
180- }
181- break ;
167+ uint8_t * mask = NULL ;
168+ uint16_t * bits = NULL ;
182169
183- case 0x09 :
184- printf (" Usage.Page: Button (0x0009)\n" );
185- if (!button_location .found ) {
186- button_location .found = true;
187- button_location .bit_index = item -> BitOffset ;
188- }
189- break ;
170+ if (item -> Attributes .Usage .Page == 0x0009 ) {
171+ mask = button_mask ;
172+ bits = & button_bits ;
173+ }
174+ if ((item -> Attributes .Usage .Page == 0x0001 ) &&
175+ ((item -> Attributes .Usage .Usage == 0x0030 ) || (item -> Attributes .Usage .Usage == 0x0031 ))) {
176+ mask = motion_mask ;
177+ bits = & motion_bits ;
178+ }
190179
191- default :
192- break ;
180+ if (mask != NULL ) {
181+ if (report_id == 0 ) {
182+ report_id = item -> ReportID ;
183+ }
184+ if (report_id != item -> ReportID ) {
185+ return ;
186+ }
187+ for (uint8_t i = 0 ; i < item -> Attributes .BitSize ; i ++ ) {
188+ int byte_no = (item -> BitOffset + i ) / 8 ;
189+ int bit_no = (item -> BitOffset + i ) % 8 ;
190+ byte_no += (report_id ? 1 : 0 );
191+ if (byte_no < sizeof (button_mask )) {
192+ mask [byte_no ] |= (1 << bit_no );
193+ (* bits )++ ;
194+ }
195+ }
193196 }
194197}
195198
@@ -253,68 +256,6 @@ static int calculate_gpio_to_usb_time(void)
253256}
254257
255258
256- static void check_offsets (void )
257- {
258- printf ("\n" );
259-
260- if (hid_using_reportid ) {
261- printf ("[*] Using reportId, so actual report data is starting at index [1]\n" );
262- }
263-
264- if (button_location .found ) {
265- if (button_location .bit_index % 8 ) {
266- printf ("[!] Button found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n" , button_location .bit_index );
267- button_location .found = false;
268- } else {
269- button_location .byte_offset = button_location .bit_index / 8 + (size_t )hid_using_reportid ;
270- printf ("[*] Button found at bit index %d, which is byte %d\n" , button_location .bit_index , button_location .bit_index / 8 );
271- printf (" Button byte offset: %d\n" , button_location .byte_offset );
272- }
273- } else {
274- button_location .found = false;
275- printf ("[x] Button not found\n" );
276- }
277-
278- // X offset has to start at a byte boundary
279- if (x_location .found ) {
280- if (x_location .bit_index % 8 ) {
281- printf ("[!] X found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n" , x_location .bit_index );
282- x_location .found = false;
283- } else {
284- x_location .byte_offset = x_location .bit_index / 8 + (size_t )hid_using_reportid ;
285- printf ("[*] X found at bit index %d, which is byte %d\n" , x_location .bit_index , x_location .bit_index / 8 );
286- printf (" X size: %d bits, %d bytes\n" , x_location .bit_size , x_location .bit_size / 8 );
287- printf (" X byte offset: %d\n" , x_location .byte_offset );
288- }
289- } else {
290- x_location .found = false;
291- printf ("[x] X not found\n" );
292- }
293-
294- // Y offset does NOT have to start at a byte boundary,
295- // but it has to be contiguous to X
296- // and their total size has to be a multiple of 8
297- if (y_location .found ) {
298- if ((y_location .bit_index % 8 ) &&
299- ((y_location .bit_index - x_location .bit_index ) != x_location .bit_size )) {
300- printf ("[!] Y found at bit index %d, which is not a multiple of 8, and not contiguous to X. Currently not supported by XLAT.\n" ,
301- y_location .bit_index );
302- y_location .found = false;
303- } else {
304- y_location .byte_offset = y_location .bit_index / 8 + (size_t )hid_using_reportid ;
305- printf ("[*] Y found at bit index %d, which is byte %d\n" , y_location .bit_index , y_location .bit_index / 8 );
306- printf (" Y size: %d bits, %d bytes\n" , y_location .bit_size , y_location .bit_size / 8 );
307- printf (" Y byte offset: %d\n" , y_location .byte_offset );
308- }
309- } else {
310- y_location .found = false;
311- printf ("[x] Y not found\n" );
312- }
313-
314- printf ("\n" );
315- }
316-
317-
318259//////////////////////
319260// PUBLIC FUNCTIONS //
320261//////////////////////
@@ -352,11 +293,10 @@ void xlat_usb_hid_event(void)
352293
353294 if (USBH_HID_GetDeviceType (phost ) == HID_MOUSE )
354295 { // if the HID is Mouse
355- uint8_t hid_raw_data [64 ];
296+ uint8_t hid_raw_data [REPORT_LEN ];
356297
357298 if (USBH_HID_GetRawData (phost , hid_raw_data ) == USBH_OK ) {
358- // check reportId for ULX
359- if (hid_using_reportid && (hid_raw_data [0 ] != 0x01 )) {
299+ if ((report_id != 0 ) && (hid_raw_data [0 ] != report_id )) {
360300 // ignore
361301 goto out ;
362302 }
@@ -368,68 +308,24 @@ void xlat_usb_hid_event(void)
368308 printf ("\n" );
369309#endif
370310 if (xlat_mode == XLAT_MODE_CLICK ) {
371- // FOR BUTTONS/CLICKS:
372- // The correct location of button data is determined by parsing the HID descriptor
373- // This information is available in the button_location struct
374-
375- // First, check if the location was found
376- if (!button_location .found ) {
377- return ;
378- }
379-
380- static uint8_t prev_button = 0 ;
381- uint8_t button = hid_raw_data [button_location .byte_offset ];
382-
383- // Check if the button state has changed
384- if (button != prev_button ) {
385- // Only measure on button PRESS, not on RELEASE
386- if (button > prev_button ) {
387- // Save the captured USB event timestamp
311+ for (uint8_t i = (report_id ? 1 : 0 ); i < REPORT_LEN ; i ++ ) {
312+ if (((hid_raw_data [i ] ^ prev_report [i ]) & hid_raw_data [i ] & button_mask [i ])) {
388313 last_usb_timestamp_us = hevt -> timestamp ;
389-
390- printf ("[%5lu] hid@%lu: " , xTaskGetTickCount (), hevt -> timestamp );
391- printf ("Button: B=0x%02x @ %lu\n" , button , hevt -> timestamp );
392-
393314 calculate_gpio_to_usb_time ();
315+ break ;
394316 }
395317 }
396-
397- // Save previous state
398- prev_button = button ;
399318 }
400319 else if (xlat_mode == XLAT_MODE_MOTION ) {
401- // FOR MOTION:
402- // The correct location of button data is determined by parsing the HID descriptor
403- // This information is available in the [x|y]_location structs
404-
405- // First, check if the locations were found
406- if ((!x_location .found ) || (!y_location .found )) {
407- return ;
408- }
409-
410- // Check X and Y data is contiguous
411- if ((x_location .byte_offset + x_location .bit_size / 8 ) != y_location .byte_offset ) {
412- return ;
413- }
414-
415- size_t start_idx = x_location .byte_offset ;
416- size_t length = (x_location .bit_size + y_location .bit_size ) / 8 ;
417-
418- // Loop over the data and check for non-zero values
419- // In case there is non-zero data, call calculate_gpio_to_usb_tine();
420- for (size_t idx = start_idx ; idx < start_idx + length ; idx ++ ) {
421- if (hid_raw_data [idx ]) {
422- // Save the captured USB event timestamp
320+ for (uint8_t i = (report_id ? 1 : 0 ); i < REPORT_LEN ; i ++ ) {
321+ if (hid_raw_data [i ] & motion_mask [i ]) {
423322 last_usb_timestamp_us = hevt -> timestamp ;
424-
425- printf ("[%5lu] hid@%lu: " , xTaskGetTickCount (), hevt -> timestamp );
426- printf ("Motion: X=0x%02x, Y=0x%02x @ %lu\n" , hid_raw_data [x_location .byte_offset ], hid_raw_data [y_location .byte_offset ], hevt -> timestamp );
427-
428323 calculate_gpio_to_usb_time ();
429- break ; // stop at the first bit of motion in this report
324+ break ;
430325 }
431326 }
432327 }
328+ memcpy (prev_report , hid_raw_data , sizeof (prev_report ));
433329 }
434330 }
435331
@@ -569,16 +465,6 @@ void xlat_reset_latency(void)
569465 }
570466}
571467
572- void xlat_set_using_reportid (bool use_reportid )
573- {
574- hid_using_reportid = use_reportid ;
575- }
576-
577- bool xlat_get_using_reportid (void )
578- {
579- return hid_using_reportid ;
580- }
581-
582468static void xlat_timer_callback (TimerHandle_t xTimer )
583469{
584470 // re-enable GPIO interrupts
@@ -651,12 +537,19 @@ void xlat_parse_hid_descriptor(uint8_t *desc, size_t desc_size)
651537 return ;
652538 }
653539
654- // Check if using reportIDs:
655- hid_using_reportid = report_info .UsingReportIDs ;
656- printf ("Using reportIDs: %d\n" , hid_using_reportid );
540+ printf ("Button mask: " );
541+ for (int i = 0 ; i < REPORT_LEN ; i ++ ) {
542+ printf ("%02x" , button_mask [i ]);
543+ }
544+ printf ("\n" );
545+ printf ("Motion mask: " );
546+ for (int i = 0 ; i < REPORT_LEN ; i ++ ) {
547+ printf ("%02x" , motion_mask [i ]);
548+ }
549+ printf ("\n" );
657550
658- // Find click and motion data offsets
659- check_offsets ( );
551+ // Check if using reportIDs:
552+ printf ( "Using report ID: %d\n" , report_id );
660553
661554 // Send a message to the gfx thread, to refresh the device info
662555 struct gfx_event * evt ;
@@ -666,33 +559,37 @@ void xlat_parse_hid_descriptor(uint8_t *desc, size_t desc_size)
666559 osMessagePut (msgQGfxTask , (uint32_t )evt , 0U );
667560}
668561
669- hid_data_location_t * xlat_get_button_location (void )
562+ uint16_t xlat_get_button_bits (void )
670563{
671- return & button_location ;
564+ return button_bits ;
672565}
673566
674- hid_data_location_t * xlat_get_x_location (void )
567+ uint16_t xlat_get_motion_bits (void )
675568{
676- return & x_location ;
569+ return motion_bits ;
677570}
678571
679- hid_data_location_t * xlat_get_y_location (void )
572+ uint16_t xlat_get_report_id (void )
680573{
681- return & y_location ;
574+ return report_id ;
682575}
683576
684577void xlat_clear_locations (void )
685578{
686579 printf ("Clearing locations\n" );
687- button_location .found = false;
688- x_location .found = false;
689- y_location .found = false;
580+ memset (prev_report , 0 , sizeof (prev_report ));
581+ memset (button_mask , 0 , sizeof (button_mask ));
582+ memset (motion_mask , 0 , sizeof (motion_mask ));
583+ button_bits = 0 ;
584+ motion_bits = 0 ;
585+ report_id = 0 ;
690586}
691587
692588void xlat_init (void )
693589{
694590 // create timer
695591 xlat_timer_handle = xTimerCreate ("xlat_timer" , pdMS_TO_TICKS (1000 ), pdFALSE , NULL , xlat_timer_callback );
592+ xlat_clear_locations ();
696593 hw_exti_interrupts_enable ();
697594 xlat_initialized = true;
698595 printf ("XLAT initialized\n" );
0 commit comments