mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-12 12:24:34 +01:00
updates to xbox360/retrode/hornet usb controller support (thanks revvv!)
This commit is contained in:
parent
aa2ee0e422
commit
f07b637a43
@ -38,6 +38,7 @@
|
|||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
#include "utils/retrode.h"
|
#include "utils/retrode.h"
|
||||||
#include "utils/xbox360.h"
|
#include "utils/xbox360.h"
|
||||||
|
#include "utils/hornet.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ANALOG_SENSITIVITY 30
|
#define ANALOG_SENSITIVITY 30
|
||||||
@ -337,6 +338,7 @@ UpdatePads()
|
|||||||
WiiDRC_ScanPads();
|
WiiDRC_ScanPads();
|
||||||
Retrode_ScanPads();
|
Retrode_ScanPads();
|
||||||
XBOX360_ScanPads();
|
XBOX360_ScanPads();
|
||||||
|
Hornet_ScanPads();
|
||||||
WPAD_ScanPads();
|
WPAD_ScanPads();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -538,7 +540,8 @@ static void decodepad (int chan)
|
|||||||
u32 wiidrcp = userInput[chan].wiidrcdata.btns_h;
|
u32 wiidrcp = userInput[chan].wiidrcdata.btns_h;
|
||||||
|
|
||||||
jp |= Retrode_ButtonsHeld(chan);
|
jp |= Retrode_ButtonsHeld(chan);
|
||||||
jp |= XBOX360_ButtonsHeld(chan);
|
jp |= XBOX360_ButtonsHeld(chan);
|
||||||
|
jp |= Hornet_ButtonsHeld(chan);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -903,8 +906,8 @@ void SetDefaultButtonMap ()
|
|||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
char* GetUSBControllerInfo()
|
char* GetUSBControllerInfo()
|
||||||
{
|
{
|
||||||
static char info[50];
|
static char info[70];
|
||||||
snprintf(info, 50, "Retrode: %s, XBOX360: %s", Retrode_Status(), XBOX360_Status());
|
snprintf(info, 70, "Retrode: %s, XBOX360: %s, Hornet: %s", Retrode_Status(), XBOX360_Status(), Hornet_Status());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -35,6 +35,8 @@ void SetDefaultButtonMap ();
|
|||||||
bool MenuRequested();
|
bool MenuRequested();
|
||||||
void SetupPads();
|
void SetupPads();
|
||||||
void UpdatePads();
|
void UpdatePads();
|
||||||
|
#ifdef HW_RVL
|
||||||
char* GetUSBControllerInfo();
|
char* GetUSBControllerInfo();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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] = new GuiText("under the terms of the GNU General Public License (GPL) Version 2.");
|
||||||
txt[i]->SetPosition(0,y); i++; y+=20;
|
txt[i]->SetPosition(0,y); i++; y+=20;
|
||||||
|
|
||||||
//char iosVersion[20];
|
char iosVersion[90];
|
||||||
char iosVersion[70]; // added 50 for Retrode info
|
|
||||||
|
|
||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
//sprintf(iosVersion, "IOS: %ld", IOS_GetVersion());
|
snprintf(iosVersion, 90, "IOS: %ld / %s", IOS_GetVersion(), GetUSBControllerInfo());
|
||||||
snprintf(iosVersion, 70, "IOS: %ld / %s", IOS_GetVersion(), GetUSBControllerInfo());
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255});
|
txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255});
|
||||||
|
161
source/utils/hornet.c
Normal file
161
source/utils/hornet.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#ifdef HW_RVL
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
#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
|
18
source/utils/hornet.h
Normal file
18
source/utils/hornet.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _HORNET_H_
|
||||||
|
#define _HORNET_H_
|
||||||
|
|
||||||
|
#include <gctypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Hornet_ScanPads();
|
||||||
|
u32 Hornet_ButtonsHeld(int chan);
|
||||||
|
char* Hornet_Status();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,9 @@
|
|||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
|
|
||||||
|
#define RETRODE_VID 0x0403
|
||||||
|
#define RETRODE_PID 0x97C1
|
||||||
|
|
||||||
static bool setup = false;
|
static bool setup = false;
|
||||||
static bool replugRequired = false;
|
static bool replugRequired = false;
|
||||||
static s32 deviceId = 0;
|
static s32 deviceId = 0;
|
||||||
@ -9,9 +12,14 @@ static u8 bMaxPacketSize = 0;
|
|||||||
|
|
||||||
static u32 jpRetrode[4];
|
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)
|
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 == NULL || devdesc.configurations->interfaces == NULL ||
|
||||||
devdesc.configurations->interfaces->endpoints == NULL)
|
devdesc.configurations->interfaces->endpoints == NULL)
|
||||||
{
|
{
|
||||||
@ -32,20 +40,20 @@ static u8 getEndpoint(usb_devdesc devdesc)
|
|||||||
|
|
||||||
static int removal_cb(int result, void *usrdata)
|
static int removal_cb(int result, void *usrdata)
|
||||||
{
|
{
|
||||||
s32 fd = (s32) usrdata;
|
s32 fd = (s32) usrdata;
|
||||||
if (fd == deviceId)
|
if (fd == deviceId)
|
||||||
{
|
{
|
||||||
deviceId = 0;
|
deviceId = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open()
|
static void open()
|
||||||
{
|
{
|
||||||
if (deviceId != 0)
|
if (deviceId != 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_device_entry dev_entry[8];
|
usb_device_entry dev_entry[8];
|
||||||
u8 dev_count;
|
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
|
// Retrode has two entries in USB_GetDeviceList(), one for gamepads and one for SNES mouse
|
||||||
int i;
|
for (int i = 0; i < dev_count; ++i)
|
||||||
for (i = 0; i < dev_count; ++i)
|
|
||||||
{
|
{
|
||||||
|
if (!isRetrode(dev_entry[i]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
s32 fd;
|
s32 fd;
|
||||||
if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0)
|
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))
|
if (isRetrodeGamepad(devdesc))
|
||||||
{
|
{
|
||||||
deviceId = fd;
|
deviceId = fd;
|
||||||
replugRequired = false;
|
replugRequired = false;
|
||||||
endpoint = getEndpoint(devdesc);
|
endpoint = getEndpoint(devdesc);
|
||||||
bMaxPacketSize = devdesc.bMaxPacketSize0;
|
bMaxPacketSize = devdesc.bMaxPacketSize0;
|
||||||
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
|
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
USB_CloseDevice(&fd);
|
USB_CloseDevice(&fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup = true;
|
setup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Retrode_ScanPads()
|
void Retrode_ScanPads()
|
||||||
@ -100,7 +111,7 @@ void Retrode_ScanPads()
|
|||||||
|
|
||||||
uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize];
|
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)
|
if (USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf) != 5)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -115,21 +126,21 @@ void Retrode_ScanPads()
|
|||||||
// 4 = right Genesis/MD
|
// 4 = right Genesis/MD
|
||||||
|
|
||||||
// Button layout
|
// Button layout
|
||||||
// A=3,10
|
// A=3,10
|
||||||
// B=3,01
|
// B=3,01
|
||||||
// X=3,20
|
// X=3,20
|
||||||
// Y=3,02
|
// Y=3,02
|
||||||
// L=3,40
|
// L=3,40
|
||||||
// R=3,80
|
// R=3,80
|
||||||
// Up=2,9C
|
// Up=2,9C
|
||||||
// Down=2,64
|
// Down=2,64
|
||||||
// Left=1,9C
|
// Left=1,9C
|
||||||
// Right=1,64
|
// Right=1,64
|
||||||
// Start=3,08
|
// Start=3,08
|
||||||
// Select=3,04
|
// Select=3,04
|
||||||
|
|
||||||
u32 jp = 0;
|
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[2] & 0x64) == 0x64) ? PAD_BUTTON_DOWN : 0;
|
||||||
jp |= ((buf[1] & 0x9C) == 0x9C) ? PAD_BUTTON_LEFT : 0;
|
jp |= ((buf[1] & 0x9C) == 0x9C) ? PAD_BUTTON_LEFT : 0;
|
||||||
jp |= ((buf[1] & 0x64) == 0x64) ? PAD_BUTTON_RIGHT : 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] & 0x80) ? PAD_TRIGGER_R : 0;
|
||||||
|
|
||||||
jp |= (buf[3] & 0x08) ? PAD_BUTTON_START : 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,
|
// 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.
|
// and held buttons are not possible w/o saving the state.
|
||||||
@ -152,10 +163,10 @@ void Retrode_ScanPads()
|
|||||||
|
|
||||||
u32 Retrode_ButtonsHeld(int chan)
|
u32 Retrode_ButtonsHeld(int chan)
|
||||||
{
|
{
|
||||||
if(!setup)
|
if(!setup)
|
||||||
{
|
{
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
if (deviceId == 0)
|
if (deviceId == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -165,10 +176,10 @@ u32 Retrode_ButtonsHeld(int chan)
|
|||||||
|
|
||||||
char* Retrode_Status()
|
char* Retrode_Status()
|
||||||
{
|
{
|
||||||
open();
|
open();
|
||||||
if (replugRequired)
|
if (replugRequired)
|
||||||
return "please replug";
|
return "please replug";
|
||||||
return deviceId ? "connected" : "not found";
|
return deviceId ? "connected" : "not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef _RETRODE_H_
|
#ifndef _RETRODE_H_
|
||||||
#define _RETRODE_H_
|
#define _RETRODE_H_
|
||||||
|
|
||||||
|
#include <gctypes.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
#include <ogc/usb.h>
|
#include <ogc/usb.h>
|
||||||
|
|
||||||
#define USB_CLASS_XBOX360 0xFF
|
#define USB_CLASS_XBOX360 0xFF
|
||||||
|
#define XBOX360_VID 0x045e
|
||||||
|
#define XBOX360_PID 0x028e
|
||||||
|
|
||||||
static bool setup = false;
|
static bool setup = false;
|
||||||
static bool replugRequired = false;
|
static bool replugRequired = false;
|
||||||
static s32 deviceId = 0;
|
static s32 deviceId = 0;
|
||||||
static u8 endpoint_in = 0x81;
|
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 bMaxPacketSize = 20;
|
||||||
static u8 bConfigurationValue = 1;
|
static u8 bConfigurationValue = 1;
|
||||||
static u8 ATTRIBUTE_ALIGN(32) buf[20];
|
static u8 ATTRIBUTE_ALIGN(32) buf[20];
|
||||||
@ -28,159 +30,164 @@ static u8 getEndpoint(usb_devdesc devdesc)
|
|||||||
return devdesc.configurations->interfaces->endpoints->bEndpointAddress;
|
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 int read(s32 device_id, u8 endpoint, u8 bMaxPacketSize0);
|
||||||
|
|
||||||
static void start_reading(s32 device_id, u8 endpoint, u8 bMaxPacketSize0)
|
static void start_reading(s32 device_id, u8 endpoint, u8 bMaxPacketSize0)
|
||||||
{
|
{
|
||||||
if (isReading)
|
if (isReading)
|
||||||
{
|
{
|
||||||
// already reading
|
// already reading
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isReading = true;
|
isReading = true;
|
||||||
read(deviceId, endpoint_in, bMaxPacketSize0);
|
read(deviceId, endpoint_in, bMaxPacketSize0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop_reading()
|
static void stop_reading()
|
||||||
{
|
{
|
||||||
isReading = false;
|
isReading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_cb(int res, void *usrdata)
|
static int read_cb(int res, void *usrdata)
|
||||||
{
|
{
|
||||||
if (!isReading)
|
if (!isReading)
|
||||||
{
|
{
|
||||||
// stop reading
|
// stop reading
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The four startup messages have res = 3 and can be ignored
|
// NOTE: The four startup messages have res = 3 and can be ignored
|
||||||
|
|
||||||
// Button layout
|
// Button layout
|
||||||
// A=3,10
|
// A=3,10
|
||||||
// B=3,20
|
// B=3,20
|
||||||
// X=3,40
|
// X=3,40
|
||||||
// Y=3,80
|
// Y=3,80
|
||||||
// Up=2,01
|
// Up=2,01
|
||||||
// Right=2,08
|
// Right=2,08
|
||||||
// Left=2,04
|
// Left=2,04
|
||||||
// Down=2,02
|
// Down=2,02
|
||||||
// L=3,01
|
// L=3,01
|
||||||
// R=3,02
|
// R=3,02
|
||||||
// L2=4,FF ; analog trigger
|
// L2=4,FF ; analog trigger
|
||||||
// R3=5,FF ; analog trigger
|
// R3=5,FF ; analog trigger
|
||||||
// L3=2,40 ; left hat button
|
// L3=2,40 ; left hat button
|
||||||
// L3=2,80 ; right hat button
|
// L3=2,80 ; right hat button
|
||||||
// XBOX=3,04
|
// XBOX=3,04
|
||||||
// Start=2,10
|
// Start=2,10
|
||||||
// Back=2,20
|
// Back=2,20
|
||||||
// LStickX=6/7,FF ; <low byte>,<high byte>
|
// LStickX=6/7,FF ; <low byte>,<high byte>
|
||||||
// LStickY=8/9,FF
|
// LStickY=8/9,FF
|
||||||
// RStickX=10/11,FF
|
// RStickX=10/11,FF
|
||||||
// RStickY=12/13,FF
|
// RStickY=12/13,FF
|
||||||
|
|
||||||
if (res == 20)
|
if (res == 20)
|
||||||
{
|
{
|
||||||
jp = 0;
|
jp = 0;
|
||||||
jp |= ((buf[2] & 0x01) == 0x01) ? PAD_BUTTON_UP : 0;
|
jp |= ((buf[2] & 0x01) == 0x01) ? PAD_BUTTON_UP : 0;
|
||||||
jp |= ((buf[2] & 0x02) == 0x02) ? PAD_BUTTON_DOWN : 0;
|
jp |= ((buf[2] & 0x02) == 0x02) ? PAD_BUTTON_DOWN : 0;
|
||||||
jp |= ((buf[2] & 0x04) == 0x04) ? PAD_BUTTON_LEFT : 0;
|
jp |= ((buf[2] & 0x04) == 0x04) ? PAD_BUTTON_LEFT : 0;
|
||||||
jp |= ((buf[2] & 0x08) == 0x08) ? PAD_BUTTON_RIGHT : 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] & 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] & 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] & 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] & 0x80) == 0x80) ? PAD_BUTTON_X : 0; // XBOX360 Y button maps to X
|
||||||
|
|
||||||
jp |= ((buf[3] & 0x01) == 0x01) ? PAD_TRIGGER_L : 0;
|
jp |= ((buf[3] & 0x01) == 0x01) ? PAD_TRIGGER_L : 0;
|
||||||
jp |= ((buf[3] & 0x02) == 0x02) ? PAD_TRIGGER_R : 0;
|
jp |= ((buf[3] & 0x02) == 0x02) ? PAD_TRIGGER_R : 0;
|
||||||
|
|
||||||
jp |= ((buf[2] & 0x10) == 0x10) ? PAD_BUTTON_START : 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
|
jp |= ((buf[2] & 0x20) == 0x20) ? PAD_TRIGGER_Z : 0; // XBOX360 back button maps to Z
|
||||||
|
|
||||||
// triggers
|
// triggers
|
||||||
jp |= (buf[4] > 128) ? PAD_TRIGGER_L : 0;
|
jp |= (buf[4] > 128) ? PAD_TRIGGER_L : 0;
|
||||||
jp |= (buf[5] > 128) ? PAD_TRIGGER_R : 0;
|
jp |= (buf[5] > 128) ? PAD_TRIGGER_R : 0;
|
||||||
|
|
||||||
// left stick
|
// left stick
|
||||||
int16_t lx = (buf[7] << 8) | buf[6]; // [-32768, 32767]
|
int16_t lx = (buf[7] << 8) | buf[6]; // [-32768, 32767]
|
||||||
int16_t ly = (buf[9] << 8) | buf[8]; // [-32768, 32767]
|
int16_t ly = (buf[9] << 8) | buf[8]; // [-32768, 32767]
|
||||||
jp |= (ly > 16384) ? PAD_BUTTON_UP : 0;
|
jp |= (ly > 16384) ? PAD_BUTTON_UP : 0;
|
||||||
jp |= (ly < -16384) ? PAD_BUTTON_DOWN : 0;
|
jp |= (ly < -16384) ? PAD_BUTTON_DOWN : 0;
|
||||||
jp |= (lx < -16384) ? PAD_BUTTON_LEFT : 0;
|
jp |= (lx < -16384) ? PAD_BUTTON_LEFT : 0;
|
||||||
jp |= (lx > 16384) ? PAD_BUTTON_RIGHT : 0;
|
jp |= (lx > 16384) ? PAD_BUTTON_RIGHT : 0;
|
||||||
|
|
||||||
// right stick
|
// right stick
|
||||||
int16_t rx = (buf[11] << 8) | buf[10]; // [-32768, 32767]
|
int16_t rx = (buf[11] << 8) | buf[10]; // [-32768, 32767]
|
||||||
int16_t ry = (buf[13] << 8) | buf[12]; // [-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_UP : 0;
|
||||||
jp |= (ry < -16384) ? PAD_BUTTON_B : 0; // XBOX360 A button maps to B
|
jp |= (ry < -16384) ? PAD_BUTTON_DOWN : 0;
|
||||||
jp |= (rx < -16384) ? PAD_BUTTON_Y : 0; // XBOX360 X button maps to Y
|
jp |= (rx < -16384) ? PAD_BUTTON_LEFT : 0;
|
||||||
jp |= (rx > 16384) ? PAD_BUTTON_A : 0; // XBOX360 B button maps to A
|
jp |= (rx > 16384) ? PAD_BUTTON_RIGHT : 0;
|
||||||
|
|
||||||
// XBOX button to switch to next player
|
// XBOX button to switch to next player
|
||||||
if ((buf[3] & 0x04) == 0x04)
|
if ((buf[3] & 0x04) == 0x04)
|
||||||
{
|
{
|
||||||
xboxButtonCount++;
|
xboxButtonCount++;
|
||||||
// count = 2 means you have to push the button 1x to switch players
|
// 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
|
// count = 10 means you have to push the button 5x to switch players
|
||||||
if (xboxButtonCount >= 2)
|
if (xboxButtonCount >= 2)
|
||||||
{
|
{
|
||||||
nextPlayer = true;
|
nextPlayer = true;
|
||||||
xboxButtonCount = 0;
|
xboxButtonCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read again
|
// read again
|
||||||
read(deviceId, endpoint_in, bMaxPacketSize);
|
read(deviceId, endpoint_in, bMaxPacketSize);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// never call directly
|
// never call directly
|
||||||
static int read(s32 device_id, u8 endpoint, u8 bMaxPacketSize0)
|
static int read(s32 device_id, u8 endpoint, u8 bMaxPacketSize0)
|
||||||
{
|
{
|
||||||
// need to use async, because USB_ReadIntrMsg() blocks until a button is pressed
|
// 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);
|
return USB_ReadIntrMsgAsync(device_id, endpoint, sizeof(buf), buf, &read_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void turnOnLED()
|
static void turnOnLED()
|
||||||
{
|
{
|
||||||
uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x01, 0x03, 0x06 + player };
|
uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x01, 0x03, 0x06 + player };
|
||||||
USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf);
|
USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void increasePlayer()
|
static void increasePlayer()
|
||||||
{
|
{
|
||||||
player++;
|
player++;
|
||||||
if (player > 3)
|
if (player > 3)
|
||||||
{
|
{
|
||||||
player = 0;
|
player = 0;
|
||||||
}
|
}
|
||||||
turnOnLED();
|
turnOnLED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rumble(s32 device_id, u8 left, u8 right)
|
void rumble(s32 device_id, u8 left, u8 right)
|
||||||
{
|
{
|
||||||
uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 };
|
uint8_t ATTRIBUTE_ALIGN(32) buf[] = { 0x00, 0x08, 0x00, left, right, 0x00, 0x00, 0x00 };
|
||||||
USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf);
|
USB_WriteIntrMsg(deviceId, endpoint_out, sizeof(buf), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int removal_cb(int result, void *usrdata)
|
static int removal_cb(int result, void *usrdata)
|
||||||
{
|
{
|
||||||
s32 fd = (s32) usrdata;
|
s32 fd = (s32) usrdata;
|
||||||
if (fd == deviceId)
|
if (fd == deviceId)
|
||||||
{
|
{
|
||||||
stop_reading();
|
stop_reading();
|
||||||
deviceId = 0;
|
deviceId = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adapted from RetroArch input/drivers_hid/wiiusb_hid.c#wiiusb_get_description()
|
// 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++)
|
for (c = 0; c < devdesc->bNumConfigurations; c++)
|
||||||
{
|
{
|
||||||
const usb_configurationdesc *config = &devdesc->configurations[c];
|
const usb_configurationdesc *config = &devdesc->configurations[c];
|
||||||
|
|
||||||
for (i = 0; i < (int)config->bNumInterfaces; i++)
|
for (i = 0; i < (int)config->bNumInterfaces; i++)
|
||||||
{
|
{
|
||||||
const usb_interfacedesc *inter = &config->interfaces[i];
|
const usb_interfacedesc *inter = &config->interfaces[i];
|
||||||
|
|
||||||
for (k = 0; k < (int)inter->bNumEndpoints; k++)
|
for (k = 0; k < (int)inter->bNumEndpoints; k++)
|
||||||
{
|
{
|
||||||
const usb_endpointdesc *epdesc = &inter->endpoints[k];
|
const usb_endpointdesc *epdesc = &inter->endpoints[k];
|
||||||
bool is_int = (epdesc->bmAttributes & 0x03) == USB_ENDPOINT_INTERRUPT;
|
bool is_int = (epdesc->bmAttributes & 0x03) == USB_ENDPOINT_INTERRUPT;
|
||||||
bool is_out = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_OUT;
|
bool is_out = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_OUT;
|
||||||
bool is_in = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_IN;
|
bool is_in = (epdesc->bEndpointAddress & 0x80) == USB_ENDPOINT_IN;
|
||||||
|
|
||||||
if (is_int)
|
if (is_int)
|
||||||
{
|
{
|
||||||
if (is_in)
|
if (is_in)
|
||||||
{
|
{
|
||||||
//endpoint_in = epdesc->bEndpointAddress;
|
//endpoint_in = epdesc->bEndpointAddress;
|
||||||
//endpoint_in_max_size = epdesc->wMaxPacketSize;
|
//endpoint_in_max_size = epdesc->wMaxPacketSize;
|
||||||
}
|
}
|
||||||
if (is_out)
|
if (is_out)
|
||||||
{
|
{
|
||||||
endpoint_out = epdesc->bEndpointAddress;
|
endpoint_out = epdesc->bEndpointAddress;
|
||||||
//endpoint_out_max_size = epdesc->wMaxPacketSize;
|
//endpoint_out_max_size = epdesc->wMaxPacketSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open()
|
static void open()
|
||||||
{
|
{
|
||||||
if (deviceId != 0)
|
if (deviceId != 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_device_entry dev_entry[8];
|
usb_device_entry dev_entry[8];
|
||||||
u8 dev_count;
|
u8 dev_count;
|
||||||
if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_XBOX360, &dev_count) < 0)
|
if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_XBOX360, &dev_count) < 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
for (int i = 0; i < dev_count; ++i)
|
||||||
for (i = 0; i < dev_count; ++i)
|
{
|
||||||
{
|
if (!isXBOX360(dev_entry[i]))
|
||||||
s32 fd;
|
{
|
||||||
if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0)
|
continue;
|
||||||
{
|
}
|
||||||
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;
|
usb_devdesc devdesc;
|
||||||
if (USB_GetDescriptors(fd, &devdesc) < 0)
|
if (USB_GetDescriptors(fd, &devdesc) < 0)
|
||||||
{
|
{
|
||||||
// You have to replug the XBOX360 controller!
|
// You have to replug the XBOX360 controller!
|
||||||
replugRequired = true;
|
replugRequired = true;
|
||||||
USB_CloseDevice(&fd);
|
USB_CloseDevice(&fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isXBOX360(devdesc) && USB_SetConfiguration(fd, bConfigurationValue) >= 0)
|
if (isXBOX360Gamepad(devdesc) && USB_SetConfiguration(fd, bConfigurationValue) >= 0)
|
||||||
{
|
{
|
||||||
deviceId = fd;
|
deviceId = fd;
|
||||||
replugRequired = false;
|
replugRequired = false;
|
||||||
wiiusb_get_description(&dev_entry[i], &devdesc);
|
wiiusb_get_description(&dev_entry[i], &devdesc);
|
||||||
turnOnLED();
|
turnOnLED();
|
||||||
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
|
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
USB_CloseDevice(&fd);
|
USB_CloseDevice(&fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup = true;
|
setup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XBOX360_ScanPads()
|
void XBOX360_ScanPads()
|
||||||
@ -285,19 +295,19 @@ void XBOX360_ScanPads()
|
|||||||
|
|
||||||
u32 XBOX360_ButtonsHeld(int chan)
|
u32 XBOX360_ButtonsHeld(int chan)
|
||||||
{
|
{
|
||||||
if(!setup)
|
if(!setup)
|
||||||
{
|
{
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
if (deviceId == 0)
|
if (deviceId == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (nextPlayer)
|
if (nextPlayer)
|
||||||
{
|
{
|
||||||
nextPlayer = false;
|
nextPlayer = false;
|
||||||
increasePlayer();
|
increasePlayer();
|
||||||
}
|
}
|
||||||
if (chan != player)
|
if (chan != player)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -307,10 +317,10 @@ u32 XBOX360_ButtonsHeld(int chan)
|
|||||||
|
|
||||||
char* XBOX360_Status()
|
char* XBOX360_Status()
|
||||||
{
|
{
|
||||||
open();
|
open();
|
||||||
if (replugRequired)
|
if (replugRequired)
|
||||||
return "please replug";
|
return "please replug";
|
||||||
return deviceId ? "connected" : "not found";
|
return deviceId ? "connected" : "not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user