From f07b637a43d3e54c7820ef5952cd481eb11f8826 Mon Sep 17 00:00:00 2001 From: Daryl Borth Date: Fri, 3 Jan 2020 20:13:51 -0700 Subject: [PATCH] updates to xbox360/retrode/hornet usb controller support (thanks revvv!) --- source/input.cpp | 11 +- source/input.h | 2 + source/menu.cpp | 6 +- source/utils/hornet.c | 161 ++++++++++++++++ source/utils/hornet.h | 18 ++ source/utils/retrode.c | 97 +++++----- source/utils/retrode.h | 2 + source/utils/xbox360.c | 426 +++++++++++++++++++++-------------------- 8 files changed, 464 insertions(+), 259 deletions(-) create mode 100644 source/utils/hornet.c create mode 100644 source/utils/hornet.h diff --git a/source/input.cpp b/source/input.cpp index a05eda5e..172558f5 100644 --- a/source/input.cpp +++ b/source/input.cpp @@ -38,6 +38,7 @@ #ifdef HW_RVL #include "utils/retrode.h" #include "utils/xbox360.h" +#include "utils/hornet.h" #endif #define ANALOG_SENSITIVITY 30 @@ -337,6 +338,7 @@ UpdatePads() WiiDRC_ScanPads(); Retrode_ScanPads(); XBOX360_ScanPads(); + Hornet_ScanPads(); WPAD_ScanPads(); #endif @@ -538,7 +540,8 @@ static void decodepad (int chan) u32 wiidrcp = userInput[chan].wiidrcdata.btns_h; jp |= Retrode_ButtonsHeld(chan); - jp |= XBOX360_ButtonsHeld(chan); + jp |= XBOX360_ButtonsHeld(chan); + jp |= Hornet_ButtonsHeld(chan); #endif /*** @@ -903,8 +906,8 @@ void SetDefaultButtonMap () #ifdef HW_RVL char* GetUSBControllerInfo() { - static char info[50]; - snprintf(info, 50, "Retrode: %s, XBOX360: %s", Retrode_Status(), XBOX360_Status()); + static char info[70]; + snprintf(info, 70, "Retrode: %s, XBOX360: %s, Hornet: %s", Retrode_Status(), XBOX360_Status(), Hornet_Status()); return info; } -#endif \ No newline at end of file +#endif diff --git a/source/input.h b/source/input.h index 095ddb3e..8a1e89ef 100644 --- a/source/input.h +++ b/source/input.h @@ -35,6 +35,8 @@ void SetDefaultButtonMap (); bool MenuRequested(); void SetupPads(); void UpdatePads(); +#ifdef HW_RVL char* GetUSBControllerInfo(); +#endif #endif diff --git a/source/menu.cpp b/source/menu.cpp index 2df42330..c21a21db 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -868,12 +868,10 @@ static void WindowCredits(void * ptr) txt[i] = new GuiText("under the terms of the GNU General Public License (GPL) Version 2."); txt[i]->SetPosition(0,y); i++; y+=20; - //char iosVersion[20]; - char iosVersion[70]; // added 50 for Retrode info + char iosVersion[90]; #ifdef HW_RVL - //sprintf(iosVersion, "IOS: %ld", IOS_GetVersion()); - snprintf(iosVersion, 70, "IOS: %ld / %s", IOS_GetVersion(), GetUSBControllerInfo()); + snprintf(iosVersion, 90, "IOS: %ld / %s", IOS_GetVersion(), GetUSBControllerInfo()); #endif txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255}); diff --git a/source/utils/hornet.c b/source/utils/hornet.c new file mode 100644 index 00000000..f0844326 --- /dev/null +++ b/source/utils/hornet.c @@ -0,0 +1,161 @@ +#ifdef HW_RVL +#include + +#define HORNET_VID 0x0079 +#define HORNET_PID 0x0011 + +static bool setup = false; +static bool replugRequired = false; +static s32 deviceId = 0; +static u8 endpoint = 0; +static u8 bMaxPacketSize = 0; +static u32 jp; + +static bool isHornetGamepad(usb_device_entry dev) +{ + return dev.vid == HORNET_VID && dev.pid == HORNET_PID; +} + +static u8 getEndpoint(usb_devdesc devdesc) +{ + if (devdesc.configurations == NULL || devdesc.configurations->interfaces == NULL || + devdesc.configurations->interfaces->endpoints == NULL) + { + return -1; + } + return devdesc.configurations->interfaces->endpoints->bEndpointAddress; +} + +static int removal_cb(int result, void *usrdata) +{ + s32 fd = (s32) usrdata; + if (fd == deviceId) + { + deviceId = 0; + } + return 1; +} + +static void open() +{ + if (deviceId != 0) + { + return; + } + + usb_device_entry dev_entry[8]; + u8 dev_count; + if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0) + { + return; + } + + for (int i = 0; i < dev_count; ++i) + { + if (!isHornetGamepad(dev_entry[i])) + { + continue; + } + s32 fd; + if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0) + { + continue; + } + + usb_devdesc devdesc; + if (USB_GetDescriptors(fd, &devdesc) < 0) + { + // You have to replug the controller! + replugRequired = true; + USB_CloseDevice(&fd); + break; + } + + deviceId = fd; + replugRequired = false; + endpoint = getEndpoint(devdesc); + bMaxPacketSize = devdesc.bMaxPacketSize0; + USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd); + break; + } + + setup = true; +} + +void Hornet_ScanPads() +{ + if (deviceId == 0) + { + return; + } + + uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize]; + s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf); + if (res < 0) + { + return; + } + + // Button layout + // A=5,2F + // B=5,1F + // X=6,01 + // Y=5,8F + // Select=6,10 ; Hornet button label = "9" + // Start=6,20 ; Hornet button label = "10" + // Up=4,00 + // Right=3,FF + // Left=3,00 + // Down=4,FF + // L=6,04 + // R=6,08 + // Unused=6,02 ; Hornet button label = "6" + // Unused=5,4F ; Hornet button label = "3" + + jp = 0; + jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0; + jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0; + jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0; + jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0; + + jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0; + jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_B : 0; + jp |= ((buf[6] & 0x01) == 0x01) ? PAD_BUTTON_X : 0; + jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0; + + jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0; + jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0; + + jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0; + jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // Hornet select button maps to Z + + jp |= ((buf[6] & 0x02) == 0x02) ? PAD_BUTTON_Y : 0; // Hornet button 6 maps to Y + jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0; // Hornet button 3 maps to B +} + +u32 Hornet_ButtonsHeld(int chan) +{ + if(!setup) + { + open(); + } + if (deviceId == 0) + { + return 0; + } + if (chan != 0) + { + return 0; + } + return jp; +} + +char* Hornet_Status() +{ + open(); + if (replugRequired) + return "please replug"; + return deviceId ? "connected" : "not found"; +} + +#endif diff --git a/source/utils/hornet.h b/source/utils/hornet.h new file mode 100644 index 00000000..b58dfd91 --- /dev/null +++ b/source/utils/hornet.h @@ -0,0 +1,18 @@ +#ifndef _HORNET_H_ +#define _HORNET_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool Hornet_ScanPads(); +u32 Hornet_ButtonsHeld(int chan); +char* Hornet_Status(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/utils/retrode.c b/source/utils/retrode.c index 0966a726..8f174599 100644 --- a/source/utils/retrode.c +++ b/source/utils/retrode.c @@ -1,6 +1,9 @@ #ifdef HW_RVL #include +#define RETRODE_VID 0x0403 +#define RETRODE_PID 0x97C1 + static bool setup = false; static bool replugRequired = false; static s32 deviceId = 0; @@ -9,9 +12,14 @@ static u8 bMaxPacketSize = 0; static u32 jpRetrode[4]; +static bool isRetrode(usb_device_entry dev) +{ + return dev.vid == RETRODE_VID && dev.pid == RETRODE_PID; +} + static bool isRetrodeGamepad(usb_devdesc devdesc) { - if (devdesc.idVendor != 0x0403 || devdesc.idProduct != 0x97C1 || + if (devdesc.idVendor != RETRODE_VID || devdesc.idProduct != RETRODE_PID || devdesc.configurations == NULL || devdesc.configurations->interfaces == NULL || devdesc.configurations->interfaces->endpoints == NULL) { @@ -32,20 +40,20 @@ static u8 getEndpoint(usb_devdesc devdesc) static int removal_cb(int result, void *usrdata) { - s32 fd = (s32) usrdata; - if (fd == deviceId) - { - deviceId = 0; - } - return 1; + s32 fd = (s32) usrdata; + if (fd == deviceId) + { + deviceId = 0; + } + return 1; } static void open() { if (deviceId != 0) - { - return; - } + { + return; + } usb_device_entry dev_entry[8]; u8 dev_count; @@ -55,9 +63,12 @@ static void open() } // Retrode has two entries in USB_GetDeviceList(), one for gamepads and one for SNES mouse - int i; - for (i = 0; i < dev_count; ++i) + for (int i = 0; i < dev_count; ++i) { + if (!isRetrode(dev_entry[i])) + { + continue; + } s32 fd; if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0) { @@ -76,19 +87,19 @@ static void open() if (isRetrodeGamepad(devdesc)) { deviceId = fd; - replugRequired = false; - endpoint = getEndpoint(devdesc); - bMaxPacketSize = devdesc.bMaxPacketSize0; - USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd); - break; + replugRequired = false; + endpoint = getEndpoint(devdesc); + bMaxPacketSize = devdesc.bMaxPacketSize0; + USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd); + break; } else { - USB_CloseDevice(&fd); + USB_CloseDevice(&fd); } } - setup = true; + setup = true; } void Retrode_ScanPads() @@ -100,7 +111,7 @@ void Retrode_ScanPads() uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize]; - // Retrode gamepad endpoint returns 5 bytes with gamepad events + // Retrode gamepad endpoint returns 5 bytes with gamepad events if (USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf) != 5) { return; @@ -115,21 +126,21 @@ void Retrode_ScanPads() // 4 = right Genesis/MD // Button layout - // A=3,10 - // B=3,01 - // X=3,20 - // Y=3,02 - // L=3,40 - // R=3,80 - // Up=2,9C - // Down=2,64 - // Left=1,9C - // Right=1,64 - // Start=3,08 - // Select=3,04 + // A=3,10 + // B=3,01 + // X=3,20 + // Y=3,02 + // L=3,40 + // R=3,80 + // Up=2,9C + // Down=2,64 + // Left=1,9C + // Right=1,64 + // Start=3,08 + // Select=3,04 u32 jp = 0; - jp |= ((buf[2] & 0x9C) == 0x9C) ? PAD_BUTTON_UP : 0; + jp |= ((buf[2] & 0x9C) == 0x9C) ? PAD_BUTTON_UP : 0; jp |= ((buf[2] & 0x64) == 0x64) ? PAD_BUTTON_DOWN : 0; jp |= ((buf[1] & 0x9C) == 0x9C) ? PAD_BUTTON_LEFT : 0; jp |= ((buf[1] & 0x64) == 0x64) ? PAD_BUTTON_RIGHT : 0; @@ -143,7 +154,7 @@ void Retrode_ScanPads() jp |= (buf[3] & 0x80) ? PAD_TRIGGER_R : 0; jp |= (buf[3] & 0x08) ? PAD_BUTTON_START : 0; - jp |= (buf[3] & 0x04) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z + jp |= (buf[3] & 0x04) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z // Required, otherwise if the returned port isn't the one we are looking for, jp will be set to zero, // and held buttons are not possible w/o saving the state. @@ -152,10 +163,10 @@ void Retrode_ScanPads() u32 Retrode_ButtonsHeld(int chan) { - if(!setup) - { - open(); - } + if(!setup) + { + open(); + } if (deviceId == 0) { return 0; @@ -165,10 +176,10 @@ u32 Retrode_ButtonsHeld(int chan) char* Retrode_Status() { - open(); - if (replugRequired) - return "please replug"; - return deviceId ? "connected" : "not found"; + open(); + if (replugRequired) + return "please replug"; + return deviceId ? "connected" : "not found"; } -#endif \ No newline at end of file +#endif diff --git a/source/utils/retrode.h b/source/utils/retrode.h index 85e7fd35..de6ab334 100644 --- a/source/utils/retrode.h +++ b/source/utils/retrode.h @@ -1,6 +1,8 @@ #ifndef _RETRODE_H_ #define _RETRODE_H_ +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/source/utils/xbox360.c b/source/utils/xbox360.c index 6ff34166..70c980ae 100644 --- a/source/utils/xbox360.c +++ b/source/utils/xbox360.c @@ -3,12 +3,14 @@ #include #define USB_CLASS_XBOX360 0xFF +#define XBOX360_VID 0x045e +#define XBOX360_PID 0x028e static bool setup = false; static bool replugRequired = false; static s32 deviceId = 0; static u8 endpoint_in = 0x81; -static u8 endpoint_out = 0x01; // some controllers require 0x02 for LED & rumble (updated below) +static u8 endpoint_out = 0x01; // some controllers require 0x02 (updated below) static u8 bMaxPacketSize = 20; static u8 bConfigurationValue = 1; static u8 ATTRIBUTE_ALIGN(32) buf[20]; @@ -28,159 +30,164 @@ static u8 getEndpoint(usb_devdesc devdesc) return devdesc.configurations->interfaces->endpoints->bEndpointAddress; } -static bool isXBOX360(usb_devdesc devdesc) +static bool isXBOX360(usb_device_entry dev) { - return (devdesc.idVendor == 0x045e && devdesc.idProduct == 0x028e && getEndpoint(devdesc) == endpoint_in); + return dev.vid == XBOX360_VID && dev.pid == XBOX360_PID; +} + +static bool isXBOX360Gamepad(usb_devdesc devdesc) +{ + return devdesc.idVendor == XBOX360_VID && devdesc.idProduct == XBOX360_PID && getEndpoint(devdesc) == endpoint_in; } static int read(s32 device_id, u8 endpoint, u8 bMaxPacketSize0); static void start_reading(s32 device_id, u8 endpoint, u8 bMaxPacketSize0) { - if (isReading) - { - // already reading - return; - } - isReading = true; - read(deviceId, endpoint_in, bMaxPacketSize0); + if (isReading) + { + // already reading + return; + } + isReading = true; + read(deviceId, endpoint_in, bMaxPacketSize0); } static void stop_reading() { - isReading = false; + isReading = false; } static int read_cb(int res, void *usrdata) { - if (!isReading) - { - // stop reading - return 1; - } - - // NOTE: The four startup messages have res = 3 and can be ignored - - // Button layout - // A=3,10 - // B=3,20 - // X=3,40 - // Y=3,80 - // Up=2,01 - // Right=2,08 - // Left=2,04 - // Down=2,02 - // L=3,01 - // R=3,02 - // L2=4,FF ; analog trigger - // R3=5,FF ; analog trigger - // L3=2,40 ; left hat button - // L3=2,80 ; right hat button - // XBOX=3,04 - // Start=2,10 - // Back=2,20 - // LStickX=6/7,FF ; , - // LStickY=8/9,FF - // RStickX=10/11,FF - // RStickY=12/13,FF - - if (res == 20) - { - jp = 0; - jp |= ((buf[2] & 0x01) == 0x01) ? PAD_BUTTON_UP : 0; - jp |= ((buf[2] & 0x02) == 0x02) ? PAD_BUTTON_DOWN : 0; - jp |= ((buf[2] & 0x04) == 0x04) ? PAD_BUTTON_LEFT : 0; - jp |= ((buf[2] & 0x08) == 0x08) ? PAD_BUTTON_RIGHT : 0; - - jp |= ((buf[3] & 0x10) == 0x10) ? PAD_BUTTON_B : 0; // XBOX360 A button maps to B - jp |= ((buf[3] & 0x20) == 0x20) ? PAD_BUTTON_A : 0; // XBOX360 B button maps to A - jp |= ((buf[3] & 0x40) == 0x40) ? PAD_BUTTON_Y : 0; // XBOX360 X button maps to Y - jp |= ((buf[3] & 0x80) == 0x80) ? PAD_BUTTON_X : 0; // XBOX360 Y button maps to X - - jp |= ((buf[3] & 0x01) == 0x01) ? PAD_TRIGGER_L : 0; - jp |= ((buf[3] & 0x02) == 0x02) ? PAD_TRIGGER_R : 0; - - jp |= ((buf[2] & 0x10) == 0x10) ? PAD_BUTTON_START : 0; - jp |= ((buf[2] & 0x20) == 0x20) ? PAD_TRIGGER_Z : 0; // XBOX360 back button maps to Z - - // triggers - jp |= (buf[4] > 128) ? PAD_TRIGGER_L : 0; - jp |= (buf[5] > 128) ? PAD_TRIGGER_R : 0; - - // left stick - int16_t lx = (buf[7] << 8) | buf[6]; // [-32768, 32767] - int16_t ly = (buf[9] << 8) | buf[8]; // [-32768, 32767] - jp |= (ly > 16384) ? PAD_BUTTON_UP : 0; - jp |= (ly < -16384) ? PAD_BUTTON_DOWN : 0; - jp |= (lx < -16384) ? PAD_BUTTON_LEFT : 0; - jp |= (lx > 16384) ? PAD_BUTTON_RIGHT : 0; - - // right stick - int16_t rx = (buf[11] << 8) | buf[10]; // [-32768, 32767] - int16_t ry = (buf[13] << 8) | buf[12]; // [-32768, 32767] - jp |= (ry > 16384) ? PAD_BUTTON_X : 0; // XBOX360 Y button maps to X - jp |= (ry < -16384) ? PAD_BUTTON_B : 0; // XBOX360 A button maps to B - jp |= (rx < -16384) ? PAD_BUTTON_Y : 0; // XBOX360 X button maps to Y - jp |= (rx > 16384) ? PAD_BUTTON_A : 0; // XBOX360 B button maps to A + if (!isReading) + { + // stop reading + return 1; + } + + // NOTE: The four startup messages have res = 3 and can be ignored + + // Button layout + // A=3,10 + // B=3,20 + // X=3,40 + // Y=3,80 + // Up=2,01 + // Right=2,08 + // Left=2,04 + // Down=2,02 + // L=3,01 + // R=3,02 + // L2=4,FF ; analog trigger + // R3=5,FF ; analog trigger + // L3=2,40 ; left hat button + // L3=2,80 ; right hat button + // XBOX=3,04 + // Start=2,10 + // Back=2,20 + // LStickX=6/7,FF ; , + // LStickY=8/9,FF + // RStickX=10/11,FF + // RStickY=12/13,FF + + if (res == 20) + { + jp = 0; + jp |= ((buf[2] & 0x01) == 0x01) ? PAD_BUTTON_UP : 0; + jp |= ((buf[2] & 0x02) == 0x02) ? PAD_BUTTON_DOWN : 0; + jp |= ((buf[2] & 0x04) == 0x04) ? PAD_BUTTON_LEFT : 0; + jp |= ((buf[2] & 0x08) == 0x08) ? PAD_BUTTON_RIGHT : 0; + + jp |= ((buf[3] & 0x10) == 0x10) ? PAD_BUTTON_B : 0; // XBOX360 A button maps to B + jp |= ((buf[3] & 0x20) == 0x20) ? PAD_BUTTON_A : 0; // XBOX360 B button maps to A + jp |= ((buf[3] & 0x40) == 0x40) ? PAD_BUTTON_Y : 0; // XBOX360 X button maps to Y + jp |= ((buf[3] & 0x80) == 0x80) ? PAD_BUTTON_X : 0; // XBOX360 Y button maps to X + + jp |= ((buf[3] & 0x01) == 0x01) ? PAD_TRIGGER_L : 0; + jp |= ((buf[3] & 0x02) == 0x02) ? PAD_TRIGGER_R : 0; + + jp |= ((buf[2] & 0x10) == 0x10) ? PAD_BUTTON_START : 0; + jp |= ((buf[2] & 0x20) == 0x20) ? PAD_TRIGGER_Z : 0; // XBOX360 back button maps to Z + + // triggers + jp |= (buf[4] > 128) ? PAD_TRIGGER_L : 0; + jp |= (buf[5] > 128) ? PAD_TRIGGER_R : 0; + + // left stick + int16_t lx = (buf[7] << 8) | buf[6]; // [-32768, 32767] + int16_t ly = (buf[9] << 8) | buf[8]; // [-32768, 32767] + jp |= (ly > 16384) ? PAD_BUTTON_UP : 0; + jp |= (ly < -16384) ? PAD_BUTTON_DOWN : 0; + jp |= (lx < -16384) ? PAD_BUTTON_LEFT : 0; + jp |= (lx > 16384) ? PAD_BUTTON_RIGHT : 0; + + // right stick + int16_t rx = (buf[11] << 8) | buf[10]; // [-32768, 32767] + int16_t ry = (buf[13] << 8) | buf[12]; // [-32768, 32767] + jp |= (ry > 16384) ? PAD_BUTTON_UP : 0; + jp |= (ry < -16384) ? PAD_BUTTON_DOWN : 0; + jp |= (rx < -16384) ? PAD_BUTTON_LEFT : 0; + jp |= (rx > 16384) ? PAD_BUTTON_RIGHT : 0; // XBOX button to switch to next player - if ((buf[3] & 0x04) == 0x04) - { - xboxButtonCount++; - // count = 2 means you have to push the button 1x to switch players - // count = 10 means you have to push the button 5x to switch players - if (xboxButtonCount >= 2) - { - nextPlayer = true; - xboxButtonCount = 0; - } - } - } - - // read again - read(deviceId, endpoint_in, bMaxPacketSize); - - return 1; + if ((buf[3] & 0x04) == 0x04) + { + xboxButtonCount++; + // count = 2 means you have to push the button 1x to switch players + // count = 10 means you have to push the button 5x to switch players + if (xboxButtonCount >= 2) + { + nextPlayer = true; + xboxButtonCount = 0; + } + } + } + + // read again + read(deviceId, endpoint_in, bMaxPacketSize); + + return 1; } // never call directly static int read(s32 device_id, u8 endpoint, u8 bMaxPacketSize0) { - // need to use async, because USB_ReadIntrMsg() blocks until a button is pressed - return USB_ReadIntrMsgAsync(device_id, endpoint, sizeof(buf), buf, &read_cb, NULL); + // need to use async, because USB_ReadIntrMsg() blocks until a button is pressed + return USB_ReadIntrMsgAsync(device_id, endpoint, sizeof(buf), buf, &read_cb, NULL); } static void turnOnLED() { - uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x01, 0x03, 0x06 + player }; - USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf); + uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x01, 0x03, 0x06 + player }; + USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf); } static void increasePlayer() { - player++; - if (player > 3) - { - player = 0; - } - turnOnLED(); + player++; + if (player > 3) + { + player = 0; + } + turnOnLED(); } void rumble(s32 device_id, u8 left, u8 right) { - uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 }; - USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf); + uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 }; + USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf); } static int removal_cb(int result, void *usrdata) { - s32 fd = (s32) usrdata; - if (fd == deviceId) - { - stop_reading(); - deviceId = 0; - } - return 1; + s32 fd = (s32) usrdata; + if (fd == deviceId) + { + stop_reading(); + deviceId = 0; + } + return 1; } // adapted from RetroArch input/drivers_hid/wiiusb_hid.c#wiiusb_get_description() @@ -191,86 +198,89 @@ void wiiusb_get_description(usb_device_entry *device, usb_devdesc *devdesc) for (c = 0; c < devdesc->bNumConfigurations; c++) { - const usb_configurationdesc *config = &devdesc->configurations[c]; - - for (i = 0; i < (int)config->bNumInterfaces; i++) - { - const usb_interfacedesc *inter = &config->interfaces[i]; - - for (k = 0; k < (int)inter->bNumEndpoints; k++) - { - const usb_endpointdesc *epdesc = &inter->endpoints[k]; - bool is_int = (epdesc->bmAttributes & 0x03) == USB_ENDPOINT_INTERRUPT; - bool is_out = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_OUT; - bool is_in = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_IN; - - if (is_int) - { - if (is_in) - { - //endpoint_in = epdesc->bEndpointAddress; - //endpoint_in_max_size = epdesc->wMaxPacketSize; - } - if (is_out) - { - endpoint_out = epdesc->bEndpointAddress; - //endpoint_out_max_size = epdesc->wMaxPacketSize; - } - } - } - break; - } + const usb_configurationdesc *config = &devdesc->configurations[c]; + + for (i = 0; i < (int)config->bNumInterfaces; i++) + { + const usb_interfacedesc *inter = &config->interfaces[i]; + + for (k = 0; k < (int)inter->bNumEndpoints; k++) + { + const usb_endpointdesc *epdesc = &inter->endpoints[k]; + bool is_int = (epdesc->bmAttributes & 0x03) == USB_ENDPOINT_INTERRUPT; + bool is_out = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_OUT; + bool is_in = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_IN; + + if (is_int) + { + if (is_in) + { + //endpoint_in = epdesc->bEndpointAddress; + //endpoint_in_max_size = epdesc->wMaxPacketSize; + } + if (is_out) + { + endpoint_out = epdesc->bEndpointAddress; + //endpoint_out_max_size = epdesc->wMaxPacketSize; + } + } + } + break; + } } } static void open() { - if (deviceId != 0) - { - return; - } - - usb_device_entry dev_entry[8]; - u8 dev_count; - if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_XBOX360, &dev_count) < 0) - { - return; - } - - int i; - for (i = 0; i < dev_count; ++i) - { - s32 fd; - if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0) - { - continue; - } - - usb_devdesc devdesc; - if (USB_GetDescriptors(fd, &devdesc) < 0) - { - // You have to replug the XBOX360 controller! - replugRequired = true; - USB_CloseDevice(&fd); - break; - } - - if (isXBOX360(devdesc) && USB_SetConfiguration(fd, bConfigurationValue) >= 0) - { - deviceId = fd; - replugRequired = false; - wiiusb_get_description(&dev_entry[i], &devdesc); - turnOnLED(); - USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd); - break; - } - else - { - USB_CloseDevice(&fd); - } - } - - setup = true; + if (deviceId != 0) + { + return; + } + + usb_device_entry dev_entry[8]; + u8 dev_count; + if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_XBOX360, &dev_count) < 0) + { + return; + } + + for (int i = 0; i < dev_count; ++i) + { + if (!isXBOX360(dev_entry[i])) + { + continue; + } + s32 fd; + if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0) + { + continue; + } + + usb_devdesc devdesc; + if (USB_GetDescriptors(fd, &devdesc) < 0) + { + // You have to replug the XBOX360 controller! + replugRequired = true; + USB_CloseDevice(&fd); + break; + } + + if (isXBOX360Gamepad(devdesc) && USB_SetConfiguration(fd, bConfigurationValue) >= 0) + { + deviceId = fd; + replugRequired = false; + wiiusb_get_description(&dev_entry[i], &devdesc); + turnOnLED(); + USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd); + break; + } + else + { + USB_CloseDevice(&fd); + } + } + + setup = true; } void XBOX360_ScanPads() @@ -285,19 +295,19 @@ void XBOX360_ScanPads() u32 XBOX360_ButtonsHeld(int chan) { - if(!setup) - { - open(); - } - if (deviceId == 0) - { - return 0; - } - if (nextPlayer) - { - nextPlayer = false; - increasePlayer(); - } + if(!setup) + { + open(); + } + if (deviceId == 0) + { + return 0; + } + if (nextPlayer) + { + nextPlayer = false; + increasePlayer(); + } if (chan != player) { return 0; @@ -307,10 +317,10 @@ u32 XBOX360_ButtonsHeld(int chan) char* XBOX360_Status() { - open(); - if (replugRequired) - return "please replug"; - return deviceId ? "connected" : "not found"; + open(); + if (replugRequired) + return "please replug"; + return deviceId ? "connected" : "not found"; } #endif