Skip to content

Commit

Permalink
Added 4 auxiliary buttons to the game controller API
Browse files Browse the repository at this point in the history
Xbox Elite controllers use AUX1-AUX4 to represent the paddle buttons when using the HIDAPI driver
PS4 and PS5 controllers use AUX1 to represent the touchpad button
Nintendo Switch Pro controllers use AUX1 to represent the capture button
  • Loading branch information
slouken committed Nov 6, 2020
1 parent a22beef commit 3a3aaac
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 223 deletions.
4 changes: 4 additions & 0 deletions include/SDL_gamecontroller.h
Expand Up @@ -363,6 +363,10 @@ typedef enum
SDL_CONTROLLER_BUTTON_DPAD_DOWN,
SDL_CONTROLLER_BUTTON_DPAD_LEFT,
SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
SDL_CONTROLLER_BUTTON_AUX1, // Xbox Elite paddle, Nintendo Switch Pro capture button
SDL_CONTROLLER_BUTTON_AUX2, // Xbox Elite paddle
SDL_CONTROLLER_BUTTON_AUX3, // Xbox Elite paddle
SDL_CONTROLLER_BUTTON_AUX4, // Xbox Elite paddle
SDL_CONTROLLER_BUTTON_MAX
} SDL_GameControllerButton;

Expand Down
338 changes: 189 additions & 149 deletions src/joystick/SDL_gamecontroller.c

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/joystick/SDL_gamecontrollerdb.h
Expand Up @@ -841,7 +841,6 @@ static const char *s_ControllerMappings [] =
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
"default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
#endif
"hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
NULL
};

Expand Down
36 changes: 32 additions & 4 deletions src/joystick/SDL_joystick.c
Expand Up @@ -1735,12 +1735,13 @@ SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 produc
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
if (vendor == 0x0000 && product == 0x0000) {
/* Some devices are only identifiable by their name */
if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
SDL_strcmp(name, "Wireless Gamepad") == 0) {
if (name &&
(SDL_strcmp(name, "Lic Pro Controller") == 0 ||
SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
SDL_strcmp(name, "Wireless Gamepad") == 0)) {
/* HORI or PowerA Switch Pro Controller clone */
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
} else if (SDL_strcmp(name, "Virtual Joystick") == 0) {
} else if (name && SDL_strcmp(name, "Virtual Joystick") == 0) {
type = SDL_CONTROLLER_TYPE_VIRTUAL;
} else {
type = SDL_CONTROLLER_TYPE_UNKNOWN;
Expand Down Expand Up @@ -1779,13 +1780,40 @@ SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 produc
return type;
}

SDL_bool
SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}

SDL_bool
SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return (eType == k_eControllerType_PS4Controller);
}

SDL_bool
SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return (eType == k_eControllerType_PS5Controller);
}

SDL_bool
SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return (eType == k_eControllerType_SwitchProController ||
eType == k_eControllerType_SwitchInputOnlyController);
}

SDL_bool
SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id)
{
Expand Down
7 changes: 7 additions & 0 deletions src/joystick/SDL_joystick_c.h
Expand Up @@ -61,10 +61,17 @@ extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *v
extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name);
extern SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol);

/* Function to return whether a joystick is an Xbox One Elite controller */
extern SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id);

/* Function to return whether a joystick is a PS4 controller */
extern SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id);

/* Function to return whether a joystick is a PS5 controller */
extern SDL_bool SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id);

/* Function to return whether a joystick is a Nintendo Switch Pro controller */
extern SDL_bool SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id);
extern SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id);

/* Function to return whether a joystick is a Steam Controller */
Expand Down
12 changes: 6 additions & 6 deletions src/joystick/android/SDL_sysjoystick.c
Expand Up @@ -138,16 +138,16 @@ keycode_to_SDL(int keycode)
button = SDL_CONTROLLER_BUTTON_GUIDE;
break;
case AKEYCODE_BUTTON_L2:
button = SDL_CONTROLLER_BUTTON_MAX; /* Not supported by GameController */
button = SDL_CONTROLLER_BUTTON_AUX1;
break;
case AKEYCODE_BUTTON_R2:
button = SDL_CONTROLLER_BUTTON_MAX+1; /* Not supported by GameController */
button = SDL_CONTROLLER_BUTTON_AUX2;
break;
case AKEYCODE_BUTTON_C:
button = SDL_CONTROLLER_BUTTON_MAX+2; /* Not supported by GameController */
button = SDL_CONTROLLER_BUTTON_AUX3;
break;
case AKEYCODE_BUTTON_Z:
button = SDL_CONTROLLER_BUTTON_MAX+3; /* Not supported by GameController */
button = SDL_CONTROLLER_BUTTON_AUX4;
break;

