diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c index 4ea6bdb6a..35ca38037 100644 --- a/src/hidapi/mac/hid.c +++ b/src/hidapi/mac/hid.c @@ -130,7 +130,6 @@ struct hid_device_list_node static IOHIDManagerRef hid_mgr = 0x0; static struct hid_device_list_node *device_list = 0x0; -static int hid_input_monitoring_denied = 0; static hid_device *new_hid_device(void) { @@ -522,11 +521,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) return NULL; - - /* If we don't have permission to open devices, don't enumerate them */ - if (hid_input_monitoring_denied) - return NULL; - + /* give the IOHIDManager a chance to update itself */ process_pending_events(); @@ -867,11 +862,6 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) return dev; } - else if (ret == kIOReturnNotPermitted) { - /* This application doesn't have input monitoring permissions */ - hid_input_monitoring_denied = 1; - goto return_error; - } else { goto return_error; } diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index 04710b45e..df092404c 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -52,12 +52,6 @@ HIDAPI_DriverCombined_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *n return SDL_FALSE; } -static const char * -HIDAPI_DriverCombined_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return NULL; -} - static SDL_bool HIDAPI_DriverCombined_InitDevice(SDL_HIDAPI_Device *device) { @@ -241,7 +235,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverCombined = HIDAPI_DriverCombined_UnregisterHints, HIDAPI_DriverCombined_IsEnabled, HIDAPI_DriverCombined_IsSupportedDevice, - HIDAPI_DriverCombined_GetDeviceName, HIDAPI_DriverCombined_InitDevice, HIDAPI_DriverCombined_GetDevicePlayerIndex, HIDAPI_DriverCombined_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index bbd7a05cb..d3bd2cb22 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -89,12 +89,6 @@ HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *n return SDL_FALSE; } -static const char * -HIDAPI_DriverGameCube_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "Nintendo GameCube Controller"; -} - static void ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index) { @@ -151,18 +145,13 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) SDL_EnableGameCubeAdaptors(); #endif + HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller"); + ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { SDL_OutOfMemory(); return SDL_FALSE; } - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } device->context = ctx; ctx->joysticks[0] = -1; @@ -184,8 +173,9 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) } else { /* This is all that's needed to initialize the device. Really! */ if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) { - SDL_SetError("Couldn't initialize WUP-028"); - goto error; + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverGameCube_InitDevice(): Couldn't initialize WUP-028"); + return SDL_FALSE; } /* Wait for the adapter to initialize */ @@ -230,22 +220,6 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) SDL_GameControllerButtonReportingHintChanged, ctx); return SDL_TRUE; - -error: - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - if (device->context) { - SDL_free(device->context); - device->context = NULL; - } - } - SDL_UnlockMutex(device->dev_lock); - - return SDL_FALSE; } static int @@ -565,16 +539,6 @@ HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device) SDL_GameControllerButtonReportingHintChanged, ctx); SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx); - - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = @@ -585,7 +549,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = HIDAPI_DriverGameCube_UnregisterHints, HIDAPI_DriverGameCube_IsEnabled, HIDAPI_DriverGameCube_IsSupportedDevice, - HIDAPI_DriverGameCube_GetDeviceName, HIDAPI_DriverGameCube_InitDevice, HIDAPI_DriverGameCube_GetDevicePlayerIndex, HIDAPI_DriverGameCube_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 7808052a8..0f8cfd488 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -72,15 +72,20 @@ HIDAPI_DriverLuna_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, return (type == SDL_CONTROLLER_TYPE_AMAZON_LUNA) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverLuna_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "Amazon Luna Controller"; -} - static SDL_bool HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverLuna_Context *ctx; + + HIDAPI_SetDeviceName(device, "Amazon Luna Controller"); + + ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + device->context = ctx; + return HIDAPI_JoystickConnected(device, NULL); } @@ -98,27 +103,14 @@ HIDAPI_DriverLuna_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static SDL_bool HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverLuna_Context *ctx; + SDL_DriverLuna_Context *ctx = (SDL_DriverLuna_Context *)device->context; - ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - SDL_free(ctx); - return SDL_FALSE; - } - device->context = ctx; + SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ joystick->nbuttons = SDL_CONTROLLER_NUM_LUNA_BUTTONS; joystick->naxes = SDL_CONTROLLER_AXIS_MAX; joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL; - joystick->serial = NULL; return SDL_TRUE; } @@ -406,8 +398,7 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -415,6 +406,10 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_LUNA_PROTOCOL HIDAPI_DumpPacket("Amazon Luna packet: size = %d", data, size); #endif + if (!joystick) { + continue; + } + switch (size) { case 10: HIDAPI_DriverLuna_HandleUSBStatePacket(joystick, ctx, data, size); @@ -427,7 +422,7 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -435,17 +430,6 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device) static void HIDAPI_DriverLuna_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } static void @@ -461,7 +445,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna = HIDAPI_DriverLuna_UnregisterHints, HIDAPI_DriverLuna_IsEnabled, HIDAPI_DriverLuna_IsSupportedDevice, - HIDAPI_DriverLuna_GetDeviceName, HIDAPI_DriverLuna_InitDevice, HIDAPI_DriverLuna_GetDevicePlayerIndex, HIDAPI_DriverLuna_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 1af5c9b77..99bb613ce 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -52,10 +52,10 @@ typedef struct { SDL_bool is_shanwan; SDL_bool report_sensors; SDL_bool effects_updated; - Uint8 last_state[USB_PACKET_LENGTH]; int player_index; Uint8 rumble_left; Uint8 rumble_right; + Uint8 last_state[USB_PACKET_LENGTH]; } SDL_DriverPS3_Context; @@ -76,16 +76,16 @@ HIDAPI_DriverPS3_UnregisterHints(SDL_HintCallback callback, void *userdata) static SDL_bool HIDAPI_DriverPS3_IsEnabled(void) { + SDL_bool default_value; + #if defined(__MACOSX__) /* This works well on macOS */ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, - SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, - SDL_HIDAPI_DEFAULT)); + default_value = SDL_TRUE; #elif defined(__WINDOWS__) /* You can't initialize the controller with the stock Windows drivers * See https://github.com/ViGEm/DsHidMini as an alternative driver */ - return SDL_FALSE; + default_value = SDL_FALSE; #elif defined(__LINUX__) /* Linux drivers do a better job of managing the transition between * USB and Bluetooth. There are also some quirks in communicating @@ -93,11 +93,16 @@ HIDAPI_DriverPS3_IsEnabled(void) * for libusb, but are not possible to support using hidraw if the * kernel doesn't already know about them. */ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, SDL_FALSE); + default_value = SDL_FALSE; #else /* Untested, default off */ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, SDL_FALSE); + default_value = SDL_FALSE; #endif + + if (default_value) { + default_value = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT); + } + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, default_value); } static SDL_bool @@ -112,19 +117,6 @@ HIDAPI_DriverPS3_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, return SDL_FALSE; } -static const char * -HIDAPI_DriverPS3_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - if (vendor_id == USB_VENDOR_SONY) { - if (name && SDL_strncasecmp(name, "ShanWan", 7) == 0) { - return "ShanWan PS3 Controller"; - } else { - return "PS3 Controller"; - } - } - return NULL; -} - static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length) { SDL_memset(report, 0, length); @@ -140,6 +132,63 @@ static int SendFeatureReport(SDL_hid_device *dev, Uint8 *report, size_t length) static SDL_bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverPS3_Context *ctx; + + if (device->vendor_id == USB_VENDOR_SONY) { + if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) { + HIDAPI_SetDeviceName(device, "ShanWan PS3 Controller"); + } else { + HIDAPI_SetDeviceName(device, "PS3 Controller"); + } + } + + ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + + device->context = ctx; + + if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) { + ctx->is_shanwan = SDL_TRUE; + } + + /* Set the controller into report mode over Bluetooth */ + { + Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; + + SendFeatureReport(device->dev, data, sizeof(data)); + } + + /* Set the controller into report mode over USB */ + { + Uint8 data[USB_PACKET_LENGTH]; + int size; + + if ((size = ReadFeatureReport(device->dev, 0xf2, data, 17)) < 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf2"); + return SDL_FALSE; + } +#ifdef DEBUG_PS3_PROTOCOL + HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size); +#endif + if ((size = ReadFeatureReport(device->dev, 0xf5, data, 8)) < 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf5"); + return SDL_FALSE; + } +#ifdef DEBUG_PS3_PROTOCOL + HIDAPI_DumpPacket("PS3 0xF5 packet: size = %d", data, size); +#endif + if (!ctx->is_shanwan) { + /* An output report could cause ShanWan controllers to rumble non-stop */ + SDL_hid_write(device->dev, data, 1); + } + } + return HIDAPI_JoystickConnected(device, NULL); } @@ -190,59 +239,13 @@ HIDAPI_DriverPS3_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static SDL_bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverPS3_Context *ctx; + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; - ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - ctx->device = device; ctx->joystick = joystick; - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } - device->context = ctx; - - if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) { - ctx->is_shanwan = SDL_TRUE; - } - - /* Set the controller into report mode over Bluetooth */ - { - Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; - - SendFeatureReport(device->dev, data, sizeof(data)); - } - - /* Set the controller into report mode over USB */ - { - Uint8 data[USB_PACKET_LENGTH]; - int size; - - if ((size = ReadFeatureReport(device->dev, 0xf2, data, 17)) < 0) { - SDL_SetError("Couldn't read feature report 0xf2"); - return SDL_FALSE; - } -#ifdef DEBUG_PS3_PROTOCOL - HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size); -#endif - if ((size = ReadFeatureReport(device->dev, 0xf5, data, 8)) < 0) { - SDL_SetError("Couldn't read feature report 0xf5"); - return SDL_FALSE; - } -#ifdef DEBUG_PS3_PROTOCOL - HIDAPI_DumpPacket("PS3 0xF5 packet: size = %d", data, size); -#endif - if (!ctx->is_shanwan) { - /* An output report could cause ShanWan controllers to rumble non-stop */ - SDL_hid_write(device->dev, data, 1); - } - } + ctx->effects_updated = SDL_FALSE; + ctx->rumble_left = 0; + ctx->rumble_right = 0; + SDL_zeroa(ctx->last_state); /* Initialize player index (needed for setting LEDs) */ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); @@ -498,8 +501,7 @@ HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -507,10 +509,19 @@ HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_PS3_PROTOCOL HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); #endif + if (!joystick) { + continue; + } if (size == 7) { /* Seen on a ShanWan PS2 -> PS3 USB converter */ HIDAPI_DriverPS3_HandleMiniStatePacket(joystick, ctx, data, size); + + /* Wait for the first report to set the LED state after the controller stops blinking */ + if (!ctx->effects_updated) { + HIDAPI_DriverPS3_UpdateEffects(device); + ctx->effects_updated = SDL_TRUE; + } continue; } @@ -538,7 +549,7 @@ HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -546,15 +557,9 @@ HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) static void HIDAPI_DriverPS3_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -570,7 +575,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3 = HIDAPI_DriverPS3_UnregisterHints, HIDAPI_DriverPS3_IsEnabled, HIDAPI_DriverPS3_IsSupportedDevice, - HIDAPI_DriverPS3_GetDeviceName, HIDAPI_DriverPS3_InitDevice, HIDAPI_DriverPS3_GetDevicePlayerIndex, HIDAPI_DriverPS3_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index e927ec7b3..1fe59375b 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -142,8 +142,6 @@ typedef struct { Uint8 led_red; Uint8 led_green; Uint8 led_blue; - Uint8 volume; - Uint32 last_volume_check; PS4StatePacket_t last_state; } SDL_DriverPS4_Context; @@ -176,15 +174,6 @@ HIDAPI_DriverPS4_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverPS4_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - if (vendor_id == USB_VENDOR_SONY) { - return "PS4 Controller"; - } - return NULL; -} - static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length) { SDL_memset(report, 0, length); @@ -222,6 +211,106 @@ SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index) static SDL_bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverPS4_Context *ctx; + Uint8 data[USB_PACKET_LENGTH]; + int size; + char serial[18]; + + if (device->vendor_id == USB_VENDOR_SONY) { + HIDAPI_SetDeviceName(device, "PS4 Controller"); + } + + ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + + device->context = ctx; + + if (device->serial && SDL_strlen(device->serial) == 12) { + int i, j; + + j = -1; + for (i = 0; i < 12; i += 2) { + j += 1; + SDL_memcpy(&serial[j], &device->serial[i], 2); + j += 2; + serial[j] = '-'; + } + serial[j] = '\0'; + } else { + serial[0] = '\0'; + } + + /* Check for type of connection */ + ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE); + if (ctx->is_dongle) { + ctx->is_bluetooth = SDL_FALSE; + ctx->official_controller = SDL_TRUE; + ctx->enhanced_mode = SDL_TRUE; + } else if (device->vendor_id == USB_VENDOR_SONY) { + /* This will fail if we're on Bluetooth */ + size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data)); + if (size >= 7) { + SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", + data[6], data[5], data[4], data[3], data[2], data[1]); + ctx->is_bluetooth = SDL_FALSE; + ctx->enhanced_mode = SDL_TRUE; + } else { + ctx->is_bluetooth = SDL_TRUE; + + /* Read a report to see if we're in enhanced mode */ + size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); +#ifdef DEBUG_PS4_PROTOCOL + if (size > 0) { + HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size); + } else { + SDL_Log("PS4 first packet: size = %d\n", size); + } +#endif + if (size > 0 && + data[0] >= k_EPS4ReportIdBluetoothState1 && + data[0] <= k_EPS4ReportIdBluetoothState9) { + ctx->enhanced_mode = SDL_TRUE; + } + } + ctx->official_controller = SDL_TRUE; + } else { + /* Third party controllers appear to all be wired */ + ctx->is_bluetooth = SDL_FALSE; + ctx->enhanced_mode = SDL_TRUE; + } +#ifdef DEBUG_PS4 + SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE"); +#endif + + /* Get the device capabilities */ + if (device->vendor_id == USB_VENDOR_SONY) { + ctx->effects_supported = SDL_TRUE; + ctx->sensors_supported = SDL_TRUE; + ctx->touchpad_supported = SDL_TRUE; + } else if ((size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data))) == 48 && + data[2] == 0x27) { + Uint8 capabilities = data[4]; + +#ifdef DEBUG_PS4_PROTOCOL + HIDAPI_DumpPacket("PS4 capabilities: size = %d", data, size); +#endif + if ((capabilities & 0x0C) != 0) { + ctx->effects_supported = SDL_TRUE; + } + if ((capabilities & 0x02) != 0) { + ctx->sensors_supported = SDL_TRUE; + } + if ((capabilities & 0x40) != 0) { + ctx->touchpad_supported = SDL_TRUE; + } + } + + HIDAPI_SetDeviceSerial(device, serial); + return HIDAPI_JoystickConnected(device, NULL); } @@ -471,7 +560,7 @@ HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID { SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; - if (!ctx) { + if (!ctx->joystick) { return; } @@ -484,124 +573,28 @@ HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static SDL_bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverPS4_Context *ctx; - Uint8 data[USB_PACKET_LENGTH]; - int size; - SDL_bool enhanced_mode = SDL_FALSE; + SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *) device->context; - ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - ctx->device = device; ctx->joystick = joystick; ctx->last_packet = SDL_GetTicks(); - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } - device->context = ctx; - - /* Check for type of connection */ - ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE); - if (ctx->is_dongle) { - ctx->is_bluetooth = SDL_FALSE; - ctx->official_controller = SDL_TRUE; - enhanced_mode = SDL_TRUE; - } else if (device->vendor_id == USB_VENDOR_SONY) { - /* This will fail if we're on Bluetooth */ - size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data)); - if (size >= 7) { - char serial[18]; - - SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - data[6], data[5], data[4], data[3], data[2], data[1]); - joystick->serial = SDL_strdup(serial); - ctx->is_bluetooth = SDL_FALSE; - enhanced_mode = SDL_TRUE; - } else { - ctx->is_bluetooth = SDL_TRUE; - - /* Read a report to see if we're in enhanced mode */ - size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); -#ifdef DEBUG_PS4_PROTOCOL - if (size > 0) { - HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size); - } else { - SDL_Log("PS4 first packet: size = %d\n", size); - } -#endif - if (size > 0 && - data[0] >= k_EPS4ReportIdBluetoothState1 && - data[0] <= k_EPS4ReportIdBluetoothState9) { - enhanced_mode = SDL_TRUE; - } - } - ctx->official_controller = SDL_TRUE; - } else { - /* Third party controllers appear to all be wired */ - ctx->is_bluetooth = SDL_FALSE; - enhanced_mode = SDL_TRUE; - } -#ifdef DEBUG_PS4 - SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE"); -#endif - - /* Get the device capabilities */ - if (device->vendor_id == USB_VENDOR_SONY) { - ctx->effects_supported = SDL_TRUE; - ctx->sensors_supported = SDL_TRUE; - ctx->touchpad_supported = SDL_TRUE; - } else if ((size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data))) == 48 && - data[2] == 0x27) { - Uint8 capabilities = data[4]; - -#ifdef DEBUG_PS4_PROTOCOL - HIDAPI_DumpPacket("PS4 capabilities: size = %d", data, size); -#endif - if ((capabilities & 0x0C) != 0) { - ctx->effects_supported = SDL_TRUE; - } - if ((capabilities & 0x02) != 0) { - ctx->sensors_supported = SDL_TRUE; - } - if ((capabilities & 0x40) != 0) { - ctx->touchpad_supported = SDL_TRUE; - } - } - - if (!joystick->serial && device->serial && SDL_strlen(device->serial) == 12) { - int i, j; - char serial[18]; - - j = -1; - for (i = 0; i < 12; i += 2) { - j += 1; - SDL_memcpy(&serial[j], &device->serial[i], 2); - j += 2; - serial[j] = '-'; - } - serial[j] = '\0'; - - joystick->serial = SDL_strdup(serial); - } + ctx->report_sensors = SDL_FALSE; + ctx->report_touchpad = SDL_FALSE; + ctx->rumble_left = 0; + ctx->rumble_right = 0; + ctx->color_set = SDL_FALSE; + SDL_zero(ctx->last_state); /* Initialize player index (needed for setting LEDs) */ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); - /* Initialize the joystick capabilities - * - * We can't dynamically add the touchpad button, so always report it here - */ - joystick->nbuttons = 16; + /* Initialize the joystick capabilities */ + joystick->nbuttons = ctx->touchpad_supported ? 16 : 15; joystick->naxes = SDL_CONTROLLER_AXIS_MAX; joystick->epowerlevel = ctx->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED; - if (enhanced_mode) { + if (ctx->enhanced_mode) { + /* Force initialization when opening the joystick */ + ctx->enhanced_mode = SDL_FALSE; HIDAPI_DriverPS4_SetEnhancedMode(device, joystick); } else { SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, @@ -879,8 +872,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -891,6 +883,10 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) ++packet_count; ctx->last_packet = SDL_GetTicks(); + if (!joystick) { + continue; + } + switch (data[0]) { case k_EPS4ReportIdUsbState: HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1]); @@ -931,7 +927,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -944,15 +940,7 @@ HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_PS4RumbleHintChanged, ctx); - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -968,7 +956,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 = HIDAPI_DriverPS4_UnregisterHints, HIDAPI_DriverPS4_IsEnabled, HIDAPI_DriverPS4_IsSupportedDevice, - HIDAPI_DriverPS4_GetDeviceName, HIDAPI_DriverPS4_InitDevice, HIDAPI_DriverPS4_GetDevicePlayerIndex, HIDAPI_DriverPS4_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index bb03cbf8a..638bc4491 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -256,15 +256,6 @@ HIDAPI_DriverPS5_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverPS5_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - if (vendor_id == USB_VENDOR_SONY) { - return "PS5 Controller"; - } - return NULL; -} - static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length) { SDL_memset(report, 0, length); @@ -321,6 +312,112 @@ SetLightsForPlayerIndex(DS5EffectsState_t *effects, int player_index) static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverPS5_Context *ctx; + Uint8 data[USB_PACKET_LENGTH*2]; + int size; + char serial[18]; + + if (device->vendor_id == USB_VENDOR_SONY) { + HIDAPI_SetDeviceName(device, "PS5 Controller"); + } + + ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + + device->context = ctx; + + if (device->serial && SDL_strlen(device->serial) == 12) { + int i, j; + + j = -1; + for (i = 0; i < 12; i += 2) { + j += 1; + SDL_memcpy(&serial[j], &device->serial[i], 2); + j += 2; + serial[j] = '-'; + } + serial[j] = '\0'; + } else { + serial[0] = '\0'; + } + + /* Read a report to see what mode we're in */ + size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); +#ifdef DEBUG_PS5_PROTOCOL + if (size > 0) { + HIDAPI_DumpPacket("PS5 first packet: size = %d", data, size); + } else { + SDL_Log("PS5 first packet: size = %d\n", size); + } +#endif + if (size == 64) { + /* Connected over USB */ + ctx->is_bluetooth = SDL_FALSE; + ctx->enhanced_mode = SDL_TRUE; + } else if (size > 0 && data[0] == k_EPS5ReportIdBluetoothEffects) { + /* Connected over Bluetooth, using enhanced reports */ + ctx->is_bluetooth = SDL_TRUE; + ctx->enhanced_mode = SDL_TRUE; + } else { + /* Connected over Bluetooth, using simple reports (DirectInput enabled) */ + ctx->is_bluetooth = SDL_TRUE; + + /* Games written prior the introduction of PS5 controller support in SDL will not be aware of + SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, but they did know SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE. + To support apps that only knew about the PS4 hint, we'll use the PS4 hint as the default. + */ + ctx->enhanced_mode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE)); + } + + if (ctx->enhanced_mode) { + /* Read the serial number (Bluetooth address in reverse byte order) + This will also enable enhanced reports over Bluetooth + */ + if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdSerialNumber, data, sizeof(data)) >= 7) { + SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", + data[6], data[5], data[4], data[3], data[2], data[1]); + } + + /* Read the firmware version + This will also enable enhanced reports over Bluetooth + */ + if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdFirmwareInfo, data, USB_PACKET_LENGTH) >= 46) { + ctx->firmware_version = (Uint16)data[44] | ((Uint16)data[45] << 8); + } + } + + /* Get the device capabilities */ + if (device->vendor_id == USB_VENDOR_SONY) { + ctx->effects_supported = SDL_TRUE; + ctx->sensors_supported = SDL_TRUE; + ctx->touchpad_supported = SDL_TRUE; + } else if ((size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data))) == 48 && + data[2] == 0x28) { + Uint8 capabilities = data[4]; + +#ifdef DEBUG_PS5_PROTOCOL + HIDAPI_DumpPacket("PS5 capabilities: size = %d", data, size); +#endif + if ((capabilities & 0x0C) != 0) { + ctx->effects_supported = SDL_TRUE; + } + if ((capabilities & 0x02) != 0) { + ctx->sensors_supported = SDL_TRUE; + } + if ((capabilities & 0x40) != 0) { + ctx->touchpad_supported = SDL_TRUE; + } + + ctx->use_alternate_report = SDL_TRUE; + } + + HIDAPI_SetDeviceSerial(device, serial); + return HIDAPI_JoystickConnected(device, NULL); } @@ -623,7 +720,7 @@ HIDAPI_DriverPS5_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID { SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context; - if (!ctx) { + if (!ctx->joystick) { return; } @@ -636,132 +733,31 @@ HIDAPI_DriverPS5_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverPS5_Context *ctx; - Uint8 data[USB_PACKET_LENGTH*2]; - int size; - SDL_bool enhanced_mode = SDL_FALSE; + SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context; - ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - ctx->device = device; ctx->joystick = joystick; ctx->last_packet = SDL_GetTicks(); - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } - device->context = ctx; - - /* Read a report to see what mode we're in */ - size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16); -#ifdef DEBUG_PS5_PROTOCOL - if (size > 0) { - HIDAPI_DumpPacket("PS5 first packet: size = %d", data, size); - } else { - SDL_Log("PS5 first packet: size = %d\n", size); - } -#endif - if (size == 64) { - /* Connected over USB */ - ctx->is_bluetooth = SDL_FALSE; - enhanced_mode = SDL_TRUE; - } else if (size > 0 && data[0] == k_EPS5ReportIdBluetoothEffects) { - /* Connected over Bluetooth, using enhanced reports */ - ctx->is_bluetooth = SDL_TRUE; - enhanced_mode = SDL_TRUE; - } else { - /* Connected over Bluetooth, using simple reports (DirectInput enabled) */ - ctx->is_bluetooth = SDL_TRUE; - - /* Games written prior the introduction of PS5 controller support in SDL will not be aware of - SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, but they did know SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE. - To support apps that only knew about the PS4 hint, we'll use the PS4 hint as the default. - */ - enhanced_mode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, - SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE)); - } - - if (enhanced_mode) { - /* Read the serial number (Bluetooth address in reverse byte order) - This will also enable enhanced reports over Bluetooth - */ - if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdSerialNumber, data, sizeof(data)) >= 7) { - char serial[18]; - - SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - data[6], data[5], data[4], data[3], data[2], data[1]); - joystick->serial = SDL_strdup(serial); - } - - /* Read the firmware version - This will also enable enhanced reports over Bluetooth - */ - if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdFirmwareInfo, data, USB_PACKET_LENGTH) >= 46) { - ctx->firmware_version = (Uint16)data[44] | ((Uint16)data[45] << 8); - joystick->firmware_version = ctx->firmware_version; - } - } - - /* Get the device capabilities */ - if (device->vendor_id == USB_VENDOR_SONY) { - ctx->effects_supported = SDL_TRUE; - ctx->sensors_supported = SDL_TRUE; - ctx->touchpad_supported = SDL_TRUE; - } else if ((size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data))) == 48 && - data[2] == 0x28) { - Uint8 capabilities = data[4]; - -#ifdef DEBUG_PS5_PROTOCOL - HIDAPI_DumpPacket("PS5 capabilities: size = %d", data, size); -#endif - if ((capabilities & 0x0C) != 0) { - ctx->effects_supported = SDL_TRUE; - } - if ((capabilities & 0x02) != 0) { - ctx->sensors_supported = SDL_TRUE; - } - if ((capabilities & 0x40) != 0) { - ctx->touchpad_supported = SDL_TRUE; - } - - ctx->use_alternate_report = SDL_TRUE; - } - - if (!joystick->serial && device->serial && SDL_strlen(device->serial) == 12) { - int i, j; - char serial[18]; - - j = -1; - for (i = 0; i < 12; i += 2) { - j += 1; - SDL_memcpy(&serial[j], &device->serial[i], 2); - j += 2; - serial[j] = '-'; - } - serial[j] = '\0'; - - joystick->serial = SDL_strdup(serial); - } + ctx->report_sensors = SDL_FALSE; + ctx->report_touchpad = SDL_FALSE; + ctx->rumble_left = 0; + ctx->rumble_right = 0; + ctx->color_set = SDL_FALSE; + ctx->led_reset_state = k_EDS5LEDResetStateNone; + SDL_zero(ctx->last_state); /* Initialize player index (needed for setting LEDs) */ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); ctx->player_lights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, SDL_TRUE); - /* Initialize the joystick capabilities - * - * We can't dynamically add the touchpad button, so always report it here - */ - joystick->nbuttons = 17; + /* Initialize the joystick capabilities */ + joystick->nbuttons = ctx->touchpad_supported ? 17 : 15; joystick->naxes = SDL_CONTROLLER_AXIS_MAX; joystick->epowerlevel = ctx->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED; + joystick->firmware_version = ctx->firmware_version; - if (enhanced_mode) { + if (ctx->enhanced_mode) { + /* Force initialization when opening the joystick */ + ctx->enhanced_mode = SDL_FALSE; HIDAPI_DriverPS5_SetEnhancedMode(device, joystick); } else { SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, @@ -769,6 +765,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) } SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, SDL_PS5PlayerLEDHintChanged, ctx); + return SDL_TRUE; } @@ -1183,8 +1180,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -1195,6 +1191,10 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) ++packet_count; ctx->last_packet = SDL_GetTicks(); + if (!joystick) { + continue; + } + switch (data[0]) { case k_EPS5ReportIdState: if (size == 10 || size == 78) { @@ -1241,7 +1241,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -1257,15 +1257,7 @@ HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, SDL_PS5PlayerLEDHintChanged, ctx); - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -1281,7 +1273,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 = HIDAPI_DriverPS5_UnregisterHints, HIDAPI_DriverPS5_IsEnabled, HIDAPI_DriverPS5_IsSupportedDevice, - HIDAPI_DriverPS5_GetDeviceName, HIDAPI_DriverPS5_InitDevice, HIDAPI_DriverPS5_GetDevicePlayerIndex, HIDAPI_DriverPS5_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 69ab1a4a0..42cfea1c8 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -107,15 +107,20 @@ HIDAPI_DriverShield_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *nam return (type == SDL_CONTROLLER_TYPE_NVIDIA_SHIELD) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverShield_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "NVIDIA SHIELD Controller"; -} - static SDL_bool HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverShield_Context *ctx; + + HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller"); + + ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + device->context = ctx; + return HIDAPI_JoystickConnected(device, NULL); } @@ -133,7 +138,7 @@ HIDAPI_DriverShield_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystick static int HIDAPI_DriverShield_SendCommand(SDL_HIDAPI_Device *device, Uint8 cmd, const void *data, int size) { - SDL_DriverShield_Context *ctx = device->context; + SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context; ShieldCommandReport_t cmd_pkt; if (size > sizeof(cmd_pkt.payload)) { @@ -164,21 +169,14 @@ HIDAPI_DriverShield_SendCommand(SDL_HIDAPI_Device *device, Uint8 cmd, const void static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverShield_Context *ctx; + SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context; - ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - SDL_free(ctx); - return SDL_FALSE; - } - device->context = ctx; + ctx->rumble_report_pending = SDL_FALSE; + ctx->rumble_update_pending = SDL_FALSE; + ctx->left_motor_amplitude = 0; + ctx->right_motor_amplitude = 0; + ctx->last_rumble_time = 0; + SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ joystick->nbuttons = 16; @@ -186,7 +184,6 @@ HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; /* Request battery and charging info */ - ctx->battery_level = SDL_JOYSTICK_POWER_UNKNOWN; ctx->last_battery_query_time = SDL_GetTicks(); HIDAPI_DriverShield_SendCommand(device, CMD_CHARGE_STATE, NULL, 0); HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0); @@ -367,8 +364,7 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -376,9 +372,13 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_SHIELD_PROTOCOL HIDAPI_DumpPacket("NVIDIA SHIELD packet: size = %d", data, size); #endif + /* Byte 0 is HID report ID */ switch (data[0]) { case k_ShieldReportIdControllerState: + if (!joystick) { + break; + } HIDAPI_DriverShield_HandleStatePacket(joystick, ctx, data, size); break; case k_ShieldReportIdCommandResponse: @@ -390,7 +390,9 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) break; case CMD_CHARGE_STATE: ctx->charging = cmd_resp_report->payload[0] != 0; - SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level); + if (joystick) { + SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level); + } break; case CMD_BATTERY_STATE: switch (cmd_resp_report->payload[2]) { @@ -412,7 +414,9 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) ctx->battery_level = SDL_JOYSTICK_POWER_UNKNOWN; break; } - SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level); + if (joystick) { + SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level); + } break; } break; @@ -420,7 +424,7 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) } /* Ask for battery state again if we're due for an update */ - if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_battery_query_time + BATTERY_POLL_INTERVAL_MS)) { + if (joystick && SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_battery_query_time + BATTERY_POLL_INTERVAL_MS)) { ctx->last_battery_query_time = SDL_GetTicks(); HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0); } @@ -434,7 +438,7 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -442,17 +446,6 @@ HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device) static void HIDAPI_DriverShield_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } static void @@ -468,7 +461,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield = HIDAPI_DriverShield_UnregisterHints, HIDAPI_DriverShield_IsEnabled, HIDAPI_DriverShield_IsSupportedDevice, - HIDAPI_DriverShield_GetDeviceName, HIDAPI_DriverShield_InitDevice, HIDAPI_DriverShield_GetDevicePlayerIndex, HIDAPI_DriverShield_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 23056acff..8b20d75ab 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -73,15 +73,20 @@ HIDAPI_DriverStadia_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *nam return (type == SDL_CONTROLLER_TYPE_GOOGLE_STADIA) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverStadia_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "Google Stadia Controller"; -} - static SDL_bool HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverStadia_Context *ctx; + + HIDAPI_SetDeviceName(device, "Google Stadia Controller"); + + ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + device->context = ctx; + return HIDAPI_JoystickConnected(device, NULL); } @@ -99,21 +104,9 @@ HIDAPI_DriverStadia_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystick static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverStadia_Context *ctx; + SDL_DriverStadia_Context *ctx = (SDL_DriverStadia_Context *)device->context; - ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - SDL_free(ctx); - return SDL_FALSE; - } - device->context = ctx; + SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ joystick->nbuttons = SDL_CONTROLLER_NUM_STADIA_BUTTONS; @@ -281,8 +274,7 @@ HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -290,12 +282,16 @@ HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_STADIA_PROTOCOL HIDAPI_DumpPacket("Google Stadia packet: size = %d", data, size); #endif + if (!joystick) { + continue; + } + HIDAPI_DriverStadia_HandleStatePacket(joystick, ctx, data, size); } if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -303,17 +299,6 @@ HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device) static void HIDAPI_DriverStadia_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } static void @@ -329,7 +314,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia = HIDAPI_DriverStadia_UnregisterHints, HIDAPI_DriverStadia_IsEnabled, HIDAPI_DriverStadia_IsSupportedDevice, - HIDAPI_DriverStadia_GetDeviceName, HIDAPI_DriverStadia_InitDevice, HIDAPI_DriverStadia_GetDevicePlayerIndex, HIDAPI_DriverStadia_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 2faf65c36..64ce13ade 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1022,15 +1022,20 @@ HIDAPI_DriverSteam_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name return SDL_IsJoystickSteamController(vendor_id, product_id); } -static const char * -HIDAPI_DriverSteam_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "Steam Controller"; -} - static SDL_bool HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverSteam_Context *ctx; + + HIDAPI_SetDeviceName(device, "Steam Controller"); + + ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + device->context = ctx; + return HIDAPI_JoystickConnected(device, NULL); } @@ -1048,27 +1053,18 @@ HIDAPI_DriverSteam_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickI static SDL_bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverSteam_Context *ctx; + SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context; uint32_t update_rate_in_us = 0; float update_rate_in_hz = 0.0f; - ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - goto error; - } - device->context = ctx; - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - goto error; - } - SDL_hid_set_nonblocking(device->dev, 1); + ctx->report_sensors = SDL_FALSE; + SDL_zero(ctx->m_assembler); + SDL_zero(ctx->m_state); + SDL_zero(ctx->m_last_state); if (!ResetSteamController(device->dev, false, &update_rate_in_us)) { SDL_SetError("Couldn't reset controller"); - goto error; + return SDL_FALSE; } if (update_rate_in_us > 0) { update_rate_in_hz = 1000000.0f / update_rate_in_us; @@ -1084,21 +1080,6 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz); return SDL_TRUE; - -error: - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - if (device->context) { - SDL_free(device->context); - device->context = NULL; - } - } - SDL_UnlockMutex(device->dev_lock); - return SDL_FALSE; } static int @@ -1117,7 +1098,7 @@ HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystic static Uint32 HIDAPI_DriverSteam_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - /* You should use the full Steam Input API for LED support */ + /* You should use the full Steam Input API for extended capabilities */ return 0; } @@ -1166,8 +1147,7 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -1178,11 +1158,14 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) const Uint8 *pPacket; r = ReadSteamController(device->dev, data, sizeof(data)); - if (r == 0) - { + if (r == 0) { break; } + if (!joystick) { + continue; + } + nPacketLength = 0; if (r > 0) { nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&ctx->m_assembler, data, r); @@ -1281,17 +1264,7 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) static void HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - CloseSteamController(device->dev); - - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + CloseSteamController(device->dev); } static void @@ -1307,7 +1280,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam = HIDAPI_DriverSteam_UnregisterHints, HIDAPI_DriverSteam_IsEnabled, HIDAPI_DriverSteam_IsSupportedDevice, - HIDAPI_DriverSteam_GetDeviceName, HIDAPI_DriverSteam_InitDevice, HIDAPI_DriverSteam_GetDevicePlayerIndex, HIDAPI_DriverSteam_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 727b59ce1..e05fdc391 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -236,6 +236,7 @@ typedef struct typedef struct { SDL_HIDAPI_Device *device; + SDL_Joystick *joystick; SDL_bool m_bInputOnly; SDL_bool m_bUsingBluetooth; SDL_bool m_bIsGameCube; @@ -556,6 +557,29 @@ static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx) return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket)); } +static ESwitchDeviceInfoControllerType CalculateControllerType(SDL_DriverSwitch_Context *ctx, ESwitchDeviceInfoControllerType eControllerType) +{ + SDL_HIDAPI_Device *device = ctx->device; + + /* The N64 controller reports as a Pro controller over USB */ + if (eControllerType == k_eSwitchDeviceInfoControllerType_ProController && + device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { + eControllerType = k_eSwitchDeviceInfoControllerType_N64; + } + + if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown) { + /* This might be a Joy-Con that's missing from a charging grip slot */ + if (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { + if (device->interface_number == 1) { + eControllerType = k_eSwitchDeviceInfoControllerType_JoyConLeft; + } else { + eControllerType = k_eSwitchDeviceInfoControllerType_JoyConRight; + } + } + } + return eControllerType; +} + static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx) { SwitchSubcommandInputPacket_t *reply = NULL; @@ -566,13 +590,7 @@ static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx) SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0]; size_t i; - ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)status->ucDeviceType; - - /* The N64 controller reports as a Pro controller over USB */ - if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_ProController && - ctx->device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { - ctx->m_eControllerType = k_eSwitchDeviceInfoControllerType_N64; - } + ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType); for (i = 0; i < sizeof (ctx->m_rgucMACAddress); ++i) ctx->m_rgucMACAddress[i] = status->rgucMACAddress[ sizeof(ctx->m_rgucMACAddress) - i - 1 ]; @@ -584,7 +602,7 @@ static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx) if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) { // Byte 2: Controller ID (1=LJC, 2=RJC, 3=Pro) - ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType; + ctx->m_eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType); // Bytes 4-9: MAC address (big-endian) SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress)); @@ -909,6 +927,8 @@ static ESwitchDeviceInfoControllerType ReadJoyConControllerType(SDL_HIDAPI_Device *device) { ESwitchDeviceInfoControllerType eControllerType = k_eSwitchDeviceInfoControllerType_Unknown; + const int MAX_ATTEMPTS = 20; + int attempts = 0; /* Create enough of a context to read the controller type from the device */ SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx)); @@ -917,39 +937,26 @@ ReadJoyConControllerType(SDL_HIDAPI_Device *device) ctx->m_bSyncWrite = SDL_TRUE; ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device); - device->dev = SDL_hid_open_path(device->path, 0); - if (device->dev) { - const int MAX_ATTEMPTS = 20; - int attempts = 0; - for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) { - if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) { - SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0]; + for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) { + if (WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Status, NULL, 0, SDL_TRUE)) { + SwitchProprietaryStatusPacket_t *status = (SwitchProprietaryStatusPacket_t *)&ctx->m_rgucReadBuffer[0]; - eControllerType = (ESwitchDeviceInfoControllerType) status->ucDeviceType; + eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)status->ucDeviceType); + } else { + SwitchSubcommandInputPacket_t *reply = NULL; - /* The N64 controller reports as a Pro controller over USB */ - if (eControllerType == k_eSwitchDeviceInfoControllerType_ProController && - device->product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { - eControllerType = k_eSwitchDeviceInfoControllerType_N64; - } - } else { - SwitchSubcommandInputPacket_t *reply = NULL; - - ctx->m_bUsingBluetooth = SDL_TRUE; - if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) { - eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType; - } - } - if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown) { - /* Wait a bit and try again */ - SDL_Delay(100); - continue; - } else { - break; + ctx->m_bUsingBluetooth = SDL_TRUE; + if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_RequestDeviceInfo, NULL, 0, &reply)) { + eControllerType = CalculateControllerType(ctx, (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType); } } - SDL_hid_close(device->dev); - device->dev = NULL; + if (eControllerType == k_eSwitchDeviceInfoControllerType_Unknown) { + /* Wait a bit and try again */ + SDL_Delay(100); + continue; + } else { + break; + } } SDL_free(ctx); } @@ -1144,121 +1151,91 @@ HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *nam return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - /* Give a user friendly name for this controller */ - if (vendor_id == USB_VENDOR_NINTENDO) { - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - /* We don't know if this is left or right, just leave it alone */ - return NULL; - } - - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) { - return "Nintendo Switch Joy-Con (L)"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) { - if (SDL_strncmp(name, "NES Controller", 14) == 0) { - if (SDL_strstr(name, "(L)") != 0) { - return "Nintendo NES Controller (L)"; - } else if (SDL_strstr(name, "(R)") != 0) { - return "Nintendo NES Controller (R)"; - } else { - /* Not sure what this is, just leave it alone */ - return NULL; - } - } - return "Nintendo Switch Joy-Con (R)"; - } - - if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { - return "Nintendo N64 Controller"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) { - return "Nintendo SEGA Genesis Controller"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) { - return "Nintendo SNES Controller"; - } - } - - return "Nintendo Switch Pro Controller"; -} - static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device) { - ESwitchDeviceInfoControllerType eControllerType = (ESwitchDeviceInfoControllerType)device->guid.data[15]; - const char *name = NULL; + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; + char serial[18]; - switch (eControllerType) { + switch (ctx->m_eControllerType) { case k_eSwitchDeviceInfoControllerType_JoyConLeft: - name = "Nintendo Switch Joy-Con (L)"; - SDL_SetJoystickGUIDProduct(&device->guid, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT); + HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT); break; case k_eSwitchDeviceInfoControllerType_JoyConRight: - name = "Nintendo Switch Joy-Con (R)"; - SDL_SetJoystickGUIDProduct(&device->guid, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT); + HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT); break; case k_eSwitchDeviceInfoControllerType_ProController: - name = "Nintendo Switch Pro Controller"; - SDL_SetJoystickGUIDProduct(&device->guid, USB_PRODUCT_NINTENDO_SWITCH_PRO); + HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_PRO); break; case k_eSwitchDeviceInfoControllerType_NESLeft: - name = "Nintendo NES Controller (L)"; + HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)"); break; case k_eSwitchDeviceInfoControllerType_NESRight: - name = "Nintendo NES Controller (R)"; + HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)"); break; case k_eSwitchDeviceInfoControllerType_SNES: - name = "Nintendo SNES Controller"; - SDL_SetJoystickGUIDProduct(&device->guid, USB_PRODUCT_NINTENDO_SNES_CONTROLLER); + HIDAPI_SetDeviceName(device, "Nintendo SNES Controller"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SNES_CONTROLLER); break; case k_eSwitchDeviceInfoControllerType_N64: - name = "Nintendo N64 Controller"; - device->product_id = USB_PRODUCT_NINTENDO_N64_CONTROLLER; + HIDAPI_SetDeviceName(device, "Nintendo N64 Controller"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_N64_CONTROLLER); break; case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: - name = "Nintendo SEGA Genesis Controller"; - SDL_SetJoystickGUIDProduct(&device->guid, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER); + HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller"); + HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER); break; default: break; } + device->guid.data[15] = ctx->m_eControllerType; - if (name && (!name || SDL_strcmp(name, device->name) != 0)) { - SDL_free(device->name); - device->name = SDL_strdup(name); - SDL_SetJoystickGUIDCRC(&device->guid, SDL_crc16(0, name, SDL_strlen(name))); - } + SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", + ctx->m_rgucMACAddress[0], + ctx->m_rgucMACAddress[1], + ctx->m_rgucMACAddress[2], + ctx->m_rgucMACAddress[3], + ctx->m_rgucMACAddress[4], + ctx->m_rgucMACAddress[5]); + HIDAPI_SetDeviceSerial(device, serial); } static SDL_bool HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) { - /* The NES controllers need additional fix up, since we can't detect them without opening the device */ - if (device->vendor_id == USB_VENDOR_NINTENDO) { - ESwitchDeviceInfoControllerType eControllerType = ReadJoyConControllerType(device); - switch (eControllerType) { - case k_eSwitchDeviceInfoControllerType_Unknown: - /* This might be a Joy-Con that's missing from a charging grip slot */ - if (device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - if (device->interface_number == 1) { - device->guid.data[15] = k_eSwitchDeviceInfoControllerType_JoyConLeft; - } else { - device->guid.data[15] = k_eSwitchDeviceInfoControllerType_JoyConRight; - } - } - break; - default: - device->guid.data[15] = eControllerType; - break; + SDL_DriverSwitch_Context *ctx; + + ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + device->context = ctx; + + ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device); + ctx->m_bSyncWrite = SDL_TRUE; + + if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) { + /* This is a controller shaped like a GameCube controller, with a large central A button */ + ctx->m_bIsGameCube = SDL_TRUE; + } + + /* Find out whether or not we can send output reports */ + ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id); + if (!ctx->m_bInputOnly) { + if (!BReadDeviceInfo(ctx)) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverSwitch_InitDevice(): Couldn't read device info"); + return SDL_FALSE; } + UpdateDeviceIdentity(device); } + return HIDAPI_JoystickConnected(device, NULL); } @@ -1273,7 +1250,7 @@ HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystick { SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; - if (!ctx) { + if (!ctx->joystick) { return; } @@ -1285,41 +1262,22 @@ HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystick static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverSwitch_Context *ctx; + SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; Uint8 input_mode; - ctx = (SDL_DriverSwitch_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - goto error; - } - ctx->device = device; - device->context = ctx; + ctx->joystick = joystick; - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - goto error; - } - ctx->m_nMaxWriteAttempts = GetMaxWriteAttempts(device); ctx->m_bSyncWrite = SDL_TRUE; - /* Find out whether or not we can send output reports */ - ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(device->vendor_id, device->product_id); if (!ctx->m_bInputOnly) { /* Initialize rumble data */ SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]); SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]); - if (!BReadDeviceInfo(ctx)) { - SDL_SetError("Couldn't read device info"); - goto error; - } - if (!ctx->m_bUsingBluetooth) { if (!BTrySetupUSB(ctx)) { SDL_SetError("Couldn't setup USB mode"); - goto error; + return SDL_FALSE; } } @@ -1365,23 +1323,23 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti if (!LoadStickCalibration(ctx, input_mode)) { SDL_SetError("Couldn't load stick calibration"); - goto error; + return SDL_FALSE; } if (!LoadIMUCalibration(ctx)) { SDL_SetError("Couldn't load sensor calibration"); - goto error; + return SDL_FALSE; } if (!SetVibrationEnabled(ctx, 1)) { SDL_SetError("Couldn't enable vibration"); - goto error; + return SDL_FALSE; } /* Set desired input mode */ if (!SetInputMode(ctx, input_mode)) { SDL_SetError("Couldn't set input mode"); - goto error; + return SDL_FALSE; } /* Start sending USB reports */ @@ -1389,7 +1347,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti /* ForceUSB doesn't generate an ACK, so don't wait for a reply */ if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE)) { SDL_SetError("Couldn't start USB reports"); - goto error; + return SDL_FALSE; } } @@ -1404,28 +1362,6 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti SDL_HomeLEDHintChanged, ctx); } } - - /* Set the serial number */ - { - char serial[18]; - - SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - ctx->m_rgucMACAddress[0], - ctx->m_rgucMACAddress[1], - ctx->m_rgucMACAddress[2], - ctx->m_rgucMACAddress[3], - ctx->m_rgucMACAddress[4], - ctx->m_rgucMACAddress[5]); - if (joystick->serial) { - SDL_free(joystick->serial); - } - joystick->serial = SDL_strdup(serial); - } - } - - if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) { - /* This is a controller shaped like a GameCube controller, with a large central A button */ - ctx->m_bIsGameCube = SDL_TRUE; } if (AlwaysUsesLabels(device->vendor_id, device->product_id, ctx->m_eControllerType)) { @@ -1453,21 +1389,6 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti ctx->m_unLastIMUReset = ctx->m_unLastInput = SDL_GetTicks(); return SDL_TRUE; - -error: - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - if (device->context) { - SDL_free(device->context); - device->context = NULL; - } - } - SDL_UnlockMutex(device->dev_lock); - return SDL_FALSE; } static int @@ -2142,8 +2063,7 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -2153,35 +2073,39 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) #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 { - switch (ctx->m_rgucReadBuffer[0]) { - case k_eSwitchInputReportIDs_SimpleControllerState: - HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]); - break; - case k_eSwitchInputReportIDs_FullControllerState: - HandleFullControllerState(joystick, ctx, (SwitchStatePacket_t *)&ctx->m_rgucReadBuffer[1]); - break; - default: - break; + if (joystick) { + if (ctx->m_bInputOnly) { + HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]); + } else { + switch (ctx->m_rgucReadBuffer[0]) { + case k_eSwitchInputReportIDs_SimpleControllerState: + HandleSimpleControllerState(joystick, ctx, (SwitchSimpleStatePacket_t *)&ctx->m_rgucReadBuffer[1]); + break; + case k_eSwitchInputReportIDs_FullControllerState: + HandleFullControllerState(joystick, ctx, (SwitchStatePacket_t *)&ctx->m_rgucReadBuffer[1]); + break; + default: + break; + } } } ctx->m_unLastInput = now; } - if (!ctx->m_bInputOnly && !ctx->m_bUsingBluetooth && - ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - const Uint32 INPUT_WAIT_TIMEOUT_MS = 100; - if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { - /* Steam may have put the controller back into non-reporting mode */ - WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE); - } - } else if (ctx->m_bUsingBluetooth) { - const Uint32 INPUT_WAIT_TIMEOUT_MS = 3000; - if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { - /* Bluetooth may have disconnected, try reopening the controller */ - size = -1; + if (joystick) { + if (!ctx->m_bInputOnly && !ctx->m_bUsingBluetooth && + ctx->device->product_id != USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { + const Uint32 INPUT_WAIT_TIMEOUT_MS = 100; + if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { + /* Steam may have put the controller back into non-reporting mode */ + WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE); + } + } else if (ctx->m_bUsingBluetooth) { + const Uint32 INPUT_WAIT_TIMEOUT_MS = 3000; + if (SDL_TICKS_PASSED(now, ctx->m_unLastInput + INPUT_WAIT_TIMEOUT_MS)) { + /* Bluetooth may have disconnected, try reopening the controller */ + size = -1; + } } } @@ -2197,7 +2121,7 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -2227,15 +2151,7 @@ HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, SDL_PlayerLEDHintChanged, ctx); - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -2251,7 +2167,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverNintendoClassic = HIDAPI_DriverNintendoClassic_UnregisterHints, HIDAPI_DriverNintendoClassic_IsEnabled, HIDAPI_DriverNintendoClassic_IsSupportedDevice, - HIDAPI_DriverSwitch_GetDeviceName, HIDAPI_DriverSwitch_InitDevice, HIDAPI_DriverSwitch_GetDevicePlayerIndex, HIDAPI_DriverSwitch_SetDevicePlayerIndex, @@ -2275,7 +2190,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverJoyCons = HIDAPI_DriverJoyCons_UnregisterHints, HIDAPI_DriverJoyCons_IsEnabled, HIDAPI_DriverJoyCons_IsSupportedDevice, - HIDAPI_DriverSwitch_GetDeviceName, HIDAPI_DriverSwitch_InitDevice, HIDAPI_DriverSwitch_GetDevicePlayerIndex, HIDAPI_DriverSwitch_SetDevicePlayerIndex, @@ -2299,7 +2213,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch = HIDAPI_DriverSwitch_UnregisterHints, HIDAPI_DriverSwitch_IsEnabled, HIDAPI_DriverSwitch_IsSupportedDevice, - HIDAPI_DriverSwitch_GetDeviceName, HIDAPI_DriverSwitch_InitDevice, HIDAPI_DriverSwitch_GetDevicePlayerIndex, HIDAPI_DriverSwitch_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index f7a8eb832..9c9695080 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -131,6 +131,7 @@ typedef struct { typedef struct { SDL_HIDAPI_Device *device; + SDL_Joystick *joystick; EWiiCommunicationState m_eCommState; EWiiExtensionControllerType m_eExtensionControllerType; SDL_bool m_bUseButtonLabels; @@ -185,12 +186,6 @@ HIDAPI_DriverWii_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, return SDL_FALSE; } -static const char * -HIDAPI_DriverWii_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return NULL; -} - static int ReadInput(SDL_DriverWii_Context *ctx) { int size; @@ -671,45 +666,35 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c static EWiiExtensionControllerType ReadExtensionControllerType(SDL_HIDAPI_Device *device) { + SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; EWiiExtensionControllerType eExtensionControllerType = k_eWiiExtensionControllerType_Unknown; + const int MAX_ATTEMPTS = 20; + int attempts = 0; /* Create enough of a context to read the controller type from the device */ - SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx)); - if (ctx) { - ctx->device = device; - - device->dev = SDL_hid_open_path(device->path, 0); - if (device->dev) { - const int MAX_ATTEMPTS = 20; - int attempts = 0; - for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) { - Uint16 extension; - if (SendExtensionIdentify(ctx, SDL_TRUE) && - ParseExtensionIdentifyResponse(ctx, &extension)) { - Uint8 motion_plus_mode = 0; - if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) { - motion_plus_mode = (Uint8)(extension >> 8); - } - if (motion_plus_mode || extension == WII_EXTENSION_UNINITIALIZED) { - SendExtensionReset(ctx, SDL_TRUE); - if (SendExtensionIdentify(ctx, SDL_TRUE)) { - ParseExtensionIdentifyResponse(ctx, &extension); - } - } - - eExtensionControllerType = GetExtensionType(extension); - - /* Reset the Motion Plus controller if needed */ - if (motion_plus_mode) { - ActivateMotionPlusWithMode(ctx, motion_plus_mode); - } - break; + for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) { + Uint16 extension; + if (SendExtensionIdentify(ctx, SDL_TRUE) && + ParseExtensionIdentifyResponse(ctx, &extension)) { + Uint8 motion_plus_mode = 0; + if ((extension & WII_EXTENSION_MOTIONPLUS_MASK) == WII_EXTENSION_MOTIONPLUS_ID) { + motion_plus_mode = (Uint8)(extension >> 8); + } + if (motion_plus_mode || extension == WII_EXTENSION_UNINITIALIZED) { + SendExtensionReset(ctx, SDL_TRUE); + if (SendExtensionIdentify(ctx, SDL_TRUE)) { + ParseExtensionIdentifyResponse(ctx, &extension); } } - SDL_hid_close(device->dev); - device->dev = NULL; + + eExtensionControllerType = GetExtensionType(extension); + + /* Reset the Motion Plus controller if needed */ + if (motion_plus_mode) { + ActivateMotionPlusWithMode(ctx, motion_plus_mode); + } + break; } - SDL_free(ctx); } return eExtensionControllerType; } @@ -717,41 +702,44 @@ ReadExtensionControllerType(SDL_HIDAPI_Device *device) static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device) { - EWiiExtensionControllerType eExtensionControllerType = (EWiiExtensionControllerType)device->guid.data[15]; - const char *name = NULL; + SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; - switch (eExtensionControllerType) { - case k_eWiiExtensionControllerType_None: - name = "Nintendo Wii Remote"; - break; - case k_eWiiExtensionControllerType_Nunchuk: - name = "Nintendo Wii Remote with Nunchuk"; - break; - case k_eWiiExtensionControllerType_Gamepad: - name = "Nintendo Wii Remote with Classic Controller"; - break; - case k_eWiiExtensionControllerType_WiiUPro: - name = "Nintendo Wii U Pro Controller"; - break; - default: - name = "Nintendo Wii Remote with Unknown Extension"; - break; - } - if (name && (!name || SDL_strcmp(name, device->name) != 0)) { - SDL_free(device->name); - device->name = SDL_strdup(name); - SDL_SetJoystickGUIDCRC(&device->guid, SDL_crc16(0, name, SDL_strlen(name))); + switch (ctx->m_eExtensionControllerType) { + case k_eWiiExtensionControllerType_None: + HIDAPI_SetDeviceName(device, "Nintendo Wii Remote"); + break; + case k_eWiiExtensionControllerType_Nunchuk: + HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Nunchuk"); + break; + case k_eWiiExtensionControllerType_Gamepad: + HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Classic Controller"); + break; + case k_eWiiExtensionControllerType_WiiUPro: + HIDAPI_SetDeviceName(device, "Nintendo Wii U Pro Controller"); + break; + default: + HIDAPI_SetDeviceName(device, "Nintendo Wii Remote with Unknown Extension"); + break; } + device->guid.data[15] = ctx->m_eExtensionControllerType; } static SDL_bool HIDAPI_DriverWii_InitDevice(SDL_HIDAPI_Device *device) { - if (device->vendor_id == USB_VENDOR_NINTENDO) { - EWiiExtensionControllerType eExtensionControllerType; + SDL_DriverWii_Context *ctx; + + ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + device->context = ctx; + + if (device->vendor_id == USB_VENDOR_NINTENDO) { + ctx->m_eExtensionControllerType = ReadExtensionControllerType(device); - eExtensionControllerType = ReadExtensionControllerType(device); - device->guid.data[15] = eExtensionControllerType; UpdateDeviceIdentity(device); } return HIDAPI_JoystickConnected(device, NULL); @@ -766,9 +754,9 @@ HIDAPI_DriverWii_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static void HIDAPI_DriverWii_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) { - SDL_DriverWii_Context *ctx = device->context; + SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; - if (!ctx) { + if (!ctx->joystick) { return; } @@ -780,23 +768,9 @@ HIDAPI_DriverWii_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverWii_Context *ctx; + SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; - ctx = (SDL_DriverWii_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - goto error; - } - ctx->device = device; - device->context = ctx; - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - goto error; - } - - ctx->m_eExtensionControllerType = (EWiiExtensionControllerType)device->guid.data[15]; + ctx->joystick = joystick; InitializeExtension(ctx); @@ -841,21 +815,6 @@ HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) ctx->m_unLastInput = SDL_GetTicks(); return SDL_TRUE; - -error: - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - if (device->context) { - SDL_free(device->context); - device->context = NULL; - } - } - SDL_UnlockMutex(device->dev_lock); - return SDL_FALSE; } static int @@ -1509,16 +1468,16 @@ HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } now = SDL_GetTicks(); while ((size = ReadInput(ctx)) > 0) { - HandleInput(ctx, joystick); - + if (joystick) { + HandleInput(ctx, joystick); + } ctx->m_unLastInput = now; } @@ -1533,36 +1492,38 @@ HIDAPI_DriverWii_UpdateDevice(SDL_HIDAPI_Device *device) size = -1; } - /* These checks aren't needed on the Wii U Pro Controller */ - if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) { + if (joystick) { + /* These checks aren't needed on the Wii U Pro Controller */ + if (ctx->m_eExtensionControllerType != k_eWiiExtensionControllerType_WiiUPro) { - /* Check to see if the Motion Plus extension status has changed */ - if (ctx->m_unNextMotionPlusCheck && - SDL_TICKS_PASSED(now, ctx->m_unNextMotionPlusCheck)) { - CheckMotionPlusConnection(ctx); - if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) { - SchedulePeriodicMotionPlusCheck(ctx); - } else { - ctx->m_unNextMotionPlusCheck = 0; + /* Check to see if the Motion Plus extension status has changed */ + if (ctx->m_unNextMotionPlusCheck && + SDL_TICKS_PASSED(now, ctx->m_unNextMotionPlusCheck)) { + CheckMotionPlusConnection(ctx); + if (NeedsPeriodicMotionPlusCheck(ctx, SDL_FALSE)) { + SchedulePeriodicMotionPlusCheck(ctx); + } else { + ctx->m_unNextMotionPlusCheck = 0; + } } - } - /* Request a status update periodically to make sure our battery value is up to date */ - if (!ctx->m_unLastStatus || - SDL_TICKS_PASSED(now, ctx->m_unLastStatus + STATUS_UPDATE_TIME_MS)) { - Uint8 data[2]; + /* Request a status update periodically to make sure our battery value is up to date */ + if (!ctx->m_unLastStatus || + SDL_TICKS_PASSED(now, ctx->m_unLastStatus + STATUS_UPDATE_TIME_MS)) { + Uint8 data[2]; - data[0] = k_eWiiOutputReportIDs_StatusRequest; - data[1] = ctx->m_bRumbleActive; - WriteOutput(ctx, data, sizeof(data), SDL_FALSE); + data[0] = k_eWiiOutputReportIDs_StatusRequest; + data[1] = ctx->m_bRumbleActive; + WriteOutput(ctx, data, sizeof(data), SDL_FALSE); - ctx->m_unLastStatus = now; + ctx->m_unLastStatus = now; + } } } if (size < 0 || ctx->m_bDisconnected) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -1578,15 +1539,7 @@ HIDAPI_DriverWii_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED, SDL_PlayerLEDHintChanged, ctx); - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -1602,7 +1555,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii = HIDAPI_DriverWii_UnregisterHints, HIDAPI_DriverWii_IsEnabled, HIDAPI_DriverWii_IsSupportedDevice, - HIDAPI_DriverWii_GetDeviceName, HIDAPI_DriverWii_InitDevice, HIDAPI_DriverWii_GetDevicePlayerIndex, HIDAPI_DriverWii_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 5254a16ad..a73071b94 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -40,6 +40,7 @@ typedef struct { SDL_HIDAPI_Device *device; + SDL_Joystick *joystick; int player_index; SDL_bool player_lights; Uint8 last_state[USB_PACKET_LENGTH]; @@ -108,12 +109,6 @@ HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *na #endif } -static const char * -HIDAPI_DriverXbox360_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return NULL; -} - static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on) { const SDL_bool blink = SDL_FALSE; @@ -151,6 +146,17 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c static SDL_bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device) { + SDL_DriverXbox360_Context *ctx; + + ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + ctx->device = device; + + device->context = ctx; + return HIDAPI_JoystickConnected(device, NULL); } @@ -165,7 +171,7 @@ HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystic { SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context; - if (!ctx) { + if (!ctx->joystick) { return; } @@ -177,22 +183,10 @@ HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_Joystic static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_DriverXbox360_Context *ctx; + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context; - ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx)); - if (!ctx) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - ctx->device = device; - - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_SetError("Couldn't open %s", device->path); - SDL_free(ctx); - return SDL_FALSE; - } - device->context = ctx; + ctx->joystick = joystick; + SDL_zeroa(ctx->last_state); /* Initialize player index (needed for setting LEDs) */ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); @@ -343,8 +337,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device) if (device->num_joysticks > 0) { joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { + } else { return SDL_FALSE; } @@ -352,6 +345,10 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device) #ifdef DEBUG_XBOX_PROTOCOL HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size); #endif + if (!joystick) { + continue; + } + if (data[0] == 0x00) { HIDAPI_DriverXbox360_HandleStatePacket(joystick, ctx, data, size); } @@ -359,7 +356,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device) if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -372,17 +369,7 @@ HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED, SDL_PlayerLEDHintChanged, ctx); - SDL_LockMutex(device->dev_lock); - { - if (device->dev) { - SDL_hid_close(device->dev); - device->dev = NULL; - } - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); + ctx->joystick = NULL; } static void @@ -398,7 +385,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 = HIDAPI_DriverXbox360_UnregisterHints, HIDAPI_DriverXbox360_IsEnabled, HIDAPI_DriverXbox360_IsSupportedDevice, - HIDAPI_DriverXbox360_GetDeviceName, HIDAPI_DriverXbox360_InitDevice, HIDAPI_DriverXbox360_GetDevicePlayerIndex, HIDAPI_DriverXbox360_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index c3fd3a010..5869aff49 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -41,7 +41,6 @@ typedef struct { SDL_HIDAPI_Device *device; SDL_bool connected; - SDL_bool opened; int player_index; SDL_bool player_lights; Uint8 last_state[USB_PACKET_LENGTH]; @@ -86,12 +85,6 @@ HIDAPI_DriverXbox360W_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *n return SDL_FALSE; } -static const char * -HIDAPI_DriverXbox360W_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return "Xbox 360 Wireless Controller"; -} - static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on) { const SDL_bool blink = SDL_FALSE; @@ -150,6 +143,8 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) /* Requests controller presence information from the wireless dongle */ const Uint8 init_packet[] = { 0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + HIDAPI_SetDeviceName(device, "Xbox 360 Wireless Controller"); + ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { SDL_OutOfMemory(); @@ -157,12 +152,6 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) } ctx->device = device; - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } device->context = ctx; if (SDL_hid_write(device->dev, init_packet, sizeof(init_packet)) != sizeof(init_packet)) { @@ -200,8 +189,6 @@ HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys SDL_zeroa(ctx->last_state); - ctx->opened = SDL_TRUE; - /* Initialize player index (needed for setting LEDs) */ ctx->player_index = SDL_JoystickGetPlayerIndex(joystick); ctx->player_lights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED, SDL_TRUE); @@ -367,11 +354,9 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device) } } - if (joystick) { - if (size < 0) { - /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); - } + if (size < 0 && device->num_joysticks > 0) { + /* Read error, device is disconnected */ + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } @@ -383,22 +368,11 @@ HIDAPI_DriverXbox360W_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED, SDL_PlayerLEDHintChanged, ctx); - - ctx->opened = SDL_FALSE; } static void HIDAPI_DriverXbox360W_FreeDevice(SDL_HIDAPI_Device *device) { - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W = @@ -409,7 +383,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W = HIDAPI_DriverXbox360W_UnregisterHints, HIDAPI_DriverXbox360W_IsEnabled, HIDAPI_DriverXbox360W_IsSupportedDevice, - HIDAPI_DriverXbox360W_GetDeviceName, HIDAPI_DriverXbox360W_InitDevice, HIDAPI_DriverXbox360W_GetDevicePlayerIndex, HIDAPI_DriverXbox360W_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 17a30a072..987fb6987 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -106,7 +106,6 @@ typedef struct { Uint32 start_time; Uint8 sequence; Uint32 send_time; - Uint8 last_state[USB_PACKET_LENGTH]; SDL_bool has_guide_packet; SDL_bool has_color_led; SDL_bool has_paddles; @@ -116,6 +115,7 @@ typedef struct { Uint8 high_frequency_rumble; Uint8 left_trigger_rumble; Uint8 right_trigger_rumble; + Uint8 last_state[USB_PACKET_LENGTH]; } SDL_DriverXboxOne_Context; static SDL_bool @@ -306,34 +306,8 @@ HIDAPI_DriverXboxOne_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *na return (type == SDL_CONTROLLER_TYPE_XBOXONE) ? SDL_TRUE : SDL_FALSE; } -static const char * -HIDAPI_DriverXboxOne_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - return NULL; -} - static SDL_bool HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device) -{ - return HIDAPI_JoystickConnected(device, NULL); -} - -static int -HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) -{ - return -1; -} - -static void -HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) -{ -} - -static SDL_bool HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); -static void HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); - -static SDL_bool -HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { SDL_DriverXboxOne_Context *ctx; @@ -343,12 +317,6 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst return SDL_FALSE; } - device->dev = SDL_hid_open_path(device->path, 0); - if (!device->dev) { - SDL_free(ctx); - SDL_SetError("Couldn't open %s", device->path); - return SDL_FALSE; - } device->context = ctx; ctx->vendor_id = device->vendor_id; @@ -372,6 +340,31 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst SDL_Log("Controller version: %d (0x%.4x)\n", device->version, device->version); #endif + return HIDAPI_JoystickConnected(device, NULL); +} + +static int +HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + +static SDL_bool +HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context; + + ctx->low_frequency_rumble = 0; + ctx->high_frequency_rumble = 0; + ctx->left_trigger_rumble = 0; + ctx->right_trigger_rumble = 0; + SDL_zeroa(ctx->last_state); + /* Initialize the joystick capabilities */ joystick->nbuttons = 15; if (ctx->has_share_button) { @@ -975,12 +968,19 @@ HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device, SDL_DriverXboxOn } static SDL_bool -HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device) { SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context; + SDL_Joystick *joystick = NULL; Uint8 data[USB_PACKET_LENGTH]; int size; + if (device->num_joysticks > 0) { + joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); + } else { + return SDL_FALSE; + } + while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { #ifdef DEBUG_XBOX_PROTOCOL HIDAPI_DumpPacket("Xbox One packet: size = %d", data, size); @@ -988,6 +988,9 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy if (ctx->bluetooth) { switch (data[0]) { case 0x01: + if (!joystick) { + break; + } if (size >= 16) { HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick, ctx, data, size); } else { @@ -997,9 +1000,15 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy } break; case 0x02: + if (!joystick) { + break; + } HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, ctx, data, size); break; case 0x04: + if (!joystick) { + break; + } HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, ctx, data, size); break; default: @@ -1045,6 +1054,10 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy break; case 0x03: /* Controller status update */ + if (!joystick) { + /* We actually want to handle this packet any time it arrives */ + /*break;*/ + } HIDAPI_DriverXboxOne_HandleStatusPacket(joystick, ctx, data, size); break; case 0x04: @@ -1054,6 +1067,9 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy /* Unknown chatty controller information, sent by both sides */ break; case 0x07: + if (!joystick) { + break; + } HIDAPI_DriverXboxOne_HandleModePacket(joystick, ctx, data, size); break; case 0x1E: @@ -1066,6 +1082,9 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy The controller sends that in response to this request: 0x1E 0x30 0x07 0x01 0x04 */ + if (!joystick) { + break; + } #ifdef SET_SERIAL_AFTER_OPEN if (size == 20 && data[3] == 0x10) { HIDAPI_DriverXboxOne_HandleSerialIDPacket(joystick, ctx, data, size); @@ -1082,6 +1101,9 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy #endif break; } + if (!joystick) { + break; + } HIDAPI_DriverXboxOne_HandleStatePacket(joystick, ctx, data, size); break; default: @@ -1111,37 +1133,14 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy if (size < 0) { /* Read error, device is disconnected */ - HIDAPI_JoystickDisconnected(device, joystick->instance_id); + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); } return (size >= 0); } -static SDL_bool -HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device) -{ - SDL_Joystick *joystick = NULL; - - if (device->num_joysticks > 0) { - joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); - } - if (!joystick) { - return SDL_FALSE; - } - return HIDAPI_DriverXboxOne_UpdateJoystick(device, joystick); -} - static void HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - SDL_LockMutex(device->dev_lock); - { - SDL_hid_close(device->dev); - device->dev = NULL; - - SDL_free(device->context); - device->context = NULL; - } - SDL_UnlockMutex(device->dev_lock); } static void @@ -1157,7 +1156,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne = HIDAPI_DriverXboxOne_UnregisterHints, HIDAPI_DriverXboxOne_IsEnabled, HIDAPI_DriverXboxOne_IsSupportedDevice, - HIDAPI_DriverXboxOne_GetDeviceName, HIDAPI_DriverXboxOne_InitDevice, HIDAPI_DriverXboxOne_GetDevicePlayerIndex, HIDAPI_DriverXboxOne_SetDevicePlayerIndex, diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 57764de2f..0a3873a71 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -314,6 +314,20 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device) device->driver->FreeDevice(device); device->driver = NULL; + + SDL_LockMutex(device->dev_lock); + { + if (device->dev) { + SDL_hid_close(device->dev); + device->dev = NULL; + } + + if (device->context) { + SDL_free(device->context); + device->context = NULL; + } + } + SDL_UnlockMutex(device->dev_lock); } static void @@ -344,18 +358,27 @@ HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device) return; /* Already setup */ } - device->driver = HIDAPI_GetDeviceDriver(device); - if (device->driver) { - const char *name = device->driver->GetDeviceName(device->name, device->vendor_id, device->product_id); - if (name && name != device->name) { - SDL_free(device->name); - device->name = SDL_strdup(name); - } + /* Make sure we can open the device and leave it open for the driver */ + device->dev = SDL_hid_open_path(device->path, 0); + if (!device->dev) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_SetupDeviceDriver() couldn't open %s: %s\n", + device->path, SDL_GetError()); + return; } + SDL_hid_set_nonblocking(device->dev, 1); + + device->driver = HIDAPI_GetDeviceDriver(device); /* Initialize the device, which may cause a connected event */ if (device->driver && !device->driver->InitDevice(device)) { - device->driver = NULL; + HIDAPI_CleanupDeviceDriver(device); + } + + if (!device->driver && device->dev) { + /* No driver claimed this device, go ahead and close it */ + SDL_hid_close(device->dev); + device->dev = NULL; } } @@ -481,6 +504,32 @@ HIDAPI_JoystickInstanceIsUnique(SDL_HIDAPI_Device *device, SDL_JoystickID joysti return SDL_TRUE; } +void +HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name) +{ + if (name && *name && SDL_strcmp(name, device->name) != 0) { + SDL_free(device->name); + device->name = SDL_strdup(name); + SDL_SetJoystickGUIDCRC(&device->guid, SDL_crc16(0, name, SDL_strlen(name))); + } +} + +void +HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id) +{ + /* Don't set the device product ID directly, or we'll constantly re-enumerate this device */ + SDL_SetJoystickGUIDProduct(&device->guid, product_id); +} + +void +HIDAPI_SetDeviceSerial(SDL_HIDAPI_Device *device, const char *serial) +{ + if (serial && *serial && (!device->serial || SDL_strcmp(serial, device->serial) != 0)) { + SDL_free(device->serial); + device->serial = SDL_strdup(serial); + } +} + SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID) { @@ -1102,6 +1151,13 @@ HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) } hwdata->device = device; + /* Process any pending reports before opening the device */ + SDL_LockMutex(device->dev_lock); + device->updating = SDL_TRUE; + device->driver->UpdateDevice(device); + device->updating = SDL_FALSE; + SDL_UnlockMutex(device->dev_lock); + if (!device->driver->OpenJoystick(device, joystick)) { /* The open failed, mark this device as disconnected and update devices */ HIDAPI_JoystickDisconnected(device, joystickID); diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 58c35914a..3b574d657 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -103,7 +103,6 @@ typedef struct _SDL_HIDAPI_DeviceDriver void (*UnregisterHints)(SDL_HintCallback callback, void *userdata); SDL_bool (*IsEnabled)(void); SDL_bool (*IsSupportedDevice)(SDL_HIDAPI_Device *device, 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); - const char *(*GetDeviceName)(const char *name, Uint16 vendor_id, Uint16 product_id); SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device); int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id); void (*SetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index); @@ -146,6 +145,9 @@ extern SDL_bool HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type); extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name); extern void HIDAPI_UpdateDevices(void); +extern void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name); +extern void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id); +extern void HIDAPI_SetDeviceSerial(SDL_HIDAPI_Device *device, const char *serial); extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID); extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID);