#include "bsp/board.h"
#include "tusb.h"
typedef struct TU_ATTR_PACKED
{
uint8_t x, y, z, rz;
struct {
uint8_t dpad : 4; uint8_t square : 1; uint8_t cross : 1; uint8_t circle : 1; uint8_t triangle : 1; };
struct {
uint8_t l1 : 1;
uint8_t r1 : 1;
uint8_t l2 : 1;
uint8_t r2 : 1;
uint8_t share : 1;
uint8_t option : 1;
uint8_t l3 : 1;
uint8_t r3 : 1;
};
struct {
uint8_t ps : 1; uint8_t tpad : 1; uint8_t counter : 6; };
} sony_ds4_report_t;
static inline bool is_sony_ds4(uint8_t dev_addr)
{
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) || (vid == 0x0f0d && pid == 0x005e) || (vid == 0x0f0d && pid == 0x00ee) || (vid == 0x1f4f && pid == 0x1002) );
}
void hid_app_task(void)
{
}
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
{
(void)desc_report;
(void)desc_len;
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
printf("VID = %04x, PID = %04x\r\n", vid, pid);
if ( is_sony_ds4(dev_addr) )
{
if ( !tuh_hid_receive_report(dev_addr, instance) )
{
printf("Error: cannot request to receive report\r\n");
}
}
}
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
bool diff_than_2(uint8_t x, uint8_t y)
{
return (x - y > 2) || (y - x > 2);
}
bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
{
bool result;
result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-4);
return result;
}
void process_sony_ds4(uint8_t const* report, uint16_t len)
{
const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
static sony_ds4_report_t prev_report = { 0 };
uint8_t const report_id = report[0];
report++;
len--;
if (report_id == 1)
{
sony_ds4_report_t ds4_report;
memcpy(&ds4_report, report, sizeof(ds4_report));
prev_report.counter = ds4_report.counter;
if ( diff_report(&prev_report, &ds4_report) )
{
printf("(x, y, z, rz) = (%u, %u, %u, %u)\r\n", ds4_report.x, ds4_report.y, ds4_report.z, ds4_report.rz);
printf("DPad = %s ", dpad_str[ds4_report.dpad]);
if (ds4_report.square ) printf("Square ");
if (ds4_report.cross ) printf("Cross ");
if (ds4_report.circle ) printf("Circle ");
if (ds4_report.triangle ) printf("Triangle ");
if (ds4_report.l1 ) printf("L1 ");
if (ds4_report.r1 ) printf("R1 ");
if (ds4_report.l2 ) printf("L2 ");
if (ds4_report.r2 ) printf("R2 ");
if (ds4_report.share ) printf("Share ");
if (ds4_report.option ) printf("Option ");
if (ds4_report.l3 ) printf("L3 ");
if (ds4_report.r3 ) printf("R3 ");
if (ds4_report.ps ) printf("PS ");
if (ds4_report.tpad ) printf("TPad ");
printf("\r\n");
}
prev_report = ds4_report;
}
}
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
if ( is_sony_ds4(dev_addr) )
{
process_sony_ds4(report, len);
}
if ( !tuh_hid_receive_report(dev_addr, instance) )
{
printf("Error: cannot request to receive report\r\n");
}
}