Skip to content

Commit d583ff8

Browse files
committed
Moved Nintendo Switch 2 Controller initialization from hid.c to SDL_hidapi_switch2.c
1 parent 9e92233 commit d583ff8

File tree

3 files changed

+148
-98
lines changed

3 files changed

+148
-98
lines changed

src/hidapi/libusb/hid.c

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,82 +1307,6 @@ static void init_xboxone(libusb_device_handle *device_handle, unsigned short idV
13071307
}
13081308
}
13091309

1310-
static bool is_ns2(unsigned short idVendor, unsigned short idProduct)
1311-
{
1312-
if (idVendor == 0x057e) {
1313-
if (idProduct == 0x2069) {
1314-
return true;
1315-
}
1316-
if (idProduct == 0x2073) {
1317-
return true;
1318-
}
1319-
}
1320-
return false;
1321-
}
1322-
1323-
static void init_ns2(libusb_device_handle *device_handle, const struct libusb_config_descriptor *conf_desc)
1324-
{
1325-
int j, k, l, res;
1326-
1327-
for (j = 0; j < conf_desc->bNumInterfaces; j++) {
1328-
const struct libusb_interface *intf = &conf_desc->interface[j];
1329-
for (k = 0; k < intf->num_altsetting; k++) {
1330-
const struct libusb_interface_descriptor *intf_desc = &intf->altsetting[k];
1331-
if (intf_desc->bInterfaceNumber == 1) {
1332-
uint8_t endpoint = 0;
1333-
for (l = 0; l < intf_desc->bNumEndpoints; l++) {
1334-
const struct libusb_endpoint_descriptor* ep = &intf_desc->endpoint[l];
1335-
if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK && (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
1336-
endpoint = ep->bEndpointAddress;
1337-
break;
1338-
}
1339-
}
1340-
1341-
if (endpoint) {
1342-
res = libusb_claim_interface(device_handle, intf_desc->bInterfaceNumber);
1343-
if (res < 0) {
1344-
LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
1345-
continue;
1346-
}
1347-
1348-
const unsigned char DEFAULT_REPORT_DATA[] = {
1349-
0x03, 0x91, 0x00, 0x0d, 0x00, 0x08,
1350-
0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1351-
};
1352-
const unsigned char SET_LED_DATA[] = {
1353-
0x09, 0x91, 0x00, 0x07, 0x00, 0x08,
1354-
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1355-
};
1356-
1357-
int transferred;
1358-
res = libusb_bulk_transfer(device_handle,
1359-
endpoint,
1360-
(unsigned char*)DEFAULT_REPORT_DATA,
1361-
sizeof(DEFAULT_REPORT_DATA),
1362-
&transferred,
1363-
1000);
1364-
if (res < 0) {
1365-
LOG("can't set report data: %d\n", res);
1366-
}
1367-
1368-
res = libusb_bulk_transfer(device_handle,
1369-
endpoint,
1370-
(unsigned char*)SET_LED_DATA,
1371-
sizeof(SET_LED_DATA),
1372-
&transferred,
1373-
1000);
1374-
if (res < 0) {
1375-
LOG("can't set LED data: %d\n", res);
1376-
}
1377-
1378-
libusb_release_interface(device_handle, intf_desc->bInterfaceNumber);
1379-
return;
1380-
}
1381-
}
1382-
}
1383-
}
1384-
}
1385-
13861310
static void calculate_device_quirks(hid_device *dev, unsigned short idVendor, unsigned short idProduct)
13871311
{
13881312
static const int VENDOR_SONY = 0x054c;
@@ -1444,11 +1368,6 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa
14441368
init_xboxone(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
14451369
}
14461370

1447-
/* Initialize Nintendo Switch 2 controllers */
1448-
if (is_ns2(desc.idVendor, desc.idProduct)) {
1449-
init_ns2(dev->device_handle, conf_desc);
1450-
}
1451-
14521371
/* Store off the string descriptor indexes */
14531372
dev->manufacturer_index = desc.iManufacturer;
14541373
dev->product_index = desc.iProduct;

src/joystick/hidapi/SDL_hidapi_switch2.c

Lines changed: 146 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@
2626
#ifdef SDL_JOYSTICK_HIDAPI
2727

2828
#include "../../SDL_hints_c.h"
29+
#include "../../misc/SDL_libusb.h"
2930
#include "../SDL_sysjoystick.h"
3031
#include "SDL_hidapijoystick_c.h"
31-
#include "SDL_hidapi_rumble.h"
32-
#include "SDL_hidapi_nintendo.h"
3332

3433
#ifdef SDL_JOYSTICK_HIDAPI_SWITCH2
3534

35+
typedef struct
36+
{
37+
SDL_LibUSBContext *libusb;
38+
libusb_device_handle *device_handle;
39+
bool interface_claimed;
40+
Uint8 interface_number;
41+
Uint8 bulk_endpoint;
42+
} SDL_DriverSwitch2_Context;
43+
3644
static void HIDAPI_DriverSwitch2_RegisterHints(SDL_HintCallback callback, void *userdata)
3745
{
3846
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH2, callback, userdata);
@@ -51,29 +59,138 @@ static bool HIDAPI_DriverSwitch2_IsEnabled(void)
5159
static bool HIDAPI_DriverSwitch2_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)
5260
{
5361
if (vendor_id == USB_VENDOR_NINTENDO) {
54-
switch (product_id) {
55-
case USB_PRODUCT_NINTENDO_SWITCH2_GAMECUBE_CONTROLLER:
56-
case USB_PRODUCT_NINTENDO_SWITCH2_PRO:
62+
switch (product_id) {
63+
case USB_PRODUCT_NINTENDO_SWITCH2_GAMECUBE_CONTROLLER:
64+
case USB_PRODUCT_NINTENDO_SWITCH2_PRO:
5765
return true;
58-
}
66+
}
5967
}
6068

6169
return false;
6270
}
6371

