mirror of
https://github.com/whowechina/diva_pico.git
synced 2026-10-09 06:59:49 +03:00
Add partial PS4 support (no auth)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 <switch|steam|arcade>\n";
|
||||
const char *usage = "Usage: keymap <switch|steam|arcade|ps4>\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[])
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef struct __attribute__((packed)) {
|
||||
|
||||
typedef struct {
|
||||
bool diva_plus;
|
||||
bool hid_ps4;
|
||||
struct {
|
||||
bool sensor;
|
||||
} debug;
|
||||
|
||||
+93
-22
@@ -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);
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef PS4_FEAT_H
|
||||
#define PS4_FEAT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
#ifndef USB_DESCRIPTORS_H_
|
||||
#define USB_DESCRIPTORS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#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_ */
|
||||
|
||||
Reference in New Issue
Block a user