From 517be8082200da7a3e7ab5683343c66f30ec0d8f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 25 Nov 2020 16:05:19 -0800 Subject: [PATCH] Implemented battery status for Bluetooth Xbox One controllers Also switched the rumble loop count to 0xEB (one hour) to match Windows driver --- src/joystick/hidapi/SDL_hidapi_xboxone.c | 36 ++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index a5d7bcdaa..c40210f12 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -376,7 +376,10 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst joystick->nbuttons += 4; } joystick->naxes = SDL_CONTROLLER_AXIS_MAX; - joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; + + if (!ctx->bluetooth) { + joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; + } return SDL_TRUE; } @@ -387,7 +390,7 @@ HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device) SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context; if (ctx->bluetooth) { - Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 }; + Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB }; rumble_packet[2] = ctx->left_trigger_rumble; rumble_packet[3] = ctx->right_trigger_rumble; @@ -398,7 +401,7 @@ HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device) return SDL_SetError("Couldn't send rumble packet"); } } else { - Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF }; + Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB }; rumble_packet[6] = ctx->left_trigger_rumble; rumble_packet[7] = ctx->right_trigger_rumble; @@ -853,6 +856,30 @@ HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_devi SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED); } +static void +HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size) +{ + Uint8 flags = data[1]; + SDL_bool on_usb = (((flags & 0x0C) >> 2) == 0); + + if (on_usb) { + /* Does this ever happen? */ + SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED); + } else { + switch ((flags & 0x03)) { + case 0: + SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW); + break; + case 1: + SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM); + break; + default: /* 2, 3 */ + SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL); + break; + } + } +} + #ifdef SET_SERIAL_AFTER_OPEN static void HIDAPI_DriverXboxOne_HandleSerialIDPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size) @@ -951,6 +978,9 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy case 0x02: HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size); break; + case 0x04: + HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, device->dev, ctx, data, size); + break; default: #ifdef DEBUG_JOYSTICK SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);