Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/joystick/hidapi/SDL_hidapi_gamecube.c
21409 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22
23
#ifdef SDL_JOYSTICK_HIDAPI
24
25
#include "../../SDL_hints_c.h"
26
#include "../SDL_sysjoystick.h"
27
#include "SDL_hidapijoystick_c.h"
28
#include "SDL_hidapi_rumble.h"
29
#include "../../hidapi/SDL_hidapi_c.h"
30
31
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
32
33
// Define this if you want to log all packets from the controller
34
#if 0
35
#define DEBUG_GAMECUBE_PROTOCOL
36
#endif
37
38
#define MAX_CONTROLLERS 4
39
40
typedef struct
41
{
42
bool pc_mode;
43
SDL_JoystickID joysticks[MAX_CONTROLLERS];
44
Uint8 wireless[MAX_CONTROLLERS];
45
Uint8 min_axis[MAX_CONTROLLERS * SDL_GAMEPAD_AXIS_COUNT];
46
Uint8 max_axis[MAX_CONTROLLERS * SDL_GAMEPAD_AXIS_COUNT];
47
Uint8 rumbleAllowed[MAX_CONTROLLERS];
48
Uint8 rumble[1 + MAX_CONTROLLERS];
49
// Without this variable, hid_write starts to lag a TON
50
bool rumbleUpdate;
51
bool useRumbleBrake;
52
} SDL_DriverGameCube_Context;
53
54
static void HIDAPI_DriverGameCube_RegisterHints(SDL_HintCallback callback, void *userdata)
55
{
56
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, callback, userdata);
57
}
58
59
static void HIDAPI_DriverGameCube_UnregisterHints(SDL_HintCallback callback, void *userdata)
60
{
61
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, callback, userdata);
62
}
63
64
static bool HIDAPI_DriverGameCube_IsEnabled(void)
65
{
66
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
67
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
68
SDL_HIDAPI_DEFAULT));
69
}
70
71
static bool HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
72
{
73
if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) {
74
// Nintendo Co., Ltd. Wii U GameCube Controller Adapter
75
return true;
76
}
77
if (vendor_id == USB_VENDOR_DRAGONRISE &&
78
(product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER1 ||
79
product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER2)) {
80
// EVORETRO GameCube Controller Adapter
81
return true;
82
}
83
return false;
84
}
85
86
static void ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index)
87
{
88
SDL_memset(&ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT], 128 - 88, SDL_GAMEPAD_AXIS_COUNT);
89
SDL_memset(&ctx->max_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT], 128 + 88, SDL_GAMEPAD_AXIS_COUNT);
90
91
// Trigger axes may have a higher resting value
92
ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT + SDL_GAMEPAD_AXIS_LEFT_TRIGGER] = 40;
93
ctx->min_axis[joystick_index * SDL_GAMEPAD_AXIS_COUNT + SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] = 40;
94
}
95
96
static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
97
{
98
if (hint) {
99
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
100
ctx->useRumbleBrake = SDL_GetStringBoolean(hint, false);
101
}
102
}
103
104
static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
105
{
106
SDL_DriverGameCube_Context *ctx;
107
Uint8 packet[37];
108
Uint8 *curSlot;
109
Uint8 i;
110
int size;
111
Uint8 initMagic = 0x13;
112
Uint8 rumbleMagic = 0x11;
113
114
#ifdef HAVE_ENABLE_GAMECUBE_ADAPTORS
115
SDL_EnableGameCubeAdaptors();
116
#endif
117
118
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
119
if (!ctx) {
120
return false;
121
}
122
device->context = ctx;
123
124
ctx->rumble[0] = rumbleMagic;
125
126
if (device->vendor_id != USB_VENDOR_NINTENDO) {
127
ctx->pc_mode = true;
128
}
129
130
if (ctx->pc_mode) {
131
ResetAxisRange(ctx, 0);
132
HIDAPI_JoystickConnected(device, &ctx->joysticks[0]);
133
} else {
134
// This is all that's needed to initialize the device. Really!
135
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
136
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
137
"HIDAPI_DriverGameCube_InitDevice(): Couldn't initialize WUP-028");
138
return false;
139
}
140
141
// Wait for the adapter to initialize
142
SDL_Delay(10);
143
144
// Add all the applicable joysticks
145
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
146
#ifdef DEBUG_GAMECUBE_PROTOCOL
147
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
148
#endif
149
if (size < 37 || packet[0] != 0x21) {
150
continue; // Nothing to do yet...?
151
}
152
153
// Go through all 4 slots
154
curSlot = packet + 1;
155
for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
156
ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
157
158
// Only allow rumble if the adapter's second USB cable is connected
159
ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) && !ctx->wireless[i];
160
161
if (curSlot[0] & 0x30) { // 0x10 - Wired, 0x20 - Wireless
162
if (ctx->joysticks[i] == 0) {
163
ResetAxisRange(ctx, i);
164
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
165
}
166
} else {
167
if (ctx->joysticks[i] != 0) {
168
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
169
ctx->joysticks[i] = 0;
170
}
171
continue;
172
}
173
}
174
}
175
}
176
177
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE,
178
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
179
180
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
181
182
return true;
183
}
184
185
static int HIDAPI_DriverGameCube_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
186
{
187
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
188
Uint8 i;
189
190
for (i = 0; i < 4; ++i) {
191
if (instance_id == ctx->joysticks[i]) {
192
return i;
193
}
194
}
195
return -1;
196
}
197
198
static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
199
{
200
}
201
202
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick)
203
{
204
SDL_Joystick *joystick;
205
const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index
206
Uint8 v;
207
Sint16 axis_value;
208
Uint64 timestamp = SDL_GetTicksNS();
209
210
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
211
if (!joystick) {
212
// Hasn't been opened yet, skip
213
return;
214
}
215
216
#define READ_BUTTON(off, flag, button) \
217
SDL_SendJoystickButton( \
218
timestamp, \
219
joystick, \
220
button, \
221
((packet[off] & flag) != 0));
222
READ_BUTTON(0, 0x02, 0) // A
223
READ_BUTTON(0, 0x04, 1) // B
224
READ_BUTTON(0, 0x08, 3) // Y
225
READ_BUTTON(0, 0x01, 2) // X
226
READ_BUTTON(1, 0x80, 4) // DPAD_LEFT
227
READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT
228
READ_BUTTON(1, 0x40, 6) // DPAD_DOWN
229
READ_BUTTON(1, 0x10, 7) // DPAD_UP
230
READ_BUTTON(1, 0x02, 8) // START
231
READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER
232
/* These two buttons are for the bottoms of the analog triggers.
233
* More than likely, you're going to want to read the axes instead!
234
* -flibit
235
*/
236
READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT
237
READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT
238
#undef READ_BUTTON
239
240
#define READ_AXIS(off, axis, invert) \
241
v = (invert) ? (0xff - packet[off]) : packet[off]; \
242
if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
243
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
244
if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
245
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
246
axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
247
SDL_SendJoystickAxis( \
248
timestamp, \
249
joystick, \
250
axis, axis_value);
251
READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0)
252
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1)
253
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0)
254
READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1)
255
READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
256
READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
257
#undef READ_AXIS
258
}
259
260
static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, Uint8 *packet, int size)
261
{
262
SDL_Joystick *joystick;
263
Uint8 *curSlot;
264
Uint8 i;
265
Sint16 axis_value;
266
Uint64 timestamp = SDL_GetTicksNS();
267
268
if (size < 37 || packet[0] != 0x21) {
269
return; // Nothing to do right now...?
270
}
271
272
// Go through all 4 slots
273
curSlot = packet + 1;
274
for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
275
ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
276
277
// Only allow rumble if the adapter's second USB cable is connected
278
ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) && !ctx->wireless[i];
279
280
if (curSlot[0] & 0x30) { // 0x10 - Wired, 0x20 - Wireless
281
if (ctx->joysticks[i] == 0) {
282
ResetAxisRange(ctx, i);
283
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
284
}
285
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
286
287
// Hasn't been opened yet, skip
288
if (!joystick) {
289
continue;
290
}
291
} else {
292
if (ctx->joysticks[i] != 0) {
293
HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
294
ctx->joysticks[i] = 0;
295
}
296
continue;
297
}
298
299
#define READ_BUTTON(off, flag, button) \
300
SDL_SendJoystickButton( \
301
timestamp, \
302
joystick, \
303
button, \
304
((curSlot[off] & flag) != 0));
305
READ_BUTTON(1, 0x01, 0) // A
306
READ_BUTTON(1, 0x02, 1) // B
307
READ_BUTTON(1, 0x04, 2) // X
308
READ_BUTTON(1, 0x08, 3) // Y
309
READ_BUTTON(1, 0x10, 4) // DPAD_LEFT
310
READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT
311
READ_BUTTON(1, 0x40, 6) // DPAD_DOWN
312
READ_BUTTON(1, 0x80, 7) // DPAD_UP
313
READ_BUTTON(2, 0x01, 8) // START
314
READ_BUTTON(2, 0x02, 9) // RIGHTSHOULDER
315
/* These two buttons are for the bottoms of the analog triggers.
316
* More than likely, you're going to want to read the axes instead!
317
* -flibit
318
*/
319
READ_BUTTON(2, 0x04, 10) // TRIGGERRIGHT
320
READ_BUTTON(2, 0x08, 11) // TRIGGERLEFT
321
#undef READ_BUTTON
322
323
#define READ_AXIS(off, axis) \
324
if (curSlot[off] < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
325
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = curSlot[off]; \
326
if (curSlot[off] > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
327
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = curSlot[off]; \
328
axis_value = (Sint16)HIDAPI_RemapVal(curSlot[off], ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
329
SDL_SendJoystickAxis( \
330
timestamp, \
331
joystick, \
332
axis, axis_value);
333
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX)
334
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY)
335
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX)
336
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTY)
337
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER)
338
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)
339
#undef READ_AXIS
340
}
341
}
342
343
static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
344
{
345
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
346
Uint8 packet[USB_PACKET_LENGTH];
347
int size;
348
349
// Read input packet
350
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
351
#ifdef DEBUG_GAMECUBE_PROTOCOL
352
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
353
#endif
354
if (ctx->pc_mode) {
355
if (size == 10) {
356
// This is the older firmware
357
// The first byte is the index of the connected controller
358
// The C stick has an inverted value range compared to the left stick
359
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true);
360
} else if (size == 9) {
361
// This is the newer firmware (version 0x7)
362
// The C stick has the same value range compared to the left stick
363
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false);
364
} else {
365
// How do we handle this packet?
366
}
367
} else {
368
HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size);
369
}
370
}
371
372
// Write rumble packet
373
if (ctx->rumbleUpdate) {
374
SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
375
ctx->rumbleUpdate = false;
376
}
377
378
// If we got here, nothing bad happened!
379
return true;
380
}
381
382
static bool HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
383
{
384
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
385
Uint8 i;
386
387
SDL_AssertJoysticksLocked();
388
389
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
390
if (joystick->instance_id == ctx->joysticks[i]) {
391
joystick->nbuttons = 12;
392
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
393
if (ctx->wireless[i]) {
394
joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
395
} else {
396
joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED;
397
}
398
return true;
399
}
400
}
401
return false; // Should never get here!
402
}
403
404
static bool HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
405
{
406
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
407
Uint8 i, val;
408
409
SDL_AssertJoysticksLocked();
410
411
if (ctx->pc_mode) {
412
return SDL_Unsupported();
413
}
414
415
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
416
if (joystick->instance_id == ctx->joysticks[i]) {
417
if (ctx->wireless[i]) {
418
return SDL_SetError("Nintendo GameCube WaveBird controllers do not support rumble");
419
}
420
if (!ctx->rumbleAllowed[i]) {
421
return SDL_SetError("Second USB cable for WUP-028 not connected");
422
}
423
if (ctx->useRumbleBrake) {
424
if (low_frequency_rumble == 0 && high_frequency_rumble > 0) {
425
val = 0; // if only low is 0 we want to do a regular stop
426
} else if (low_frequency_rumble == 0 && high_frequency_rumble == 0) {
427
val = 2; // if both frequencies are 0 we want to do a hard stop
428
} else {
429
val = 1; // normal rumble
430
}
431
} else {
432
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
433
}
434
if (val != ctx->rumble[i + 1]) {
435
ctx->rumble[i + 1] = val;
436
ctx->rumbleUpdate = true;
437
}
438
return true;
439
}
440
}
441
442
// Should never get here!
443
return SDL_SetError("Couldn't find joystick");
444
}
445
446
static bool HIDAPI_DriverGameCube_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
447
{
448
return SDL_Unsupported();
449
}
450
451
static Uint32 HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
452
{
453
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
454
Uint32 result = 0;
455
456
SDL_AssertJoysticksLocked();
457
458
if (!ctx->pc_mode) {
459
Uint8 i;
460
461
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
462
if (joystick->instance_id == ctx->joysticks[i]) {
463
if (!ctx->wireless[i] && ctx->rumbleAllowed[i]) {
464
result |= SDL_JOYSTICK_CAP_RUMBLE;
465
break;
466
}
467
}
468
}
469
}
470
471
return result;
472
}
473
474
static bool HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
475
{
476
return SDL_Unsupported();
477
}
478
479
static bool HIDAPI_DriverGameCube_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
480
{
481
return SDL_Unsupported();
482
}
483
484
static bool HIDAPI_DriverGameCube_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
485
{
486
return SDL_Unsupported();
487
}
488
489
static void HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
490
{
491
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
492
493
// Stop rumble activity
494
if (ctx->rumbleUpdate) {
495
SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
496
ctx->rumbleUpdate = false;
497
}
498
}
499
500
static void HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
501
{
502
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
503
504
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE,
505
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
506
}
507
508
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = {
509
SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
510
true,
511
HIDAPI_DriverGameCube_RegisterHints,
512
HIDAPI_DriverGameCube_UnregisterHints,
513
HIDAPI_DriverGameCube_IsEnabled,
514
HIDAPI_DriverGameCube_IsSupportedDevice,
515
HIDAPI_DriverGameCube_InitDevice,
516
HIDAPI_DriverGameCube_GetDevicePlayerIndex,
517
HIDAPI_DriverGameCube_SetDevicePlayerIndex,
518
HIDAPI_DriverGameCube_UpdateDevice,
519
HIDAPI_DriverGameCube_OpenJoystick,
520
HIDAPI_DriverGameCube_RumbleJoystick,
521
HIDAPI_DriverGameCube_RumbleJoystickTriggers,
522
HIDAPI_DriverGameCube_GetJoystickCapabilities,
523
HIDAPI_DriverGameCube_SetJoystickLED,
524
HIDAPI_DriverGameCube_SendJoystickEffect,
525
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
526
HIDAPI_DriverGameCube_CloseJoystick,
527
HIDAPI_DriverGameCube_FreeDevice,
528
};
529
530
#endif // SDL_JOYSTICK_HIDAPI_GAMECUBE
531
532
#endif // SDL_JOYSTICK_HIDAPI
533
534