diff --git a/config-tool-web/examples.js b/config-tool-web/examples.js index e0a208d5..d0985949 100644 --- a/config-tool-web/examples.js +++ b/config-tool-web/examples.js @@ -10066,7 +10066,701 @@ const examples = [ ], "quirks": [] } + }, + { + 'description': 'Xbox controller (Bluetooth) adapter for Switch 2', + 'config': { + "version": 17, + "unmapped_passthrough_layers": [], + "partial_scroll_timeout": 1000000, + "tap_hold_threshold": 200000, + "gpio_debounce_time_ms": 5, + "interval_override": 0, + "our_descriptor_number": 6, + "ignore_auth_dev_inputs": false, + "input_labels": 1, + "mappings": [ + { + "target_usage": "0xfff90001", + "source_usage": "0xfff50001", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90002", + "source_usage": "0xfff50002", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90003", + "source_usage": "0xfff50003", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90004", + "source_usage": "0xfff50004", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010030", + "source_usage": "0x00010030", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010031", + "source_usage": "0x00010031", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010032", + "source_usage": "0x00010032", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010035", + "source_usage": "0x00010035", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090002", + "source_usage": "0x00090001", + "source_name": "A", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090003", + "source_usage": "0x00090002", + "source_name": "B", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090001", + "source_usage": "0x00090004", + "source_name": "X", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090004", + "source_usage": "0x00090005", + "source_name": "Y", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090005", + "source_usage": "0x00090007", + "source_name": "LB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090006", + "source_usage": "0x00090008", + "source_name": "RB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090007", + "source_usage": "0xfff30002", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090008", + "source_usage": "0xfff30003", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000b", + "source_usage": "0x0009000e", + "source_name": "LSB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000c", + "source_usage": "0x0009000f", + "source_name": "RSB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090009", + "source_usage": "0x0009000b", + "source_name": "View", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000a", + "source_usage": "0x0009000c", + "source_name": "Menu", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000d", + "source_usage": "0x0009000d", + "source_name": "Guide", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + } + ], + "macros": [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ], + "expressions": [ + "/*\nXbox controllers in Bluetooth mode report dpad directions as 1..8\n(N, NE, E, SE, S, SW, W, NW) with 0 as neutral.\n*/ eol eol 0x00010039 input_state 6000 eq eol 0x00010039 input_state 7000 eq bitwise_or eol 0x00010039 input_state 8000 eq bitwise_or eol 1000 store /* left */ eol eol 0x00010039 input_state 2000 eq eol 0x00010039 input_state 3000 eq bitwise_or eol 0x00010039 input_state 4000 eq bitwise_or eol 2000 store /* right */ eol eol 0x00010039 input_state 8000 eq eol 0x00010039 input_state 1000 eq bitwise_or eol 0x00010039 input_state 2000 eq bitwise_or eol 3000 store /* up */ eol eol 0x00010039 input_state 4000 eq eol 0x00010039 input_state 5000 eq bitwise_or eol 0x00010039 input_state 6000 eq bitwise_or eol 4000 store /* down */", + "0x000200c5 input_state_scaled eol 63000 gt", + "0x000200c4 input_state_scaled eol 63000 gt", + "", + "", + "", + "", + "" + ], + "macro_entry_duration": 1, + "gpio_output_mode": 0, + "quirks": [] + } + }, + { + 'description': 'Xbox controller (USB) adapter for Switch 2', + 'config': { + "version": 17, + "unmapped_passthrough_layers": [], + "partial_scroll_timeout": 1000000, + "tap_hold_threshold": 200000, + "gpio_debounce_time_ms": 5, + "interval_override": 0, + "our_descriptor_number": 6, + "ignore_auth_dev_inputs": false, + "input_labels": 1, + "mappings": [ + { + "target_usage": "0xfff90001", + "source_usage": "0x0009000b", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90002", + "source_usage": "0x0009000c", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90003", + "source_usage": "0x00090009", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0xfff90004", + "source_usage": "0x0009000a", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010030", + "source_usage": "0x00010030", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010031", + "source_usage": "0x00010031", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010032", + "source_usage": "0x00010032", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00010035", + "source_usage": "0x00010035", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090002", + "source_usage": "0x00090005", + "source_name": "A", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090003", + "source_usage": "0x00090006", + "source_name": "B", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090001", + "source_usage": "0x00090007", + "source_name": "X", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090004", + "source_usage": "0x00090008", + "source_name": "Y", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090005", + "source_usage": "0x0009000d", + "source_name": "LB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090006", + "source_usage": "0x0009000e", + "source_name": "RB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090007", + "source_usage": "0xfff30001", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090008", + "source_usage": "0xfff30002", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000b", + "source_usage": "0x0009000f", + "source_name": "LSB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000c", + "source_usage": "0x00090010", + "source_name": "RSB", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x00090009", + "source_usage": "0x00090004", + "source_name": "View", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000a", + "source_usage": "0x00090003", + "source_name": "Menu", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + }, + { + "target_usage": "0x0009000d", + "source_usage": "0x00090011", + "source_name": "Guide", + "scaling": 1000, + "layers": [ + 0 + ], + "sticky": false, + "tap": false, + "hold": false, + "source_port": 0, + "target_port": 0 + } + ], + "macros": [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ], + "expressions": [ + "0x000200c5 input_state_scaled eol 63000 gt", + "0x000200c4 input_state_scaled eol 63000 gt", + "", + "", + "", + "", + "", + "" + ], + "macro_entry_duration": 1, + "gpio_output_mode": 0, + "quirks": [] + } } ]; -export default examples; +export default examples; \ No newline at end of file diff --git a/config-tool-web/index.html b/config-tool-web/index.html index 43d396bc..48244412 100644 --- a/config-tool-web/index.html +++ b/config-tool-web/index.html @@ -186,6 +186,7 @@

