aboutsummaryrefslogtreecommitdiff
path: root/src/xinput.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xinput.c')
-rw-r--r--src/xinput.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/xinput.c b/src/xinput.c
new file mode 100644
index 0000000..07eb01a
--- /dev/null
+++ b/src/xinput.c
@@ -0,0 +1,96 @@
+#include "tusb.h"
+#include "xinput_host.h"
+#include "gamepad.h"
+
+#define XINPUT_GAMEPAD_SHOULDER (XINPUT_GAMEPAD_LEFT_SHOULDER | XINPUT_GAMEPAD_RIGHT_SHOULDER)
+#define XINPUT_GAMEPAD_DPAD (XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_RIGHT)
+#define XINPUT_GAMEPAD_THUMB (XINPUT_GAMEPAD_LEFT_THUMB | XINPUT_GAMEPAD_RIGHT_THUMB)
+
+
+//Since https://github.com/hathach/tinyusb/pull/2222, we can add in custom vendor drivers easily
+usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count){
+ *driver_count = 1;
+ return &usbh_xinput_driver;
+}
+
+void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, xinputh_interface_t const* xid_itf, uint16_t len)
+{
+ const xinput_gamepad_t *p = &xid_itf->pad;
+
+ if (xid_itf->last_xfer_result == XFER_RESULT_SUCCESS)
+ {
+ if (xid_itf->connected && xid_itf->new_pad_data)
+ {
+ gamepad.x = p->sThumbLX;
+ gamepad.y = p->sThumbLY;
+ gamepad.z = p->sThumbRX;
+ gamepad.rz = p->sThumbRY;
+ //gamepad.rx = ((float)p->bLeftTrigger * 256) - 32767;
+ //gamepad.ry = ((float)p->bRightTrigger * 256) - 32767;
+ gamepad.gas = p->bRightTrigger;
+ gamepad.brake = p->bLeftTrigger;
+
+ uint8_t dpad = (p->wButtons & XINPUT_GAMEPAD_DPAD);
+
+ if (dpad & XINPUT_GAMEPAD_DPAD_UP)
+ {
+ if (dpad & XINPUT_GAMEPAD_DPAD_LEFT)
+ gamepad.hat = 8;
+ else if (dpad & XINPUT_GAMEPAD_DPAD_RIGHT)
+ gamepad.hat = 2;
+ else
+ gamepad.hat = 1;
+ }
+ else if (dpad & XINPUT_GAMEPAD_DPAD_DOWN)
+ {
+ if (dpad & XINPUT_GAMEPAD_DPAD_LEFT)
+ gamepad.hat = 6;
+ else if (dpad & XINPUT_GAMEPAD_DPAD_RIGHT)
+ gamepad.hat = 4;
+ else
+ gamepad.hat = 5;
+ }
+ else if (dpad & XINPUT_GAMEPAD_DPAD_LEFT)
+ gamepad.hat = 7;
+ else if (dpad & XINPUT_GAMEPAD_DPAD_RIGHT)
+ gamepad.hat = 3;
+ else
+ gamepad.hat = 0;
+
+ gamepad.buttons = \
+ (p->wButtons & (XINPUT_GAMEPAD_A | XINPUT_GAMEPAD_B)) >> 12 |
+ (p->wButtons & (XINPUT_GAMEPAD_X | XINPUT_GAMEPAD_Y)) >> 11 |
+ (p->wButtons & XINPUT_GAMEPAD_SHOULDER) >> 2 |
+ (p->wButtons & XINPUT_GAMEPAD_BACK) << 5 |
+ (p->wButtons & XINPUT_GAMEPAD_START) << 7 |
+ (p->wButtons & XINPUT_GAMEPAD_THUMB) << 7 |
+ (p->wButtons & XINPUT_GAMEPAD_GUIDE) << 2 |
+ 0;
+
+ request_can_send_now_event();
+ }
+ }
+ tuh_xinput_receive_report(dev_addr, instance);
+}
+
+void tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, const xinputh_interface_t *xinput_itf)
+{
+ TU_LOG1("Controller attached\n");
+ // If this is a Xbox 360 Wireless controller we need to wait for a connection packet
+ // on the in pipe before setting LEDs etc. So just start getting data until a controller is connected.
+ if (xinput_itf->type == XBOX360_WIRELESS && xinput_itf->connected == false)
+ {
+ tuh_xinput_receive_report(dev_addr, instance);
+ return;
+ }
+ tuh_xinput_set_led(dev_addr, instance, 0, true);
+ tuh_xinput_set_led(dev_addr, instance, 1, true);
+ tuh_xinput_set_rumble(dev_addr, instance, 0, 0, true);
+ tuh_xinput_receive_report(dev_addr, instance);
+}
+
+void tuh_xinput_umount_cb(uint8_t dev_addr, uint8_t instance)
+{
+ TU_LOG1("Controller removed, clearing controls\n");
+ memset(&gamepad, sizeof(gamepad), 0);
+} \ No newline at end of file