Skip to content

Commit 60a3bb6

Browse files
committed
Completed support for multiple gamepad devices
Added deviceIndex to status handler callback Removed manufacturer/product/device values from gamepad state structure, obsoleted by USPiDeviceGetInformation Added PS3 GamePad specific activation messages Better calculation of HID report size
1 parent 34447cb commit 60a3bb6

File tree

5 files changed

+124
-55
lines changed

5 files changed

+124
-55
lines changed

SDL2/src/joystick/raspberry/SDL_sysjoystick.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct SDL_joylist_item
4949
int device_instance;
5050
char *name;
5151
SDL_JoystickGUID guid;
52+
unsigned int devnum;
5253
struct joystick_hwdata *hwdata;
5354
struct SDL_joylist_item *next;
5455

@@ -173,13 +174,18 @@ NES_JoystickUpdate(SDL_Joystick * joystick)
173174
#ifdef HAVE_USPI
174175
#include <uspi.h>
175176

176-
SDL_Joystick * uspi_joystick;
177+
SDL_Joystick * uspi_joystick[4];
177178

178179
static void
179-
USPiGamePadStatusHandler (const USPiGamePadState *pGamePadState)
180+
USPiGamePadStatusHandler (unsigned nDeviceIndex, const USPiGamePadState *pGamePadState)
180181
{
181182
int i, value, bmMask, center, steps1, steps2;
182-
struct joystick_hwdata *hwdata = uspi_joystick->hwdata;
183+
SDL_Joystick *joystick = uspi_joystick[nDeviceIndex];
184+
185+
if (joystick == NULL)
186+
return;
187+
188+
struct joystick_hwdata *hwdata = joystick->hwdata;
183189

184190
for (i = 0; i < pGamePadState->naxes; i++) {
185191
value = pGamePadState->axes[i].value;
@@ -188,25 +194,25 @@ USPiGamePadStatusHandler (const USPiGamePadState *pGamePadState)
188194
steps1 = 32767000 / (center - pGamePadState->axes[i].minimum);
189195
steps2 = 32767000 / (pGamePadState->axes[i].maximum - center);
190196
if (value < center)
191-
SDL_PrivateJoystickAxis(uspi_joystick, i, ((value - center) * steps1 - 500) / 1000);
197+
SDL_PrivateJoystickAxis(joystick, i, ((value - center) * steps1 - 500) / 1000);
192198
else
193-
SDL_PrivateJoystickAxis(uspi_joystick, i, ((value - center) * steps2 + 500) / 1000);
199+
SDL_PrivateJoystickAxis(joystick, i, ((value - center) * steps2 + 500) / 1000);
194200
hwdata->axes[i] = value;
195201
}
196202
}
197203

198204
for (i = 0; i < pGamePadState->nhats; i++) {
199205
value = pGamePadState->hats[i];
200206
if (hwdata->hats[i] != value) {
201-
SDL_PrivateJoystickHat(uspi_joystick, i, value);
207+
SDL_PrivateJoystickHat(joystick, i, value);
202208
hwdata->hats[i] = value;
203209
}
204210
}
205211