HID Remapper Configuration

+ @@ -662,4 +663,4 @@ - + \ No newline at end of file diff --git a/config-tool-web/usages.js b/config-tool-web/usages.js index 3bce62d8..6b6ca3ff 100644 --- a/config-tool-web/usages.js +++ b/config-tool-web/usages.js @@ -527,6 +527,31 @@ const usages = { "0x00090007": { 'name': 'View', 'class': 'mouse' }, "0x00090008": { 'name': 'Menu', 'class': 'mouse' }, }, + 6: { + "0x00090001": { 'name': 'B', 'class': 'mouse' }, + "0x00090002": { 'name': 'A', 'class': 'mouse' }, + "0x00090003": { 'name': 'Y', 'class': 'mouse' }, + "0x00090004": { 'name': 'X', 'class': 'mouse' }, + "0x00090005": { 'name': 'L', 'class': 'mouse' }, + "0x00090006": { 'name': 'R', 'class': 'mouse' }, + "0x00090007": { 'name': 'ZL', 'class': 'mouse' }, + "0x00090008": { 'name': 'ZR', 'class': 'mouse' }, + "0x00090009": { 'name': 'Select', 'class': 'mouse' }, + "0x0009000a": { 'name': 'Start', 'class': 'mouse' }, + "0x0009000b": { 'name': 'L3', 'class': 'mouse' }, + "0x0009000c": { 'name': 'R3', 'class': 'mouse' }, + "0x0009000d": { 'name': 'Home', 'class': 'mouse' }, + "0x0009000e": { 'name': 'Capture', 'class': 'mouse' }, + "0x0009000f": { 'name': 'Chat', 'class': 'mouse' }, + "0xfff90001": { 'name': 'D-pad left', 'class': 'mouse' }, + "0xfff90002": { 'name': 'D-pad right', 'class': 'mouse' }, + "0xfff90003": { 'name': 'D-pad up', 'class': 'mouse' }, + "0xfff90004": { 'name': 'D-pad down', 'class': 'mouse' }, + "0x00010030": { 'name': 'Left stick X', 'class': 'mouse' }, + "0x00010031": { 'name': 'Left stick Y', 'class': 'mouse' }, + "0x00010032": { 'name': 'Right stick X', 'class': 'mouse' }, + "0x00010035": { 'name': 'Right stick Y', 'class': 'mouse' }, + }, }; const common_target_usages = { @@ -645,6 +670,7 @@ Object.assign(usages[2], common_target_usages); Object.assign(usages[3], common_target_usages); Object.assign(usages[4], common_target_usages); Object.assign(usages[5], common_target_usages); +Object.assign(usages[6], common_target_usages); usages[1] = usages[0]; // absolute mouse & keyboard is the same as regular mouse & keyboard -export default usages; +export default usages; \ No newline at end of file diff --git a/firmware/src/our_descriptor.cc b/firmware/src/our_descriptor.cc index 32d8926e..73257f62 100644 --- a/firmware/src/our_descriptor.cc +++ b/firmware/src/our_descriptor.cc @@ -309,6 +309,69 @@ const uint8_t our_report_descriptor_horipad[] = { 0xC0, // End Collection }; +const uint8_t our_report_descriptor_horipad_o[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0E, // Usage Maximum (0x0E) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x01, // Physical Maximum (1) + 0x65, 0x00, // Unit (None) + 0x55, 0x00, // Unit Exponent (0) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0E, // Report Count (14) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x39, // Usage (Hat switch) + 0x25, 0x07, // Logical Maximum (7) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) + 0x25, 0x01, // Logical Maximum (1) + 0x45, 0x01, // Physical Maximum (1) + 0x65, 0x00, // Unit (None) + 0x75, 0x01, // Report Size (1) + 0x95, 0x03, // Report Count (3) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x09, 0x0F, // Usage (0x0F) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x30, // Usage (X) + 0x25, 0xFF, // Logical Maximum (255) + 0x45, 0xFF, // Physical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x31, // Usage (Y) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x32, // Usage (Z) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x35, // Usage (Rz) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x25, 0x01, // Logical Maximum (1) + 0x45, 0x01, // Physical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x0A, 0x4F, 0x48, // Usage (0x484F) + 0x25, 0xFF, // Logical Maximum (255) + 0x45, 0xFF, // Physical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x0A, 0x4F, 0x48, // Usage (0x484F) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection +}; + uint8_t const our_report_descriptor_ps4[] = { 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x05, // Usage (Game Pad) @@ -674,6 +737,16 @@ const our_descriptor_def_t our_descriptors[] = { .clear_report = xac_compat_clear_report, .default_value = ps4_stadia_default_value, // sic }, + { + .idx = 6, + .descriptor = our_report_descriptor_horipad_o, + .descriptor_length = sizeof(our_report_descriptor_horipad_o), + .vid = 0x0F0D, + .pid = 0x0202, + .handle_received_report = do_handle_received_report, + .clear_report = horipad_clear_report, + .default_value = horipad_default_value, + }, }; const uint8_t config_report_descriptor[] = { @@ -733,4 +806,4 @@ uint8_t const boot_kb_report_descriptor[] = { 0xC0, // End Collection }; -const uint32_t boot_kb_report_descriptor_length = sizeof(boot_kb_report_descriptor); +const uint32_t boot_kb_report_descriptor_length = sizeof(boot_kb_report_descriptor); \ No newline at end of file diff --git a/firmware/src/our_descriptor.h b/firmware/src/our_descriptor.h index 0bdbc8e0..359fa0e6 100644 --- a/firmware/src/our_descriptor.h +++ b/firmware/src/our_descriptor.h @@ -13,7 +13,7 @@ #define MAX_INPUT_REPORT_ID 3 -#define NOUR_DESCRIPTORS 6 +#define NOUR_DESCRIPTORS 7 typedef void (*device_connected_t)(uint16_t interface, uint16_t vid, uint16_t pid); typedef void (*device_disconnected_t)(uint8_t dev_addr);