/* D-Pad key codes (API 1) */
Expand All @@ -165,7 +165,7 @@ keycode_to_SDL(int keycode)
break;
case AKEYCODE_DPAD_CENTER:
/* This is handled better by applications as the A button */
/*button = SDL_CONTROLLER_BUTTON_MAX+4;*/ /* Not supported by GameController */
/*button = 19;*/ /* Not supported by GameController */
button = SDL_CONTROLLER_BUTTON_A;
break;

Expand All @@ -186,7 +186,7 @@ keycode_to_SDL(int keycode)
case AKEYCODE_BUTTON_14:
case AKEYCODE_BUTTON_15:
case AKEYCODE_BUTTON_16:
button = keycode - AKEYCODE_BUTTON_1 + SDL_CONTROLLER_BUTTON_MAX + 5;
button = 20 + (keycode - AKEYCODE_BUTTON_1);
break;

default:
Expand Down
24 changes: 1 addition & 23 deletions src/joystick/hidapi/SDL_hidapi_ps5.c
Expand Up @@ -68,28 +68,6 @@ typedef struct {
/* Define this if you want to log all packets from the controller */
/*#define DEBUG_PS5_PROTOCOL*/

#ifdef DEBUG_PS5_PROTOCOL
static void
DumpPacket(const char *prefix, Uint8 *data, int size)
{
int i;
char *buffer;
size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;

buffer = (char *)SDL_malloc(length);
SDL_snprintf(buffer, length, prefix, size);
for (i = 0; i < size; ++i) {
if ((i % 8) == 0) {
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
}
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
}
SDL_strlcat(buffer, "\n", length);
SDL_Log("%s", buffer);
SDL_free(buffer);
}
#endif /* DEBUG_PS5_PROTOCOL */

static SDL_bool
HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
Expand Down Expand Up @@ -371,7 +349,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)

while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS5_PROTOCOL
DumpPacket("PS5 packet: size = %d", data, size);
HIDAPI_DumpPacket("PS5 packet: size = %d", data, size);
#endif
switch (data[0]) {
case 0x01:
Expand Down
6 changes: 5 additions & 1 deletion src/joystick/hidapi/SDL_hidapi_steam.c
Expand Up @@ -1010,7 +1010,7 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
InitializeSteamControllerPacketAssembler(&ctx->m_assembler);

/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
joystick->nbuttons = 17;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;

return SDL_TRUE;
Expand Down Expand Up @@ -1111,6 +1111,10 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)

SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK,
(ctx->m_state.ulButtons & STEAM_JOYSTICK_BUTTON_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX1,
(ctx->m_state.ulButtons & STEAM_BUTTON_BACK_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX2,
(ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED);
}
{
/* Minimum distance from center of pad to register a direction */
Expand Down
12 changes: 11 additions & 1 deletion src/joystick/hidapi/SDL_hidapi_switch.c
Expand Up @@ -38,6 +38,10 @@

#ifdef SDL_JOYSTICK_HIDAPI_SWITCH

/* Define this if you want to log all packets from the controller */
/*#define DEBUG_SWITCH_PROTOCOL*/
#define DEBUG_SWITCH_PROTOCOL

/* Define this to get log output for rumble logic */
/*#define DEBUG_RUMBLE*/

Expand Down Expand Up @@ -800,7 +804,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
SDL_GameControllerButtonReportingHintChanged, ctx);

/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
joystick->nbuttons = 16;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;

Expand Down Expand Up @@ -960,6 +964,7 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}

if (packet->ucStickHat != ctx->m_lastInputOnlyState.ucStickHat) {
Expand Down Expand Up @@ -1058,6 +1063,7 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}

if (packet->ucStickHat != ctx->m_lastSimpleState.ucStickHat) {
Expand Down Expand Up @@ -1142,6 +1148,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);

SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
}

if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
Expand Down Expand Up @@ -1210,6 +1217,9 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
}

