From f18e7d6d67b9dc5d14d3d326e34e43bbf27b8ee7 Mon Sep 17 00:00:00 2001 From: whowechina Date: Sun, 12 Apr 2026 11:18:53 +0800 Subject: [PATCH] Add partial PS4 support (no auth) --- firmware/src/CMakeLists.txt | 2 +- firmware/src/commands.c | 15 +-- firmware/src/config.c | 8 +- firmware/src/config.h | 1 + firmware/src/main.c | 115 +++++++++++++++++----- firmware/src/ps4_feat.c | 174 +++++++++++++++++++++++++++++++++ firmware/src/ps4_feat.h | 14 +++ firmware/src/usb_descriptors.c | 62 ++++++++++-- firmware/src/usb_descriptors.h | 72 ++++++++++++++ 9 files changed, 426 insertions(+), 37 deletions(-) create mode 100644 firmware/src/ps4_feat.c create mode 100644 firmware/src/ps4_feat.h diff --git a/firmware/src/CMakeLists.txt b/firmware/src/CMakeLists.txt index 69b9914..952270f 100644 --- a/firmware/src/CMakeLists.txt +++ b/firmware/src/CMakeLists.txt @@ -5,7 +5,7 @@ function(make_firmware board board_def) pico_sdk_init() add_executable(${board} main.c slider.c rgb.c button.c save.c config.c commands.c - cli.c mpr121.c hebtn.c lzfx.c usb_descriptors.c) + cli.c mpr121.c hebtn.c lzfx.c usb_descriptors.c ps4_feat.c) target_compile_definitions(${board} PUBLIC ${board_def}) pico_enable_stdio_usb(${board} 1) pico_enable_stdio_uart(${board} 0) diff --git a/firmware/src/commands.c b/firmware/src/commands.c index 0d53f60..a0da068 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -62,9 +62,9 @@ static void disp_hall() static void disp_hid() { - const char *joy_map[] = {"Switch", "Steam", "Arcade"}; + const char *joy_map[] = {"Switch", "Steam", "Arcade", "PS4"}; printf("[HID]\n"); - printf(" Keymap: %s\n", joy_map[diva_cfg->hid.joy_map % 3]); + printf(" Keymap: %s\n", joy_map[diva_cfg->hid.joy_map % 4]); } void handle_display(int argc, char *argv[]) @@ -175,21 +175,24 @@ static void handle_stat(int argc, char *argv[]) static void handle_keymap(int argc, char *argv[]) { - const char *usage = "Usage: keymap \n"; + const char *usage = "Usage: keymap \n"; if (argc != 1) { printf(usage); return; } - const char *choices[] = {"switch", "steam", "arcade"}; - int match = cli_match_prefix(choices, 3, argv[0]); + const char *choices[] = {"switch", "steam", "arcade", "ps4"}; + int match = cli_match_prefix(choices, count_of(choices), argv[0]); if (match < 0) { printf(usage); return; } diva_cfg->hid.joy_map = match; - config_changed(); + disp_hid(); + save_request(true); + + printf("Please replug the controller to apply the change.\n"); } static void handle_filter(int argc, char *argv[]) diff --git a/firmware/src/config.c b/firmware/src/config.c index 91788bd..bcc8c4b 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -31,10 +31,16 @@ static diva_cfg_t default_cfg = { }, }; -diva_runtime_t diva_runtime; +diva_runtime_t diva_runtime = { + .hid_ps4 = false, +}; static void config_loaded() { + if (diva_cfg->hid.joy_map > 3) { + diva_cfg->hid.joy_map = default_cfg.hid.joy_map; + config_changed(); + } if ((diva_cfg->sense.filter & 0x0f) > 3 || ((diva_cfg->sense.filter >> 4) & 0x0f) > 3) { diva_cfg->sense.filter = default_cfg.sense.filter; diff --git a/firmware/src/config.h b/firmware/src/config.h index 4a1cef4..a514d19 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -39,6 +39,7 @@ typedef struct __attribute__((packed)) { typedef struct { bool diva_plus; + bool hid_ps4; struct { bool sensor; } debug; diff --git a/firmware/src/main.c b/firmware/src/main.c index ad966df..5cb3517 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -34,13 +34,27 @@ #include "button.h" #include "hebtn.h" #include "lzfx.h" +#include "ps4_feat.h" struct __attribute__((packed)) { uint16_t buttons; // 16 buttons; see JoystickButtons_t for bit mapping uint8_t HAT; // HAT switch; one nibble w/ unused nibble uint32_t axis; // slider touch data uint8_t VendorSpec; -} hid_joy, sent_hid_joy; +} hid_ns, sent_hid_ns; + +struct __attribute__((packed)) { + uint8_t left_x; + uint8_t left_y; + uint8_t right_x; + uint8_t right_y; + uint8_t hat_buttons; + uint8_t buttons_11_4; + uint8_t buttons_counter; + uint8_t trigger_l; + uint8_t trigger_r; + uint8_t vendor[54]; +} hid_ps4, sent_hid_ps4; void report_usb_hid() { @@ -52,14 +66,25 @@ void report_usb_hid() uint64_t now = time_us_64(); - hid_joy.HAT = 0x08; - hid_joy.VendorSpec = 0; - if ((memcmp(&hid_joy, &sent_hid_joy, sizeof(hid_joy)) != 0) || - (now - last_report_joy >= 2000)) { - if (tud_hid_report(0, &hid_joy, sizeof(hid_joy))) { - sent_hid_joy = hid_joy; + if (diva_runtime.hid_ps4) { + hid_ps4.hat_buttons = (hid_ps4.hat_buttons & 0xF0) | 0x08; + if ((memcmp(&hid_ps4, &sent_hid_ps4, sizeof(hid_ps4)) != 0) || + (now - last_report_joy >= 2000)) { + if (tud_hid_report(REPORT_ID_JOYSTICK, &hid_ps4, sizeof(hid_ps4))) { + sent_hid_ps4 = hid_ps4; + } + last_report_joy = now; + } + } else { + hid_ns.HAT = 0x08; + hid_ns.VendorSpec = 0; + if ((memcmp(&hid_ns, &sent_hid_ns, sizeof(hid_ns)) != 0) || + (now - last_report_joy >= 2000)) { + if (tud_hid_report(0, &hid_ns, sizeof(hid_ns))) { + sent_hid_ns = hid_ns; + } + last_report_joy = now; } - last_report_joy = now; } } @@ -68,38 +93,69 @@ static uint16_t unified_button_read() return button_read() | hebtn_read(); } -const static uint8_t maps[3][7] = { +const static uint8_t maps[4][7] = { { 3, 0, 1, 2, 12, 8, 9 }, { 0, 3, 2, 1, 12, 8, 9 }, // Steam { 3, 0, 1, 2, 9, 12, 8 }, // Arcade + { 0, 1, 2, 3, 12, 8, 9 }, // PS4 }; +static uint16_t mapped_buttons; + static void map_buttons() { uint16_t button = unified_button_read(); - const uint8_t *map = maps[diva_cfg->hid.joy_map % 3]; + const uint8_t *map = maps[diva_cfg->hid.joy_map % 4]; - hid_joy.buttons = 0; + mapped_buttons = 0; for (int i = 0; i < 7; i++) { - hid_joy.buttons |= (button & (1 << i)) ? (1 << map[i]) : 0; + mapped_buttons |= (button & (1 << i)) ? (1 << map[i]) : 0; } } -static void gen_joy_report() +static uint32_t touch_axis_bits() { - hid_joy.axis = 0; + uint32_t axis = 0; int zone_num = slider_zone_num(); for (int i = 0; i < zone_num; i++) { if (slider_touched(zone_num - 1 - i)) { uint32_t bits = zone_num > 16 ? (1 << i) : 0x03 << (i * 2); - hid_joy.axis |= bits; + axis |= bits; } } - hid_joy.axis ^= 0x80808080; + return axis ^ 0x80808080; +} +static void gen_ns_report() +{ + hid_ns.axis = touch_axis_bits(); + hid_ns.buttons = mapped_buttons; +} + +static void gen_ps4_report() +{ + uint16_t ps4_buttons = mapped_buttons; + + hid_ps4.left_x = 0x80; + hid_ps4.left_y = 0x80; + hid_ps4.right_x = 0x80; + hid_ps4.right_y = 0x80; + hid_ps4.hat_buttons = (ps4_buttons << 4); + hid_ps4.buttons_11_4 = ps4_buttons >> 4; + hid_ps4.buttons_counter = ps4_buttons >> 12; + hid_ps4.trigger_l = 0; + hid_ps4.trigger_r = 0; +} + +static void gen_hid_report() +{ map_buttons(); - + if (diva_runtime.hid_ps4) { + gen_ps4_report(); + } else { + gen_ns_report(); + } } static void run_lights() @@ -170,7 +226,7 @@ static void core0_loop() slider_update(); hebtn_update(); - gen_joy_report(); + gen_hid_report(); report_usb_hid(); next_frame += 1000; @@ -214,11 +270,15 @@ static void keymap_check() diva_cfg->hid.joy_map = 0; } else if (buttons == 0x02) { diva_cfg->hid.joy_map = 1; - } else if ((buttons == 0x04) || (buttons == 0x08)) { + } else if (buttons == 0x04) { diva_cfg->hid.joy_map = 2; + } else if (buttons == 0x08) { + diva_cfg->hid.joy_map = 3; } else { return; } + diva_runtime.hid_ps4 = (diva_cfg->hid.joy_map == 3); + hid_use_ps4(diva_runtime.hid_ps4); config_changed(); } @@ -230,9 +290,6 @@ void init() update_check(); - tusb_init(); - stdio_init_all(); - config_init(); mutex_init(&core1_io_lock); save_init(0xca44cafe, &core1_io_lock); @@ -247,6 +304,12 @@ void init() keymap_check(); + diva_runtime.hid_ps4 = (diva_cfg->hid.joy_map == 3); + hid_use_ps4(diva_runtime.hid_ps4); + + tusb_init(); + stdio_init_all(); + cli_init("diva_pico>", "\n << Diva Pico Controller >>\n" " https://github.com/whowechina\n\n"); @@ -268,6 +331,9 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { + if (diva_runtime.hid_ps4) { + return ps4_feat_get_report(report_id, report_type, buffer, reqlen); + } printf("Get from USB %d-%d\n", report_id, report_type); return 0; } @@ -278,6 +344,11 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { + if (diva_runtime.hid_ps4) { + ps4_feat_set_report(report_id, report_type, buffer, bufsize); + return; + } + if (report_type == HID_REPORT_TYPE_OUTPUT) { uint8_t obuf[48]; memcpy(obuf, buffer, bufsize); diff --git a/firmware/src/ps4_feat.c b/firmware/src/ps4_feat.c new file mode 100644 index 0000000..25d9756 --- /dev/null +++ b/firmware/src/ps4_feat.c @@ -0,0 +1,174 @@ +#include + +#include "ps4_feat.h" + +static const uint8_t ps4_feat_02[] = { + 0xfe, 0xff, 0x0e, 0x00, 0x04, 0x00, 0xd4, 0x22, + 0x2a, 0xdd, 0xbb, 0x22, 0x5e, 0xdd, 0x81, 0x22, + 0x84, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0x85, 0x1f, + 0xb0, 0xe0, 0xc6, 0x20, 0xb5, 0xe0, 0xb1, 0x20, + 0x83, 0xdf, 0x0c, 0x00 +}; + +static const uint8_t ps4_feat_03[] = { + 0x21, 0x27, 0x04, 0xcf, 0x00, 0x2c, 0x56, + 0x08, 0x00, 0x3d, 0x00, 0xe8, 0x03, 0x04, 0x00, + 0xff, 0x7f, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x0d, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t ps4_feat_12[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x25, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t ps4_feat_a3[] = { + 0x4a, 0x75, 0x6e, 0x20, 0x20, 0x39, 0x20, 0x32, + 0x30, 0x31, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x32, 0x3a, 0x33, 0x36, 0x3a, 0x34, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x08, 0xb4, 0x01, 0x00, 0x00, 0x00, + 0x07, 0xa0, 0x10, 0x20, 0x00, 0xa0, 0x02, 0x00 +}; + +static const uint8_t ps4_feat_f2[] = { + 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t ps4_feat_f3[] = { + 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t ps4_feat_13[22]; +static uint8_t ps4_feat_14[16]; +static uint8_t ps4_feat_15[44]; + +static uint16_t ps4_feature_size(uint8_t report_id) +{ + switch (report_id) { + case 0x02: return sizeof(ps4_feat_02); + case 0x03: return sizeof(ps4_feat_03); + case 0x08: return 3; + case 0x10: return 4; + case 0x11: return 2; + case 0x12: return sizeof(ps4_feat_12); + case 0x13: return sizeof(ps4_feat_13); + case 0x14: return sizeof(ps4_feat_14); + case 0x15: return sizeof(ps4_feat_15); + case 0x80: return 6; + case 0x81: return 6; + case 0x82: return 5; + case 0x83: return 1; + case 0x84: return 4; + case 0x85: return 6; + case 0x86: return 6; + case 0x87: return 35; + case 0x88: return 34; + case 0x89: return 2; + case 0x90: return 5; + case 0x91: return 3; + case 0x92: return 3; + case 0x93: return 12; + case 0xa0: return 6; + case 0xa1: return 1; + case 0xa2: return 1; + case 0xa3: return sizeof(ps4_feat_a3); + case 0xa4: return 13; + case 0xa5: return 21; + case 0xa6: return 21; + case 0xa7: return 1; + case 0xa8: return 1; + case 0xa9: return 8; + case 0xaa: return 1; + case 0xab: return 57; + case 0xac: return 57; + case 0xad: return 11; + case 0xaf: return 2; + case 0xb0: return 63; + case 0xf0: return 63; + case 0xf1: return 63; + case 0xf2: return sizeof(ps4_feat_f2); + case 0xf3: return sizeof(ps4_feat_f3); + default: return 0; + } +} + +static const uint8_t *ps4_feature_data(uint8_t report_id) +{ + switch (report_id) { + case 0x02: return ps4_feat_02; + case 0x03: return ps4_feat_03; + case 0x12: return ps4_feat_12; + case 0x13: return ps4_feat_13; + case 0x14: return ps4_feat_14; + case 0x15: return ps4_feat_15; + case 0xa3: return ps4_feat_a3; + case 0xf2: return ps4_feat_f2; + case 0xf3: return ps4_feat_f3; + default: return NULL; + } +} + +uint16_t ps4_feat_get_report(uint8_t report_id, hid_report_type_t report_type, + uint8_t *buffer, uint16_t reqlen) +{ + if (report_type != HID_REPORT_TYPE_FEATURE) { + memset(buffer, 0, reqlen); + return reqlen; + } + + uint16_t resp_len = ps4_feature_size(report_id); + const uint8_t *resp = ps4_feature_data(report_id); + + if (resp_len == 0) { + resp_len = reqlen; + } + if (resp_len > reqlen) { + resp_len = reqlen; + } + + memset(buffer, 0, resp_len); + if (resp != NULL) { + memcpy(buffer, resp, resp_len); + } + return resp_len; +} + +void ps4_feat_set_report(uint8_t report_id, hid_report_type_t report_type, + uint8_t const *buffer, uint16_t bufsize) +{ + if (report_type != HID_REPORT_TYPE_FEATURE) { + return; + } + + uint8_t *dest = NULL; + uint16_t dest_len = 0; + + if (report_id == 0x13) { + dest = ps4_feat_13; + dest_len = sizeof(ps4_feat_13); + } else if (report_id == 0x14) { + dest = ps4_feat_14; + dest_len = sizeof(ps4_feat_14); + } else if (report_id == 0x15) { + dest = ps4_feat_15; + dest_len = sizeof(ps4_feat_15); + } + + if (dest == NULL) { + return; + } + + uint16_t copy_len = bufsize; + if (copy_len > dest_len) { + copy_len = dest_len; + } + + memset(dest, 0, dest_len); + memcpy(dest, buffer, copy_len); +} diff --git a/firmware/src/ps4_feat.h b/firmware/src/ps4_feat.h new file mode 100644 index 0000000..454ffbe --- /dev/null +++ b/firmware/src/ps4_feat.h @@ -0,0 +1,14 @@ +#ifndef PS4_FEAT_H +#define PS4_FEAT_H + +#include + +#include "tusb.h" + +uint16_t ps4_feat_get_report(uint8_t report_id, hid_report_type_t report_type, + uint8_t *buffer, uint16_t reqlen); + +void ps4_feat_set_report(uint8_t report_id, hid_report_type_t report_type, + uint8_t const *buffer, uint16_t bufsize); + +#endif diff --git a/firmware/src/usb_descriptors.c b/firmware/src/usb_descriptors.c index 6e4b0ef..a30a649 100644 --- a/firmware/src/usb_descriptors.c +++ b/firmware/src/usb_descriptors.c @@ -41,10 +41,17 @@ (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4)) +static bool use_ps4_hid; + +void hid_use_ps4(bool enable) +{ + use_ps4_hid = enable; +} + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t desc_device_joy = { +tusb_desc_device_t desc_device_ns = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -66,20 +73,45 @@ tusb_desc_device_t desc_device_joy = { .bNumConfigurations = 0x01}; +tusb_desc_device_t desc_device_ps4 = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = DIVAPICO_PS4_VENDOR_ID, + .idProduct = DIVAPICO_PS4_PRODUCT_ID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01}; + // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor uint8_t const* tud_descriptor_device_cb(void) { - return (uint8_t const*)&desc_device_joy; + return use_ps4_hid ? + (uint8_t const*)&desc_device_ps4 : + (uint8_t const*)&desc_device_ns; } //--------------------------------------------------------------------+ // HID Report Descriptor //--------------------------------------------------------------------+ -uint8_t const desc_hid_report_joy[] = { +uint8_t const desc_hid_report_ns[] = { DIVAPICO_REPORT_DESC_JOYSTICK, }; +uint8_t const desc_hid_report_ps4[] = { + DIVAPICO_REPORT_DESC_PS4, +}; + uint8_t const desc_hid_report_led[] = { DIVAPICO_LED_HEADER, DIVAPICO_REPORT_DESC_LED_SLIDER_1, @@ -96,7 +128,7 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf) { switch (itf) { case 0: - return desc_hid_report_joy; + return use_ps4_hid ? desc_hid_report_ps4 : desc_hid_report_ns; case 1: return desc_hid_report_led; default: @@ -125,7 +157,7 @@ enum { ITF_NUM_JOY, ITF_NUM_LED, #define EPNUM_CLI_OUT 0x0a #define EPNUM_CLI_IN 0x8a -uint8_t const desc_configuration_joy[] = { +uint8_t const desc_configuration_ns[] = { // Config number, interface count, string index, total length, attribute, // power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, @@ -134,7 +166,23 @@ uint8_t const desc_configuration_joy[] = { // Interface number, string index, protocol, report descriptor len, EP In // address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_JOY, 4, HID_ITF_PROTOCOL_NONE, - sizeof(desc_hid_report_joy), EPNUM_JOY_OUT, EPNUM_JOY_IN, + sizeof(desc_hid_report_ns), EPNUM_JOY_OUT, EPNUM_JOY_IN, + CFG_TUD_HID_EP_BUFSIZE, 1), + + TUD_HID_DESCRIPTOR(ITF_NUM_LED, 5, HID_ITF_PROTOCOL_NONE, + sizeof(desc_hid_report_led), EPNUM_LED, + CFG_TUD_HID_EP_BUFSIZE, 4), + + TUD_CDC_DESCRIPTOR(ITF_NUM_CLI, 6, EPNUM_CLI_NOTIF, + 8, EPNUM_CLI_OUT, EPNUM_CLI_IN, 64), +}; + +uint8_t const desc_configuration_ps4[] = { + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 200), + + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_JOY, 4, HID_ITF_PROTOCOL_NONE, + sizeof(desc_hid_report_ps4), EPNUM_JOY_OUT, EPNUM_JOY_IN, CFG_TUD_HID_EP_BUFSIZE, 1), TUD_HID_DESCRIPTOR(ITF_NUM_LED, 5, HID_ITF_PROTOCOL_NONE, @@ -149,7 +197,7 @@ uint8_t const desc_configuration_joy[] = { // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { - return desc_configuration_joy; + return use_ps4_hid ? desc_configuration_ps4 : desc_configuration_ns; } //--------------------------------------------------------------------+ diff --git a/firmware/src/usb_descriptors.h b/firmware/src/usb_descriptors.h index 07f71ac..8af0c0d 100644 --- a/firmware/src/usb_descriptors.h +++ b/firmware/src/usb_descriptors.h @@ -1,17 +1,23 @@ #ifndef USB_DESCRIPTORS_H_ #define USB_DESCRIPTORS_H_ +#include + #include "common/tusb_common.h" #include "device/usbd.h" enum { REPORT_ID_JOYSTICK = 1, + REPORT_ID_PS4_OUTPUT = 5, REPORT_ID_LED_SLIDER_1 = 4, REPORT_ID_LED_SLIDER_2 = 5, REPORT_ID_LED_BUTTON = 6, REPORT_ID_LED_COMPRESSED = 11, }; +#define DIVAPICO_PS4_VENDOR_ID 0x1532 +#define DIVAPICO_PS4_PRODUCT_ID 0x0401 + // because they are missing from tusb_hid.h #define HID_STRING_INDEX(x) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, 1) #define HID_STRING_INDEX_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, n) @@ -62,6 +68,70 @@ enum { HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \ HID_COLLECTION_END +#define DIVAPICO_REPORT_DESC_PS4 \ + 0x05, 0x01, 0x09, 0x05, 0xA1, 0x01, \ + 0x85, 0x01, \ + 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, \ + 0x15, 0x00, 0x26, 0xFF, 0x00, \ + 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, \ + 0x09, 0x39, 0x15, 0x00, 0x25, 0x07, 0x35, 0x00, 0x46, 0x3B, 0x01, \ + 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, \ + 0x65, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0E, \ + 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0E, 0x81, 0x02, \ + 0x06, 0x00, 0xFF, 0x09, 0x20, 0x75, 0x06, 0x95, 0x01, 0x81, 0x02, \ + 0x05, 0x01, 0x09, 0x33, 0x09, 0x34, \ + 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, \ + 0x06, 0x00, 0xFF, 0x09, 0x21, 0x95, 0x36, 0x81, 0x02, \ + 0x85, 0x05, 0x09, 0x22, 0x95, 0x1F, 0x91, 0x02, \ + 0x85, 0x03, 0x0A, 0x21, 0x27, 0x95, 0x2F, 0xB1, 0x02, \ + 0x85, 0x02, 0x09, 0x24, 0x95, 0x24, 0xB1, 0x02, \ + 0x85, 0x08, 0x09, 0x25, 0x95, 0x03, 0xB1, 0x02, \ + 0x85, 0x10, 0x09, 0x26, 0x95, 0x04, 0xB1, 0x02, \ + 0x85, 0x11, 0x09, 0x27, 0x95, 0x02, 0xB1, 0x02, \ + 0x85, 0x12, 0x06, 0x02, 0xFF, 0x09, 0x21, 0x95, 0x0F, 0xB1, 0x02, \ + 0x85, 0x13, 0x09, 0x22, 0x95, 0x16, 0xB1, 0x02, \ + 0x85, 0x14, 0x06, 0x05, 0xFF, 0x09, 0x20, 0x95, 0x10, 0xB1, 0x02, \ + 0x85, 0x15, 0x09, 0x21, 0x95, 0x2C, 0xB1, 0x02, \ + 0x06, 0x80, 0xFF, \ + 0x85, 0x80, 0x09, 0x20, 0x95, 0x06, 0xB1, 0x02, \ + 0x85, 0x81, 0x09, 0x21, 0x95, 0x06, 0xB1, 0x02, \ + 0x85, 0x82, 0x09, 0x22, 0x95, 0x05, 0xB1, 0x02, \ + 0x85, 0x83, 0x09, 0x23, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0x84, 0x09, 0x24, 0x95, 0x04, 0xB1, 0x02, \ + 0x85, 0x85, 0x09, 0x25, 0x95, 0x06, 0xB1, 0x02, \ + 0x85, 0x86, 0x09, 0x26, 0x95, 0x06, 0xB1, 0x02, \ + 0x85, 0x87, 0x09, 0x27, 0x95, 0x23, 0xB1, 0x02, \ + 0x85, 0x88, 0x09, 0x28, 0x95, 0x22, 0xB1, 0x02, \ + 0x85, 0x89, 0x09, 0x29, 0x95, 0x02, 0xB1, 0x02, \ + 0x85, 0x90, 0x09, 0x30, 0x95, 0x05, 0xB1, 0x02, \ + 0x85, 0x91, 0x09, 0x31, 0x95, 0x03, 0xB1, 0x02, \ + 0x85, 0x92, 0x09, 0x32, 0x95, 0x03, 0xB1, 0x02, \ + 0x85, 0x93, 0x09, 0x33, 0x95, 0x0C, 0xB1, 0x02, \ + 0x85, 0xA0, 0x09, 0x40, 0x95, 0x06, 0xB1, 0x02, \ + 0x85, 0xA1, 0x09, 0x41, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xA2, 0x09, 0x42, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xA3, 0x09, 0x43, 0x95, 0x30, 0xB1, 0x02, \ + 0x85, 0xA4, 0x09, 0x44, 0x95, 0x0D, 0xB1, 0x02, \ + 0x85, 0xA5, 0x09, 0x45, 0x95, 0x15, 0xB1, 0x02, \ + 0x85, 0xA6, 0x09, 0x46, 0x95, 0x15, 0xB1, 0x02, \ + 0x85, 0xA7, 0x09, 0x4A, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xA8, 0x09, 0x4B, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xA9, 0x09, 0x4C, 0x95, 0x08, 0xB1, 0x02, \ + 0x85, 0xAA, 0x09, 0x4E, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xAB, 0x09, 0x4F, 0x95, 0x39, 0xB1, 0x02, \ + 0x85, 0xAC, 0x09, 0x50, 0x95, 0x39, 0xB1, 0x02, \ + 0x85, 0xAD, 0x09, 0x51, 0x95, 0x0B, 0xB1, 0x02, \ + 0x85, 0xAE, 0x09, 0x52, 0x95, 0x01, 0xB1, 0x02, \ + 0x85, 0xAF, 0x09, 0x53, 0x95, 0x02, 0xB1, 0x02, \ + 0x85, 0xB0, 0x09, 0x54, 0x95, 0x3F, 0xB1, 0x02, \ + 0xC0, \ + 0x06, 0xF0, 0xFF, 0x09, 0x40, 0xA1, 0x01, \ + 0x85, 0xF0, 0x09, 0x47, 0x95, 0x3F, 0xB1, 0x02, \ + 0x85, 0xF1, 0x09, 0x48, 0x95, 0x3F, 0xB1, 0x02, \ + 0x85, 0xF2, 0x09, 0x49, 0x95, 0x0F, 0xB1, 0x02, \ + 0x85, 0xF3, 0x0A, 0x01, 0x47, 0x95, 0x07, 0xB1, 0x02, \ + 0xC0 + #define DIVAPICO_LED_HEADER \ HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), HID_USAGE(0x00), \ HID_COLLECTION(HID_COLLECTION_APPLICATION), \ @@ -110,4 +180,6 @@ enum { HID_REPORT_SIZE(8), HID_REPORT_COUNT(63), \ HID_FEATURE(HID_DATA | HID_VARIABLE | HID_ABSOLUTE) +void hid_use_ps4(bool enable); + #endif /* USB_DESCRIPTORS_H_ */