21 #include "../../SDL_internal.h" 23 #ifdef SDL_JOYSTICK_HIDAPI 31 #include "../SDL_sysjoystick.h" 35 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE 37 #define USB_PACKET_LENGTH 64 43 static const Uint8 xboxone_fw2015_init[] = {
44 0x05, 0x20, 0x00, 0x01, 0x00
52 static const Uint8 xboxone_hori_init[] = {
53 0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
54 0x00, 0x00, 0x00, 0x80, 0x00
62 static const Uint8 xboxone_pdp_init1[] = {
63 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
71 static const Uint8 xboxone_pdp_init2[] = {
72 0x06, 0x20, 0x00, 0x02, 0x01, 0x00
79 static const Uint8 xboxone_rumblebegin_init[] = {
80 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
81 0x1D, 0x1D, 0xFF, 0x00, 0x00
90 static const Uint8 xboxone_rumbleend_init[] = {
91 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00
106 } SDL_DriverXboxOne_InitPacket;
108 static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
109 { 0x0e6f, 0x0165, xboxone_hori_init,
sizeof(xboxone_hori_init) },
110 { 0x0f0d, 0x0067, xboxone_hori_init,
sizeof(xboxone_hori_init) },
111 { 0x0000, 0x0000, xboxone_fw2015_init,
sizeof(xboxone_fw2015_init) },
112 { 0x0e6f, 0x0246, xboxone_pdp_init1,
sizeof(xboxone_pdp_init1) },
113 { 0x0e6f, 0x0246, xboxone_pdp_init2,
sizeof(xboxone_pdp_init2) },
114 { 0x0e6f, 0x02ab, xboxone_pdp_init1,
sizeof(xboxone_pdp_init1) },
115 { 0x0e6f, 0x02ab, xboxone_pdp_init2,
sizeof(xboxone_pdp_init2) },
116 { 0x0e6f, 0x02a4, xboxone_pdp_init1,
sizeof(xboxone_pdp_init1) },
117 { 0x0e6f, 0x02a4, xboxone_pdp_init2,
sizeof(xboxone_pdp_init2) },
118 { 0x24c6, 0x541a, xboxone_rumblebegin_init,
sizeof(xboxone_rumblebegin_init) },
119 { 0x24c6, 0x542a, xboxone_rumblebegin_init,
sizeof(xboxone_rumblebegin_init) },
120 { 0x24c6, 0x543a, xboxone_rumblebegin_init,
sizeof(xboxone_rumblebegin_init) },
121 { 0x24c6, 0x541a, xboxone_rumbleend_init,
sizeof(xboxone_rumbleend_init) },
122 { 0x24c6, 0x542a, xboxone_rumbleend_init,
sizeof(xboxone_rumbleend_init) },
123 { 0x24c6, 0x543a, xboxone_rumbleend_init,
sizeof(xboxone_rumbleend_init) },
128 Uint8 last_state[USB_PACKET_LENGTH];
130 } SDL_DriverXboxOne_Context;
134 HIDAPI_DriverXboxOne_IsSupportedDevice(
Uint16 vendor_id,
Uint16 product_id,
Uint16 version,
int interface_number)
140 HIDAPI_DriverXboxOne_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
146 HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev,
Uint16 vendor_id,
Uint16 product_id,
void **
context)
148 SDL_DriverXboxOne_Context *
ctx;
150 Uint8 init_packet[USB_PACKET_LENGTH];
152 ctx = (SDL_DriverXboxOne_Context *)
SDL_calloc(1,
sizeof(*ctx));
161 const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[
i];
162 if (!packet->vendor_id || (vendor_id == packet->vendor_id && product_id == packet->product_id)) {
163 SDL_memcpy(init_packet, packet->data, packet->size);
164 init_packet[2] = ctx->sequence++;
165 if (
hid_write(dev, init_packet, packet->size) != packet->size) {
166 SDL_SetError(
"Couldn't write Xbox One initialization packet");
182 HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev,
void *context,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble,
Uint32 duration_ms)
184 SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
185 Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
193 rumble_packet[2] = ctx->sequence++;
194 rumble_packet[8] = (low_frequency_rumble >> 9);
195 rumble_packet[9] = (high_frequency_rumble >> 9);
197 if (
hid_write(dev, rumble_packet,
sizeof(rumble_packet)) !=
sizeof(rumble_packet)) {
201 if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
204 ctx->rumble_expiration = 0;
210 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx,
Uint8 *
data,
int size)
214 if (ctx->last_state[4] != data[4]) {
223 if (ctx->last_state[5] != data[5]) {
234 axis = ((int)*(
Sint16*)(&data[6]) * 64) - 32768;
239 axis = ((int)*(
Sint16*)(&data[8]) * 64) - 32768;
244 axis = *(
Sint16*)(&data[10]);
246 axis = *(
Sint16*)(&data[12]);
248 axis = *(
Sint16*)(&data[14]);
250 axis = *(
Sint16*)(&data[16]);
257 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx,
Uint8 *data,
int size)
259 if (data[1] == 0x30) {
261 const Uint8 seqnum = data[2];
262 const Uint8 ack[] = { 0x01, 0x20, seqnum, 0x09, 0x00, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
270 HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev,
void *context)
272 SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
273 Uint8 data[USB_PACKET_LENGTH];
279 HIDAPI_DriverXboxOne_HandleStatePacket(joystick, dev, ctx, data, size);
282 HIDAPI_DriverXboxOne_HandleModePacket(joystick, dev, ctx, data, size);
285 #ifdef DEBUG_JOYSTICK 286 SDL_Log(
"Unknown Xbox One packet: 0x%.2x\n", data[0]);
292 if (ctx->rumble_expiration) {
295 HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0);
303 HIDAPI_DriverXboxOne_Quit(SDL_Joystick *joystick, hid_device *dev,
void *context)
312 HIDAPI_DriverXboxOne_IsSupportedDevice,
313 HIDAPI_DriverXboxOne_GetDeviceName,
314 HIDAPI_DriverXboxOne_Init,
315 HIDAPI_DriverXboxOne_Rumble,
316 HIDAPI_DriverXboxOne_Update,
317 HIDAPI_DriverXboxOne_Quit
static screen_context_t context
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor, Uint16 product)
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
const char * HIDAPI_XboxControllerName(Uint16 vendor_id, Uint16 product_id)
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX
A variable controlling whether the HIDAPI driver for XBox controllers should be used.
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define SDL_OutOfMemory()
#define SDL_arraysize(array)
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.