while ((size = ReadInput(ctx)) > 0) {
#ifdef DEBUG_SWITCH_PROTOCOL
HIDAPI_DumpPacket("Nintendo Switch packet: size = %d", ctx->m_rgucReadBuffer, size);
#endif
if (ctx->m_bInputOnly) {
HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/joystick/hidapi/SDL_hidapi_xbox360.c
Expand Up @@ -708,7 +708,7 @@ HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
}

/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
joystick->nbuttons = 15;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;

Expand Down
2 changes: 1 addition & 1 deletion src/joystick/hidapi/SDL_hidapi_xbox360w.c
Expand Up @@ -136,7 +136,7 @@ HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
SDL_zeroa(ctx->last_state);

/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
joystick->nbuttons = 15;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;

Expand Down
44 changes: 8 additions & 36 deletions src/joystick/hidapi/SDL_hidapi_xboxone.c
Expand Up @@ -128,28 +128,6 @@ typedef struct {
} SDL_DriverXboxOne_Context;


#ifdef DEBUG_XBOX_PROTOCOL
static void
DumpPacket(const char *prefix, Uint8 *data, int size)
{
int i;
char *buffer;
size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;

buffer = (char *)SDL_malloc(length);
SDL_snprintf(buffer, length, prefix, size);
for (i = 0; i < size; ++i) {
if ((i % 8) == 0) {
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
}
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
}
SDL_strlcat(buffer, "\n", length);
SDL_Log("%s", buffer);
SDL_free(buffer);
}
#endif /* DEBUG_XBOX_PROTOCOL */

static SDL_bool
IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
{
Expand All @@ -167,13 +145,7 @@ IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
static SDL_bool
ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
return SDL_TRUE;
}
}
return SDL_FALSE;
return SDL_IsJoystickXboxOneElite(vendor_id, product_id);
}

/* Return true if this controller sends the 0x02 "waiting for init" packet */
Expand Down Expand Up @@ -244,7 +216,7 @@ SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)

while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
DumpPacket("Xbox One INIT packet: size = %d", data, size);
HIDAPI_DumpPacket("Xbox One INIT packet: size = %d", data, size);
#endif
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
got_response = SDL_TRUE;
Expand Down Expand Up @@ -329,7 +301,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);

/* Initialize the joystick capabilities */
joystick->nbuttons = ctx->has_paddles ? SDL_CONTROLLER_BUTTON_MAX : (SDL_CONTROLLER_BUTTON_MAX + 4);
joystick->nbuttons = ctx->has_paddles ? 19 : 15;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;

Expand Down Expand Up @@ -462,10 +434,10 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
}

if (ctx->last_state[paddle_index] != data[paddle_index]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+0, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+1, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+2, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+3, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX1, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX2, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX3, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_AUX4, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
}
}

Expand Down Expand Up @@ -740,7 +712,7 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)

while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
DumpPacket("Xbox One packet: size = %d", data, size);
HIDAPI_DumpPacket("Xbox One packet: size = %d", data, size);
#endif
if (ctx->bluetooth) {
switch (data[0]) {
Expand Down
20 changes: 20 additions & 0 deletions src/joystick/hidapi/SDL_hidapijoystick.c
Expand Up @@ -390,6 +390,26 @@ HIDAPI_ShutdownDiscovery()
#endif
}

void
HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
{
int i;
char *buffer;
size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;

buffer = (char *)SDL_malloc(length);
SDL_snprintf(buffer, length, prefix, size);
for (i = 0; i < size; ++i) {
if ((i % 8) == 0) {
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
}
SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
}
SDL_strlcat(buffer, "\n", length);
SDL_Log("%s", buffer);
SDL_free(buffer);
}

static void HIDAPI_JoystickDetect(void);
static void HIDAPI_JoystickClose(SDL_Joystick * joystick);

Expand Down
2 changes: 2 additions & 0 deletions src/joystick/hidapi/SDL_hidapijoystick_c.h
Expand Up @@ -124,6 +124,8 @@ extern void HIDAPI_UpdateDevices(void);
extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID, SDL_bool is_external);
extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID, SDL_bool is_external);

extern void HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size);

#endif /* SDL_JOYSTICK_HIDAPI_H */

/* vi: set ts=4 sw=4 expandtab: */

0 comments on commit 3a3aaac

Please sign in to comment.