206212
if (pGamePadState->nbuttons > 0) {
207213
for (i = 0, bmMask = 1 << (pGamePadState->nbuttons - 1); i < pGamePadState->nbuttons; i++, bmMask >>= 1) {
208214
if ((pGamePadState->buttons & bmMask) != (hwdata->buttons & bmMask)) {
209-
SDL_PrivateJoystickButton(uspi_joystick, i, (pGamePadState->buttons & bmMask) ? SDL_PRESSED : SDL_RELEASED);
215+
SDL_PrivateJoystickButton(joystick, i, (pGamePadState->buttons & bmMask) ? SDL_PRESSED : SDL_RELEASED);
210216
}
211217
}
212218
}
@@ -218,7 +224,7 @@ USPi_JoystickOpen(SDL_Joystick * joystick, int device_index)
218224
{
219225
int i;
220226
struct joystick_hwdata *hwdata = joystick->hwdata;
221-
const USPiGamePadState *pGamePadState = USPiGamePadGetStatus(0);
227+
const USPiGamePadState *pGamePadState = USPiGamePadGetStatus(hwdata->item->devnum);
222228

223229
joystick->naxes = pGamePadState->naxes;
224230
for (i = 0; i < pGamePadState->naxes; i++) {
@@ -235,15 +241,15 @@ USPi_JoystickOpen(SDL_Joystick * joystick, int device_index)
235241

236242
joystick->nhats = 0;
237243

238-
uspi_joystick = joystick;
244+
uspi_joystick[hwdata->item->devnum] = joystick;
239245
USPiGamePadRegisterStatusHandler(USPiGamePadStatusHandler);
240246
}
241247

242248
static void
243249
USPi_JoystickClose(SDL_Joystick * joystick)
244250
{
245251
USPiGamePadRegisterStatusHandler(NULL);
246-
uspi_joystick = NULL;
252+
uspi_joystick[joystick->hwdata->item->devnum] = NULL;
247253
}
248254

249255
#endif // HAVE_USPI
@@ -286,25 +292,27 @@ SDL_SYS_JoystickInit(void)
286292

287293
#ifdef HAVE_USPI
288294

289-
if (USPiGamePadAvailable()) {
295+
for (int deviceIndex = 0; deviceIndex < USPiGamePadAvailable(); deviceIndex++) {
290296
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
291297
if (item == NULL) {
292298
return -1;
293299
}
294300

295-
SDL_zerop(item);
301+
TUSPiDeviceInformation info;
302+
USPiDeviceGetInformation (GAMEPAD_CLASS, deviceIndex, &info);
296303

297-
item->name = SDL_strdup("USPi Gamepad");
304+
SDL_zerop(item);
305+
item->devnum = deviceIndex;
306+
item->name = SDL_strdup(info.pProduct);
298307

299-
const USPiGamePadState *pGamePadState = USPiGamePadGetStatus(0);
300308
Uint16 *guid16 = (Uint16 *) ((char *) &item->guid.data);
301309
*(guid16++) = SDL_SwapLE16(3);
302310
*(guid16++) = 0;
303-
*(guid16++) = SDL_SwapLE16(pGamePadState->idVendor);
311+
*(guid16++) = SDL_SwapLE16(info.idVendor);
304312
*(guid16++) = 0;
305-
*(guid16++) = SDL_SwapLE16(pGamePadState->idProduct);
313+
*(guid16++) = SDL_SwapLE16(info.idProduct);
306314
*(guid16++) = 0;
307-
*(guid16++) = SDL_SwapLE16(pGamePadState->idVersion);
315+
*(guid16++) = SDL_SwapLE16(info.bcdDevice);
308316
*(guid16++) = 0;
309317

310318
item->open = USPi_JoystickOpen;

uspi/include/uspi.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,11 @@ int USPiGamePadAvailable (void);
147147
#define MAX_AXIS 6
148148
#define MAX_HATS 6
149149

150-
typedef struct USPiGamePadState {
151-
unsigned short idVendor;
152-
unsigned short idProduct;
153-
unsigned short idVersion;
154-
150+
typedef struct USPiGamePadState
151+
{
155152
int naxes;
156-
struct {
153+
struct
154+
{
157155
int value;
158156
int minimum;
159157
int maximum;
@@ -170,7 +168,7 @@ USPiGamePadState;
170168
// returns 0 on failure
171169
const USPiGamePadState *USPiGamePadGetStatus (unsigned nDeviceIndex); // nDeviceIndex is 0-based
172170

173-
typedef void TGamePadStatusHandler (const USPiGamePadState *pGamePadState);
171+
typedef void TGamePadStatusHandler (unsigned nDeviceIndex, const USPiGamePadState *pGamePadState);
174172
void USPiGamePadRegisterStatusHandler (TGamePadStatusHandler *pStatusHandler);
175173

176174
//

uspi/include/uspi/usbgamepad.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,10 @@
2828
#include <uspi/types.h>
2929
#include <uspi.h>
3030

31-
#define BOOT_REPORT_SIZE 8
32-
33-
typedef void TGamePadStatusHandler (const USPiGamePadState *pGamepadState);
34-
3531
typedef struct TUSBGamePadDevice
3632
{
3733
TUSBDevice m_USBDevice;
34+
unsigned m_nDeviceIndex;
3835

3936
u8 m_ucInterfaceNumber;
4037
u8 m_ucAlternateSetting;

uspi/lib/usbgamepad.c

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ static const char FromUSBPad[] = "usbpad";
7979

8080
static boolean USBGamePadDeviceStartRequest (TUSBGamePadDevice *pThis);
8181
static void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *pContext);
82+
static void USBGamePadDevicePS3Configure (TUSBGamePadDevice *pThis);
8283

8384
void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBDevice *pDevice)
8485
{
@@ -91,13 +92,9 @@ void USBGamePadDevice (TUSBGamePadDevice *pThis, TUSBDevice *pDevice)
9192
pThis->m_pEndpointOut = 0;
9293
pThis->m_pStatusHandler = 0;
9394
pThis->m_pURB = 0;
94-
pThis->m_pReportBuffer = 0;
9595
pThis->m_pHIDReportDescriptor = 0;
9696
pThis->m_usReportDescriptorLength = 0;
97-
98-
pThis->m_State.idVendor = pDevice->m_pDeviceDesc->idVendor;
99-
pThis->m_State.idProduct = pDevice->m_pDeviceDesc->idProduct;
100-
pThis->m_State.idVersion = pDevice->m_pDeviceDesc->bcdDevice;
97+
pThis->m_nReportSize = 0;
10198

10299
pThis->m_State.naxes = 0;
103100
for (int i = 0; i < MAX_AXIS; i++) {
@@ -202,8 +199,8 @@ static void USBGamePadDeviceDecodeReport(TUSBGamePadDevice *pThis)
202199
s32 item, arg;
203200
u32 offset = 0, size = 0, count = 0;
204201
s32 lmax = UNDEFINED, lmin = UNDEFINED, pmin = UNDEFINED, pmax = UNDEFINED;
205-
s32 naxes = 0, nhats = 0, reportsize = 0;
206-
u32 state = None;
202+
s32 naxes = 0, nhats = 0;
203+
u32 id = 0, state = None;
207204

208205
u8 *pReportBuffer = pThis->m_pReportBuffer;
209206
s8 *pHIDReportDescriptor = (s8 *)pThis->m_pHIDReportDescriptor;
@@ -237,8 +234,12 @@ static void USBGamePadDeviceDecodeReport(TUSBGamePadDevice *pThis)
237234
}
238235

239236
if ((item & 0xFC) == HID_REPORT_ID) {
240-
if (BitGetUnsigned(pReportBuffer, 0, 8) != arg)
237+
if (id != 0)
241238
break;
239+
id = BitGetUnsigned(pReportBuffer, 0, 8);
240+
if (id != 0 && id != arg)
241+
return;
242+
id = arg;
242243
offset = 8;
243244
}
244245

@@ -321,7 +322,6 @@ static void USBGamePadDeviceDecodeReport(TUSBGamePadDevice *pThis)
321322
}
322323
}
323324
offset += count * size;
324-
reportsize += count * size;
325325
break;
326326
case HID_OUTPUT:
327327
break;
@@ -331,7 +331,7 @@ static void USBGamePadDeviceDecodeReport(TUSBGamePadDevice *pThis)
331331
pState->naxes = naxes;
332332
pState->nhats = nhats;
333333

334-
pThis->m_nReportSize = (reportsize + 7) / 8;
334+
pThis->m_nReportSize = (offset + 7) / 8;
335335
}
336336

337337
boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice)
@@ -431,18 +431,38 @@ boolean USBGamePadDeviceConfigure (TUSBDevice *pUSBDevice)
431431
}
432432
//DebugHexdump (pThis->m_pHIDReportDescriptor, pHIDDesc->wReportDescriptorLength, "hid");
433433

434+
pThis->m_pReportBuffer[0] = 0;
435+
USBGamePadDeviceDecodeReport (pThis);
436+
434437
if (!USBDeviceConfigure (&pThis->m_USBDevice))
435438
{
436439
LogWrite (FromUSBPad, LOG_ERROR, "Cannot set configuration");
437440

438441
return FALSE;
439442
}
440443

441-
USBGamePadDeviceGetReport (pThis);
444+
if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice),
445+
USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
446+
REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE,
447+
pThis->m_ucAlternateSetting,
448+
pThis->m_ucInterfaceNumber, 0, 0) < 0)
449+
{
450+
LogWrite (FromUSBPad, LOG_ERROR, "Cannot set interface");
451+
452+
return FALSE;
453+
}
454+
455+
pThis->m_nDeviceIndex = s_nDeviceNumber++;
456+
457+
if ( pUSBDevice->m_pDeviceDesc->idVendor == 0x054c
458+
&& pUSBDevice->m_pDeviceDesc->idProduct == 0x0268)
459+
{
460+
USBGamePadDevicePS3Configure (pThis);
461+
}
442462

