21 #include "../../SDL_internal.h"
23 #ifdef SDL_JOYSTICK_HIDAPI
31 #include "../../SDL_hints_c.h"
32 #include "../SDL_sysjoystick.h"
37 #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
39 #define MAX_CONTROLLERS 4
43 Uint8 wireless[MAX_CONTROLLERS];
46 Uint8 rumbleAllowed[MAX_CONTROLLERS];
47 Uint8 rumble[1+MAX_CONTROLLERS];
51 } SDL_DriverGameCube_Context;
64 HIDAPI_DriverGameCube_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
66 return "Nintendo GameCube Controller";
70 ResetAxisRange(SDL_DriverGameCube_Context *
ctx,
int joystick_index)
80 static float fsel(
float fComparand,
float fValGE,
float fLT)
82 return fComparand >= 0 ? fValGE : fLT;
85 static float RemapVal(
float val,
float A,
float B,
float C,
float D)
88 return fsel(
val - B , D , C);
96 return C + (D - C) * (
val - A) / (B - A);
99 static void SDLCALL SDL_GameControllerButtonReportingHintChanged(
void *userdata,
const char *
name,
const char *oldValue,
const char *hint)
101 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)userdata;
107 if (!
ctx->m_bUseButtonLabels) {
124 SDL_DriverGameCube_Context *
ctx;
129 Uint8 initMagic = 0x13;
130 Uint8 rumbleMagic = 0x11;
146 ctx->joysticks[0] = -1;
147 ctx->joysticks[1] = -1;
148 ctx->joysticks[2] = -1;
149 ctx->joysticks[3] = -1;
150 ctx->rumble[0] = rumbleMagic;
153 if (
hid_write(
device->dev, &initMagic,
sizeof(initMagic)) !=
sizeof(initMagic)) {
163 if (
size < 37 || packet[0] != 0x21) {
168 curSlot = packet + 1;
169 for (
i = 0;
i < MAX_CONTROLLERS;
i += 1, curSlot += 9) {
170 ctx->wireless[
i] = (curSlot[0] & 0x20) != 0;
173 ctx->rumbleAllowed[
i] = (curSlot[0] & 0x04) != 0 && !
ctx->wireless[
i];
175 if (curSlot[0] & 0x30) {
176 if (
ctx->joysticks[
i] == -1) {
177 ResetAxisRange(
ctx,
i);
181 if (
ctx->joysticks[
i] != -1) {
183 ctx->joysticks[
i] = -1;
191 SDL_GameControllerButtonReportingHintChanged,
ctx);
210 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
213 for (
i = 0;
i < 4; ++
i) {
214 if (instance_id ==
ctx->joysticks[
i]) {
229 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
239 if (
size < 37 || packet[0] != 0x21) {
244 curSlot = packet + 1;
245 for (
i = 0;
i < MAX_CONTROLLERS;
i += 1, curSlot += 9) {
246 ctx->wireless[
i] = (curSlot[0] & 0x20) != 0;
249 ctx->rumbleAllowed[
i] = (curSlot[0] & 0x04) != 0 && !
ctx->wireless[
i];
251 if (curSlot[0] & 0x30) {
252 if (
ctx->joysticks[
i] == -1) {
253 ResetAxisRange(
ctx,
i);
263 if (
ctx->joysticks[
i] != -1) {
265 ctx->joysticks[
i] = -1;
270 #define READ_BUTTON(off, flag, button) \
271 SDL_PrivateJoystickButton( \
273 RemapButton(ctx, button), \
274 (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
276 READ_BUTTON(1, 0x01, 0)
277 READ_BUTTON(1, 0x04, 1)
278 READ_BUTTON(1, 0x02, 2)
279 READ_BUTTON(1, 0x08, 3)
280 READ_BUTTON(1, 0x10, 4)
281 READ_BUTTON(1, 0x20, 5)
282 READ_BUTTON(1, 0x40, 6)
283 READ_BUTTON(1, 0x80, 7)
284 READ_BUTTON(2, 0x01, 8)
285 READ_BUTTON(2, 0x02, 9)
290 READ_BUTTON(2, 0x04, 10)
291 READ_BUTTON(2, 0x08, 11)
294 #define READ_AXIS(off, axis) \
295 if (axis < SDL_CONTROLLER_AXIS_TRIGGERLEFT) \
296 if (curSlot[off] < ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis]) ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis] = curSlot[off]; \
297 if (curSlot[off] > ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis]) ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis] = curSlot[off]; \
298 axis_value = (Sint16)(RemapVal(curSlot[off], ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis], ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis], SDL_MIN_SINT16, SDL_MAX_SINT16)); \
299 SDL_PrivateJoystickAxis( \
314 if (
ctx->rumbleUpdate) {
315 SDL_HIDAPI_SendRumble(
device,
ctx->rumble,
sizeof(
ctx->rumble));
326 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
328 for (
i = 0;
i < MAX_CONTROLLERS;
i += 1) {
342 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
344 for (
i = 0;
i < MAX_CONTROLLERS;
i += 1) {
346 if (
ctx->wireless[
i]) {
347 return SDL_SetError(
"Ninteno GameCube WaveBird controllers do not support rumble");
349 if (!
ctx->rumbleAllowed[
i]) {
350 return SDL_SetError(
"Second USB cable for WUP-028 not connected");
352 val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
353 if (
val !=
ctx->rumble[
i + 1]) {
393 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
396 if (
ctx->rumbleUpdate) {
397 SDL_HIDAPI_SendRumble(
device,
ctx->rumble,
sizeof(
ctx->rumble));
405 SDL_DriverGameCube_Context *
ctx = (SDL_DriverGameCube_Context *)
device->context;
411 SDL_GameControllerButtonReportingHintChanged,
ctx);
421 HIDAPI_DriverGameCube_IsSupportedDevice,
422 HIDAPI_DriverGameCube_GetDeviceName,
423 HIDAPI_DriverGameCube_InitDevice,
424 HIDAPI_DriverGameCube_GetDevicePlayerIndex,
425 HIDAPI_DriverGameCube_SetDevicePlayerIndex,
426 HIDAPI_DriverGameCube_UpdateDevice,
427 HIDAPI_DriverGameCube_OpenJoystick,
428 HIDAPI_DriverGameCube_RumbleJoystick,
429 HIDAPI_DriverGameCube_RumbleJoystickTriggers,
430 HIDAPI_DriverGameCube_HasJoystickLED,
431 HIDAPI_DriverGameCube_SetJoystickLED,
432 HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
433 HIDAPI_DriverGameCube_CloseJoystick,
434 HIDAPI_DriverGameCube_FreeDevice,
#define SDL_DelHintCallback
#define SDL_JoystickFromInstanceID
#define SDL_AddHintCallback
#define SDL_OutOfMemory()
#define SDL_Unsupported()
@ SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_X
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS
If set, game controller face buttons report their values according to their labels instead of their p...
#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE
A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
@ SDL_JOYSTICK_POWER_UNKNOWN
@ SDL_JOYSTICK_POWER_WIRED
GLuint GLuint GLsizei GLenum type
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
static SDL_AudioDeviceID device
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static SDL_Joystick * joystick
#define USB_VENDOR_NINTENDO
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER