src/joystick/hidapi/SDL_hidapi_xbox360.c
changeset 12641 64597a7e8771
parent 12503 806492103856
child 12769 096f2f3c4bdc
equal deleted inserted replaced
12640:b708d2c3fe08 12641:64597a7e8771
    52 
    52 
    53 #define USB_PACKET_LENGTH   64
    53 #define USB_PACKET_LENGTH   64
    54 
    54 
    55 
    55 
    56 typedef struct {
    56 typedef struct {
       
    57     SDL_JoystickID joystickID;
    57     Uint8 last_state[USB_PACKET_LENGTH];
    58     Uint8 last_state[USB_PACKET_LENGTH];
    58     Uint32 rumble_expiration;
    59     Uint32 rumble_expiration;
    59 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
    60 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
    60     SDL_bool xinput_enabled;
    61     SDL_bool xinput_enabled;
    61     Uint8 xinput_slot;
    62     Uint8 xinput_slot;
   275     }
   276     }
   276     return SDL_TRUE;
   277     return SDL_TRUE;
   277 }
   278 }
   278 
   279 
   279 static SDL_bool
   280 static SDL_bool
   280 HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
   281 HIDAPI_DriverXbox360_InitDriver(SDL_HIDAPI_DriverData *context, Uint16 vendor_id, Uint16 product_id, int *num_joysticks)
   281 {
   282 {
   282     SDL_DriverXbox360_Context *ctx;
   283     SDL_DriverXbox360_Context *ctx;
   283 
   284 
   284     ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
   285     ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
   285     if (!ctx) {
   286     if (!ctx) {
   294     ctx->xinput_slot = XUSER_INDEX_ANY;
   295     ctx->xinput_slot = XUSER_INDEX_ANY;
   295 #endif
   296 #endif
   296 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   297 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   297     HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
   298     HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
   298 #endif
   299 #endif
   299     *context = ctx;
   300     context->context = ctx;
   300 
   301 
       
   302     ctx->joystickID = SDL_GetNextJoystickInstanceID();
       
   303     *num_joysticks += 1;
       
   304     SDL_PrivateJoystickAdded(ctx->joystickID);
       
   305 
       
   306     return SDL_TRUE;
       
   307 }
       
   308 
       
   309 static SDL_bool
       
   310 HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick)
       
   311 {
   301     /* Set the controller LED */
   312     /* Set the controller LED */
   302     SetSlotLED(dev, (joystick->instance_id % 4));
   313     SetSlotLED(context->device, (joystick->instance_id % 4));
   303 
   314 
   304     /* Initialize the joystick capabilities */
   315     /* Initialize the joystick capabilities */
   305     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   316     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   306     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   317     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   307     joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
   318     joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
   308 
   319 
   309     return SDL_TRUE;
   320     return SDL_TRUE;
   310 }
   321 }
   311 
   322 
   312 static int
   323 static int
   313 HIDAPI_DriverXbox360_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   324 HIDAPI_DriverXbox360_NumJoysticks(SDL_HIDAPI_DriverData *context)
   314 {
   325 {
   315     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
   326     return 1;
       
   327 }
       
   328 
       
   329 static SDL_JoystickID
       
   330 HIDAPI_DriverXbox360_InstanceIDForIndex(SDL_HIDAPI_DriverData *context, int index)
       
   331 {
       
   332     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
       
   333     return ctx->joystickID;
       
   334 }
       
   335 
       
   336 static int
       
   337 HIDAPI_DriverXbox360_Rumble(SDL_HIDAPI_DriverData *context, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
       
   338 {
       
   339     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
   316 
   340 
   317 #ifdef __WIN32__
   341 #ifdef __WIN32__
   318     SDL_bool rumbled = SDL_FALSE;
   342     SDL_bool rumbled = SDL_FALSE;
   319 
   343 
   320 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   344 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   363 
   387 
   364     rumble_packet[3] = (low_frequency_rumble >> 8);
   388     rumble_packet[3] = (low_frequency_rumble >> 8);
   365     rumble_packet[4] = (high_frequency_rumble >> 8);
   389     rumble_packet[4] = (high_frequency_rumble >> 8);
   366 #endif
   390 #endif
   367 
   391 
   368     if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
   392     if (hid_write(context->device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
   369         return SDL_SetError("Couldn't send rumble packet");
   393         return SDL_SetError("Couldn't send rumble packet");
   370     }
   394     }
   371 #endif /* __WIN32__ */
   395 #endif /* __WIN32__ */
   372 
   396 
   373     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   397     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   703     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   727     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   704 }
   728 }
   705 #endif /* __MACOSX__ */
   729 #endif /* __MACOSX__ */
   706 
   730 
   707 static SDL_bool
   731 static SDL_bool
   708 HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
   732 HIDAPI_DriverXbox360_UpdateDriver(SDL_HIDAPI_DriverData *context, int *num_joysticks)
   709 {
   733 {
   710     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
   734     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
       
   735     SDL_Joystick *joystick = SDL_JoystickFromInstanceID(ctx->joystickID);
   711     Uint8 data[USB_PACKET_LENGTH];
   736     Uint8 data[USB_PACKET_LENGTH];
   712     int size;
   737     int size;
   713 
   738 
   714     while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
   739     if (joystick == NULL) {
       
   740         return SDL_TRUE; /* Nothing to do right now! */
       
   741     }
       
   742 
       
   743     while ((size = hid_read_timeout(context->device, data, sizeof(data), 0)) > 0) {
   715 #ifdef __WIN32__
   744 #ifdef __WIN32__
   716         HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
   745         HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
   717 #else
   746 #else
   718         switch (data[0]) {
   747         switch (data[0]) {
   719         case 0x00:
   748         case 0x00:
   720             HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
   749             HIDAPI_DriverXbox360_HandleStatePacket(joystick, context->device, ctx, data, size);
   721             break;
   750             break;
   722 #ifdef __MACOSX__
   751 #ifdef __MACOSX__
   723         case 0x01:
   752         case 0x01:
   724             HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, dev, ctx, data, size);
   753             HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, context->device, ctx, data, size);
   725             break;
   754             break;
   726         case 0x02:
   755         case 0x02:
   727             HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, dev, ctx, data, size);
   756             HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, context->device, ctx, data, size);
   728             break;
   757             break;
   729 #endif
   758 #endif
   730         default:
   759         default:
   731 #ifdef DEBUG_JOYSTICK
   760 #ifdef DEBUG_JOYSTICK
   732             SDL_Log("Unknown Xbox 360 packet, size = %d\n", size);
   761             SDL_Log("Unknown Xbox 360 packet, size = %d\n", size);
   740     }
   769     }
   741 
   770 
   742     if (ctx->rumble_expiration) {
   771     if (ctx->rumble_expiration) {
   743         Uint32 now = SDL_GetTicks();
   772         Uint32 now = SDL_GetTicks();
   744         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   773         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   745             HIDAPI_DriverXbox360_Rumble(joystick, dev, context, 0, 0, 0);
   774             HIDAPI_DriverXbox360_Rumble(context, joystick, 0, 0, 0);
   746         }
   775         }
   747     }
   776     }
   748 
   777 
   749     return (size >= 0);
   778     return (size >= 0);
   750 }
   779 }
   751 
   780 
   752 static void
   781 static void
   753 HIDAPI_DriverXbox360_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
   782 HIDAPI_DriverXbox360_QuitDriver(SDL_HIDAPI_DriverData *context, SDL_bool send_event, int *num_joysticks)
   754 {
   783 {
   755 #if defined(SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT) || defined(SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT)
   784     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context->context;
   756     SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
       
   757 #endif
       
   758 
   785 
   759 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
   786 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
   760     if (ctx->xinput_enabled) {
   787     if (ctx->xinput_enabled) {
   761         HIDAPI_DriverXbox360_MarkXInputSlotFree(ctx->xinput_slot);
   788         HIDAPI_DriverXbox360_MarkXInputSlotFree(ctx->xinput_slot);
   762         WIN_UnloadXInputDLL();
   789         WIN_UnloadXInputDLL();
   763     }
   790     }
   764 #endif
   791 #endif
   765 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   792 #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT
   766     HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
   793     HIDAPI_DriverXbox360_InitWindowsGamingInput(ctx);
   767 #endif
   794 #endif
   768     SDL_free(context);
   795     *num_joysticks -= 1;
       
   796     if (send_event) {
       
   797         SDL_PrivateJoystickRemoved(ctx->joystickID);
       
   798     }
       
   799     SDL_free(context->context);
   769 }
   800 }
   770 
   801 
   771 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
   802 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
   772 {
   803 {
   773     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   804     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   774     SDL_TRUE,
   805     SDL_TRUE,
   775     HIDAPI_DriverXbox360_IsSupportedDevice,
   806     HIDAPI_DriverXbox360_IsSupportedDevice,
   776     HIDAPI_DriverXbox360_GetDeviceName,
   807     HIDAPI_DriverXbox360_GetDeviceName,
   777     HIDAPI_DriverXbox360_Init,
   808     HIDAPI_DriverXbox360_InitDriver,
   778     HIDAPI_DriverXbox360_Rumble,
   809     HIDAPI_DriverXbox360_QuitDriver,
   779     HIDAPI_DriverXbox360_Update,
   810     HIDAPI_DriverXbox360_UpdateDriver,
   780     HIDAPI_DriverXbox360_Quit
   811     HIDAPI_DriverXbox360_NumJoysticks,
       
   812     HIDAPI_DriverXbox360_InstanceIDForIndex,
       
   813     HIDAPI_DriverXbox360_OpenJoystick,
       
   814     HIDAPI_DriverXbox360_Rumble
   781 };
   815 };
   782 
   816 
   783 #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */
   817 #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */
   784 
   818 
   785 #endif /* SDL_JOYSTICK_HIDAPI */
   819 #endif /* SDL_JOYSTICK_HIDAPI */