src/joystick/hidapi/SDL_hidapi_xboxone.c
changeset 13354 8c22865bd138
parent 13348 448528dc13da
child 13364 e0633ed9c498
equal deleted inserted replaced
13353:381ddcd3957c 13354:8c22865bd138
   253 {
   253 {
   254     return NULL;
   254     return NULL;
   255 }
   255 }
   256 
   256 
   257 static SDL_bool
   257 static SDL_bool
   258 HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
   258 HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
       
   259 {
       
   260     return HIDAPI_JoystickConnected(device, NULL);
       
   261 }
       
   262 
       
   263 static SDL_bool
       
   264 HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   259 {
   265 {
   260     SDL_DriverXboxOne_Context *ctx;
   266     SDL_DriverXboxOne_Context *ctx;
   261 
   267 
   262     ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
   268     ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
   263     if (!ctx) {
   269     if (!ctx) {
   264         SDL_OutOfMemory();
   270         SDL_OutOfMemory();
   265         return SDL_FALSE;
   271         return SDL_FALSE;
   266     }
   272     }
   267     *context = ctx;
   273 
   268 
   274     device->dev = hid_open_path(device->path, 0);
   269     ctx->vendor_id = vendor_id;
   275     if (!device->dev) {
   270     ctx->product_id = product_id;
   276         SDL_free(ctx);
       
   277         SDL_SetError("Couldn't open %s", device->path);
       
   278         return SDL_FALSE;
       
   279     }
       
   280     device->context = ctx;
       
   281 
       
   282     ctx->vendor_id = device->vendor_id;
       
   283     ctx->product_id = device->product_id;
   271     ctx->start_time = SDL_GetTicks();
   284     ctx->start_time = SDL_GetTicks();
   272 
   285 
   273     /* Initialize the joystick capabilities */
   286     /* Initialize the joystick capabilities */
   274     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   287     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   275     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   288     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   277 
   290 
   278     return SDL_TRUE;
   291     return SDL_TRUE;
   279 }
   292 }
   280 
   293 
   281 static int
   294 static int
   282 HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   295 HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   283 {
   296 {
   284     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
   297     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
   285     Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
   298     Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
   286 
   299 
   287     if (!ctx->initialized) {
   300     if (!ctx->initialized) {
   288         return 0;
   301         return 0;
   289     }
   302     }
   291     /* Magnitude is 1..100 so scale the 16-bit input here */
   304     /* Magnitude is 1..100 so scale the 16-bit input here */
   292     rumble_packet[2] = ctx->sequence++;
   305     rumble_packet[2] = ctx->sequence++;
   293     rumble_packet[8] = low_frequency_rumble / 655;
   306     rumble_packet[8] = low_frequency_rumble / 655;
   294     rumble_packet[9] = high_frequency_rumble / 655;
   307     rumble_packet[9] = high_frequency_rumble / 655;
   295 
   308 
   296     if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
   309     if (hid_write(device->dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
   297         return SDL_SetError("Couldn't send rumble packet");
   310         return SDL_SetError("Couldn't send rumble packet");
   298     }
   311     }
   299 
   312 
   300     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   313     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   301         ctx->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
   314         ctx->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
   364 
   377 
   365     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   378     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   366 }
   379 }
   367 
   380 
   368 static SDL_bool
   381 static SDL_bool
   369 HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
   382 HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
   370 {
   383 {
   371     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
   384     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
       
   385     SDL_Joystick *joystick = NULL;
   372     Uint8 data[USB_PACKET_LENGTH];
   386     Uint8 data[USB_PACKET_LENGTH];
   373     int size;
   387     int size;
   374 
   388 
       
   389     if (device->num_joysticks > 0) {
       
   390         joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
       
   391     }
       
   392     if (!joystick) {
       
   393         return SDL_FALSE;
       
   394     }
       
   395 
   375     if (!ctx->initialized) {
   396     if (!ctx->initialized) {
   376         if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
   397         if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
   377             if (!SendControllerInit(dev, ctx)) {
   398             if (!SendControllerInit(device->dev, ctx)) {
       
   399                 HIDAPI_JoystickDisconnected(device, joystick->instance_id);
   378                 return SDL_FALSE;
   400                 return SDL_FALSE;
   379             }
   401             }
   380             ctx->initialized = SDL_TRUE;
   402             ctx->initialized = SDL_TRUE;
   381         }
   403         }
   382     }
   404     }
   383 
   405 
   384     while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
   406     while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
   385 #ifdef DEBUG_XBOX_PROTOCOL
   407 #ifdef DEBUG_XBOX_PROTOCOL
   386         SDL_Log("Xbox One packet: size = %d\n"
   408         SDL_Log("Xbox One packet: size = %d\n"
   387                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   409                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   388                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   410                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   389                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
   411                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
   392                     data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
   414                     data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
   393                     data[16], data[17], data[18], data[19]);
   415                     data[16], data[17], data[18], data[19]);
   394 #endif
   416 #endif
   395         switch (data[0]) {
   417         switch (data[0]) {
   396         case 0x20:
   418         case 0x20:
   397             HIDAPI_DriverXboxOne_HandleStatePacket(joystick, dev, ctx, data, size);
   419             HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
   398             break;
   420             break;
   399         case 0x07:
   421         case 0x07:
   400             HIDAPI_DriverXboxOne_HandleModePacket(joystick, dev, ctx, data, size);
   422             HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
   401             break;
   423             break;
   402         default:
   424         default:
   403 #ifdef DEBUG_JOYSTICK
   425 #ifdef DEBUG_JOYSTICK
   404             SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
   426             SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
   405 #endif
   427 #endif
   408     }
   430     }
   409 
   431 
   410     if (ctx->rumble_expiration) {
   432     if (ctx->rumble_expiration) {
   411         Uint32 now = SDL_GetTicks();
   433         Uint32 now = SDL_GetTicks();
   412         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   434         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   413             HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0);
   435             HIDAPI_DriverXboxOne_RumbleJoystick(device, joystick, 0, 0, 0);
   414         }
   436         }
   415     }
   437     }
   416 
   438 
       
   439     if (size < 0) {
       
   440         /* Read error, device is disconnected */
       
   441         HIDAPI_JoystickDisconnected(device, joystick->instance_id);
       
   442     }
   417     return (size >= 0);
   443     return (size >= 0);
   418 }
   444 }
   419 
   445 
   420 static void
   446 static void
   421 HIDAPI_DriverXboxOne_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
   447 HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   422 {
   448 {
   423     SDL_free(context);
   449     hid_close(device->dev);
       
   450     device->dev = NULL;
       
   451 
       
   452     SDL_free(device->context);
       
   453     device->context = NULL;
       
   454 }
       
   455 
       
   456 static void
       
   457 HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device *device)
       
   458 {
   424 }
   459 }
   425 
   460 
   426 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
   461 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
   427 {
   462 {
   428     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   463     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   429     SDL_TRUE,
   464     SDL_TRUE,
   430     HIDAPI_DriverXboxOne_IsSupportedDevice,
   465     HIDAPI_DriverXboxOne_IsSupportedDevice,
   431     HIDAPI_DriverXboxOne_GetDeviceName,
   466     HIDAPI_DriverXboxOne_GetDeviceName,
   432     HIDAPI_DriverXboxOne_Init,
   467     HIDAPI_DriverXboxOne_InitDevice,
   433     HIDAPI_DriverXboxOne_Rumble,
   468     HIDAPI_DriverXboxOne_UpdateDevice,
   434     HIDAPI_DriverXboxOne_Update,
   469     HIDAPI_DriverXboxOne_OpenJoystick,
   435     HIDAPI_DriverXboxOne_Quit
   470     HIDAPI_DriverXboxOne_RumbleJoystick,
       
   471     HIDAPI_DriverXboxOne_CloseJoystick,
       
   472     HIDAPI_DriverXboxOne_FreeDevice
   436 };
   473 };
   437 
   474 
   438 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
   475 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
   439 
   476 
   440 #endif /* SDL_JOYSTICK_HIDAPI */
   477 #endif /* SDL_JOYSTICK_HIDAPI */