72+
static bool HIDAPI_DriverSwitch2_InitBluetooth(SDL_HIDAPI_Device *device)
73+
{
74+
// FIXME: Need to add Bluetooth support
75+
return SDL_SetError("Nintendo Switch2 controllers not supported over Bluetooth");
76+
}
77+
78+
static bool FindBulkOutEndpoint(SDL_LibUSBContext *libusb, libusb_device_handle *handle, Uint8 *bInterfaceNumber, Uint8 *bEndpointAddress)
79+
{
80+
struct libusb_config_descriptor *config;
81+
if (libusb->get_config_descriptor(libusb->get_device(handle), 0, &config) != 0) {
82+
return false;
83+
}
84+
85+
for (int i = 0; i < config->bNumInterfaces; i++) {
86+
const struct libusb_interface *iface = &config->interface[i];
87+
for (int j = 0; j < iface->num_altsetting; j++) {
88+
const struct libusb_interface_descriptor *altsetting = &iface->altsetting[j];
89+
if (altsetting->bInterfaceNumber == 1) {
90+
for (int k = 0; k < altsetting->bNumEndpoints; k++) {
91+
const struct libusb_endpoint_descriptor *ep = &altsetting->endpoint[k];
92+
if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK && (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
93+
94+
*bInterfaceNumber = altsetting->bInterfaceNumber;
95+
*bEndpointAddress = ep->bEndpointAddress;
96+
libusb->free_config_descriptor(config);
97+
return true;
98+
}
99+
}
100+
}
101+
}
102+
}
103+
libusb->free_config_descriptor(config);
104+
return false;
105+
}
106+
107+
static bool HIDAPI_DriverSwitch2_InitUSB(SDL_HIDAPI_Device *device)
108+
{
109+
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
110+
111+
if (!SDL_InitLibUSB(&ctx->libusb)) {
112+
return false;
113+
}
114+
115+
ctx->device_handle = (libusb_device_handle *)SDL_GetPointerProperty(SDL_hid_get_properties(device->dev), SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER, NULL);
116+
if (!ctx->device_handle) {
117+
return SDL_SetError("Couldn't get libusb device handle");
118+
}
119+
120+
if (!FindBulkOutEndpoint(ctx->libusb, ctx->device_handle, &ctx->interface_number, &ctx->bulk_endpoint)) {
121+
return SDL_SetError("Couldn't find bulk endpoint");
122+
}
123+
124+
int res = ctx->libusb->claim_interface(ctx->device_handle, ctx->interface_number);
125+
if (res < 0) {
126+
return SDL_SetError("Couldn't claim interface %d: %d\n", ctx->interface_number, res);
127+
}
128+
ctx->interface_claimed = true;
129+
130+
const unsigned char DEFAULT_REPORT_DATA[] = {
131+
0x03, 0x91, 0x00, 0x0d, 0x00, 0x08,
132+
0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
133+
};
134+
const unsigned char SET_LED_DATA[] = {
135+
0x09, 0x91, 0x00, 0x07, 0x00, 0x08,
136+
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
137+
};
138+
139+
int transferred;
140+
res = ctx->libusb->bulk_transfer(ctx->device_handle,
141+
ctx->bulk_endpoint,
142+
(unsigned char *)DEFAULT_REPORT_DATA,
143+
sizeof(DEFAULT_REPORT_DATA),
144+
&transferred,
145+
1000);
146+
if (res < 0) {
147+
return SDL_SetError("Couldn't set report data: %d\n", res);
148+
}
149+
150+
res = ctx->libusb->bulk_transfer(ctx->device_handle,
151+
ctx->bulk_endpoint,
152+
(unsigned char *)SET_LED_DATA,
153+
sizeof(SET_LED_DATA),
154+
&transferred,
155+
1000);
156+
if (res < 0) {
157+
return SDL_SetError("Couldn't set LED data: %d\n", res);
158+
}
159+
160+
return true;
161+
}
162+
64163
static bool HIDAPI_DriverSwitch2_InitDevice(SDL_HIDAPI_Device *device)
65164
{
66-
// Sometimes the device handle isn't available during enumeration so we don't get the device name, so set it explicitly
67-
switch (device->product_id) {
68-
case USB_PRODUCT_NINTENDO_SWITCH2_GAMECUBE_CONTROLLER:
69-
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
70-
break;
71-
case USB_PRODUCT_NINTENDO_SWITCH2_PRO:
72-
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
73-
break;
74-
default:
75-
break;
76-
}
165+
SDL_DriverSwitch2_Context *ctx;
166+
167+
ctx = (SDL_DriverSwitch2_Context *)SDL_calloc(1, sizeof(*ctx));
168+
if (!ctx) {
169+
return false;
170+
}
171+
device->context = ctx;
172+
173+
if (device->is_bluetooth) {
174+
if (!HIDAPI_DriverSwitch2_InitBluetooth(device)) {
175+
return false;
176+
}
177+
} else {
178+
if (!HIDAPI_DriverSwitch2_InitUSB(device)) {
179+
return false;
180+
}
181+
}
182+
183+
// Sometimes the device handle isn't available during enumeration so we don't get the device name, so set it explicitly
184+
switch (device->product_id) {
185+
case USB_PRODUCT_NINTENDO_SWITCH2_GAMECUBE_CONTROLLER:
186+
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
187+
break;
188+
case USB_PRODUCT_NINTENDO_SWITCH2_PRO:
189+
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
190+
break;
191+
default:
192+
break;
193+
}
77194
return HIDAPI_JoystickConnected(device, NULL);
78195
}
79196