443463
TString DeviceName;
444464
String (&DeviceName);
445-
StringFormat (&DeviceName, "upad%u", s_nDeviceNumber++);
465+
StringFormat (&DeviceName, "upad%u", pThis->m_nDeviceIndex);
446466
DeviceNameServiceAddDevice (DeviceNameServiceGet (), StringGet (&DeviceName), pThis, FALSE);
447467

448468
_String (&DeviceName);
@@ -488,7 +508,7 @@ void USBGamePadDeviceCompletionRoutine (TUSBRequest *pURB, void *pParam, void *p
488508
if (pThis->m_pHIDReportDescriptor != 0 && pThis->m_pStatusHandler != 0)
489509
{
490510
USBGamePadDeviceDecodeReport (pThis);
491-
(*pThis->m_pStatusHandler) (&pThis->m_State);
511+
(*pThis->m_pStatusHandler) (pThis->m_nDeviceIndex - 1, &pThis->m_State);
492512
}
493513
}
494514

@@ -506,8 +526,55 @@ void USBGamePadDeviceGetReport (TUSBGamePadDevice *pThis)
506526
REQUEST_IN | REQUEST_CLASS | REQUEST_TO_INTERFACE,
507527
GET_REPORT, (REPORT_TYPE_INPUT << 8) | 0x00,
508528
pThis->m_ucInterfaceNumber,
509-
pThis->m_pReportBuffer, 8) > 0)
529+
pThis->m_pReportBuffer, pThis->m_nReportSize) > 0)
510530
{
511531
USBGamePadDeviceDecodeReport (pThis);
512532
}
513533
}
534+
535+
void USBGamePadDevicePS3Configure (TUSBGamePadDevice *pThis)
536+
{
537+
static u8 writeBuf[] =
538+
{
539+
0x00, 0x00, 0x00, 0x00, 0x00,
540+
0x00, 0x00, 0x00, 0x00, 0x00,
541+
0xff, 0x27, 0x10, 0x00, 0x32,
542+
0xff, 0x27, 0x10, 0x00, 0x32,
543+
0xff, 0x27, 0x10, 0x00, 0x32,
544+
0xff, 0x27, 0x10, 0x00, 0x32,
545+
0x00, 0x00, 0x00, 0x00, 0x00,
546+
0x00, 0x00, 0x00, 0x00, 0x00,
547+
0x00, 0x00, 0x00, 0x00, 0x00,
548+
0x00, 0x00, 0x00
549+
};
550+
551+
static u8 leds[] =
552+
{
553+
0x00, // OFF
554+
0x01, // LED1
555+
0x02, // LED2
556+
0x04, // LED3
557+
0x08, // LED4
558+
};
559+
560+
/* Special PS3 Controller enable commands */
561+
pThis->m_pReportBuffer[0] = 0x42;
562+
pThis->m_pReportBuffer[1] = 0x0c;
563+
pThis->m_pReportBuffer[2] = 0x00;
564+
pThis->m_pReportBuffer[3] = 0x00;
565+
DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice),
566+
USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
567+
REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE,
568+
SET_REPORT, (REPORT_TYPE_FEATURE << 8) | 0xf4,
569+
pThis->m_ucInterfaceNumber,
570+
pThis->m_pReportBuffer, 4);
571+
572+
/* Turn on LED */
573+
writeBuf[9] |= (u8)(leds[pThis->m_nDeviceIndex] << 1);
574+
DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice),
575+
USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
576+
REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE,
577+
SET_REPORT, (REPORT_TYPE_OUTPUT << 8) | 0x01,
578+
pThis->m_ucInterfaceNumber,
579+
writeBuf, 48);
580+
}

uspi/lib/uspilibrary.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//
44
// USPi - An USB driver for Raspberry Pi written in C
55
// Copyright (C) 2014 R. Stange <[email protected]>
6-
//
6+
//
77
// This program is free software: you can redistribute it and/or modify
88
// it under the terms of the GNU General Public License as published by
99
// the Free Software Foundation, either version 3 of the License, or
@@ -56,7 +56,7 @@ int USPiInitialize (void)
5656
}
5757

5858
s_pLibrary->pUKBD1 = (TUSBKeyboardDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "ukbd1", FALSE);
59-
59+
6060
s_pLibrary->pUMouse1 = (TUSBMouseDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "umouse1", FALSE);
6161

6262
for (unsigned i = 0; i < MAX_DEVICES; i++)
@@ -155,7 +155,7 @@ int USPiMassStorageDeviceRead (unsigned long long ullOffset, void *pBuffer, unsi
155155
{
156156
return -1;
157157
}
158-
158+
159159
if (USBBulkOnlyMassStorageDeviceSeek (s_pLibrary->pUMSD[nDeviceIndex], ullOffset) != ullOffset)
160160
{
161161
return -1;
@@ -232,15 +232,14 @@ void USPiGamePadRegisterStatusHandler (TGamePadStatusHandler *pStatusHandler)
232232
{
233233
assert (s_pLibrary != 0);
234234

235-
for (unsigned i = 0; i < MAX_DEVICES; i++)
236-
{
237-
if (s_pLibrary->pUPAD[i] == 0)
238-
{
239-
break;
240-
}
241-
242-
USBGamePadDeviceRegisterStatusHandler (s_pLibrary->pUPAD[i], pStatusHandler);
243-
}
235+
unsigned i;
236+
for (i = 0; i < MAX_DEVICES; i++)
237+
{
238+
if (s_pLibrary->pUPAD[i] != 0)
239+
{
240+
USBGamePadDeviceRegisterStatusHandler (s_pLibrary->pUPAD[i], pStatusHandler);
241+
}
242+
}
244243
}
245244

246245
const USPiGamePadState *USPiGamePadGetStatus (unsigned nDeviceIndex)
@@ -252,7 +251,7 @@ const USPiGamePadState *USPiGamePadGetStatus (unsigned nDeviceIndex)
252251
{
253252
return 0;
254253
}
255-
254+
256255
USBGamePadDeviceGetReport (s_pLibrary->pUPAD[nDeviceIndex]);
257256

258257
return &s_pLibrary->pUPAD[nDeviceIndex]->m_State;

0 commit comments

Comments
 (0)