@@ -250,6 +367,18 @@ static void HIDAPI_DriverSwitch2_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Jo
250367

251368
static void HIDAPI_DriverSwitch2_FreeDevice(SDL_HIDAPI_Device *device)
252369
{
370+
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
371+
372+
if (ctx) {
373+
if (ctx->interface_claimed) {
374+
ctx->libusb->release_interface(ctx->device_handle, ctx->interface_number);
375+
ctx->interface_claimed = false;
376+
}
377+
if (ctx->libusb) {
378+
SDL_QuitLibUSB();
379+
ctx->libusb = NULL;
380+
}
381+
}
253382
}
254383

255384
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch2 = {

src/joystick/hidapi/SDL_hidapijoystick_c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
#define SDL_JOYSTICK_HIDAPI_STEAM
3636
#define SDL_JOYSTICK_HIDAPI_STEAMDECK
3737
#define SDL_JOYSTICK_HIDAPI_SWITCH
38+
#ifdef HAVE_LIBUSB
3839
#define SDL_JOYSTICK_HIDAPI_SWITCH2
40+
#endif
3941
#define SDL_JOYSTICK_HIDAPI_WII
4042
#define SDL_JOYSTICK_HIDAPI_XBOX360
4143
#define SDL_JOYSTICK_HIDAPI_XBOXONE

0 commit comments

Comments
 (0)