SDL_hidapi_shield.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #ifdef SDL_JOYSTICK_HIDAPI
  20. #include "SDL_events.h"
  21. #include "SDL_timer.h"
  22. #include "SDL_joystick.h"
  23. #include "SDL_gamecontroller.h"
  24. #include "../SDL_sysjoystick.h"
  25. #include "SDL_hidapijoystick_c.h"
  26. #include "SDL_hidapi_rumble.h"
  27. #ifdef SDL_JOYSTICK_HIDAPI_SHIELD
  28. /* Define this if you want to log all packets from the controller */
  29. /*#define DEBUG_SHIELD_PROTOCOL*/
  30. #define CMD_BATTERY_STATE 0x07
  31. #define CMD_RUMBLE 0x39
  32. #define CMD_CHARGE_STATE 0x3A
  33. /* Milliseconds between polls of battery state */
  34. #define BATTERY_POLL_INTERVAL_MS 60000
  35. /* Milliseconds between retransmission of rumble to keep motors running */
  36. #define RUMBLE_REFRESH_INTERVAL_MS 500
  37. /* Reports that are too small are dropped over Bluetooth */
  38. #define HID_REPORT_SIZE 33
  39. typedef enum {
  40. k_ShieldReportIdControllerState = 0x01,
  41. k_ShieldReportIdCommandResponse = 0x03,
  42. k_ShieldReportIdCommandRequest = 0x04,
  43. } EShieldReportId;
  44. /* This same report structure is used for both requests and responses */
  45. typedef struct {
  46. Uint8 report_id;
  47. Uint8 cmd;
  48. Uint8 seq_num;
  49. Uint8 payload[HID_REPORT_SIZE - 3];
  50. } ShieldCommandReport_t;
  51. SDL_COMPILE_TIME_ASSERT(ShieldCommandReport_t, sizeof(ShieldCommandReport_t) == HID_REPORT_SIZE);
  52. typedef struct {
  53. Uint8 seq_num;
  54. SDL_JoystickPowerLevel battery_level;
  55. SDL_bool charging;
  56. Uint32 last_battery_query_time;
  57. SDL_bool rumble_report_pending;
  58. SDL_bool rumble_update_pending;
  59. Uint8 left_motor_amplitude;
  60. Uint8 right_motor_amplitude;
  61. Uint32 last_rumble_time;
  62. Uint8 last_state[USB_PACKET_LENGTH];
  63. } SDL_DriverShield_Context;
  64. static void
  65. HIDAPI_DriverShield_RegisterHints(SDL_HintCallback callback, void *userdata)
  66. {
  67. SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SHIELD, callback, userdata);
  68. }
  69. static void
  70. HIDAPI_DriverShield_UnregisterHints(SDL_HintCallback callback, void *userdata)
  71. {
  72. SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SHIELD, callback, userdata);
  73. }
  74. static SDL_bool
  75. HIDAPI_DriverShield_IsEnabled(void)
  76. {
  77. return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SHIELD,
  78. SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
  79. SDL_HIDAPI_DEFAULT));
  80. }
  81. static SDL_bool
  82. HIDAPI_DriverShield_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)
  83. {
  84. return (type == SDL_CONTROLLER_TYPE_NVIDIA_SHIELD) ? SDL_TRUE : SDL_FALSE;
  85. }
  86. static SDL_bool
  87. HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
  88. {
  89. SDL_DriverShield_Context *ctx;
  90. ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx));
  91. if (!ctx) {
  92. SDL_OutOfMemory();
  93. return SDL_FALSE;
  94. }
  95. device->context = ctx;
  96. device->type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
  97. HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller");
  98. return HIDAPI_JoystickConnected(device, NULL);
  99. }
  100. static int
  101. HIDAPI_DriverShield_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
  102. {
  103. return -1;
  104. }
  105. static void
  106. HIDAPI_DriverShield_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
  107. {
  108. }
  109. static int
  110. HIDAPI_DriverShield_SendCommand(SDL_HIDAPI_Device *device, Uint8 cmd, const void *data, int size)
  111. {
  112. SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context;
  113. ShieldCommandReport_t cmd_pkt;
  114. if (size > sizeof(cmd_pkt.payload)) {
  115. return SDL_SetError("Command data exceeds HID report size");
  116. }
  117. if (SDL_HIDAPI_LockRumble() < 0) {
  118. return -1;
  119. }
  120. cmd_pkt.report_id = k_ShieldReportIdCommandRequest;
  121. cmd_pkt.cmd = cmd;
  122. cmd_pkt.seq_num = ctx->seq_num++;
  123. if (data) {
  124. SDL_memcpy(cmd_pkt.payload, data, size);
  125. }
  126. /* Zero unused data in the payload */
  127. SDL_memset(&cmd_pkt.payload[size], 0, sizeof(cmd_pkt.payload) - size);
  128. if (SDL_HIDAPI_SendRumbleAndUnlock(device, (Uint8*)&cmd_pkt, sizeof(cmd_pkt)) != sizeof(cmd_pkt)) {
  129. return SDL_SetError("Couldn't send command packet");
  130. }
  131. return 0;
  132. }
  133. static SDL_bool
  134. HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  135. {
  136. SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context;
  137. ctx->rumble_report_pending = SDL_FALSE;
  138. ctx->rumble_update_pending = SDL_FALSE;
  139. ctx->left_motor_amplitude = 0;
  140. ctx->right_motor_amplitude = 0;
  141. ctx->last_rumble_time = 0;
  142. SDL_zeroa(ctx->last_state);
  143. /* Initialize the joystick capabilities */
  144. joystick->nbuttons = 16;
  145. joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
  146. joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
  147. /* Request battery and charging info */
  148. ctx->last_battery_query_time = SDL_GetTicks();
  149. HIDAPI_DriverShield_SendCommand(device, CMD_CHARGE_STATE, NULL, 0);
  150. HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0);
  151. return SDL_TRUE;
  152. }
  153. static int
  154. HIDAPI_DriverShield_SendNextRumble(SDL_HIDAPI_Device *device)
  155. {
  156. SDL_DriverShield_Context *ctx = device->context;
  157. Uint8 rumble_data[3];
  158. if (!ctx->rumble_update_pending) {
  159. return 0;
  160. }
  161. rumble_data[0] = 0x01; /* enable */
  162. rumble_data[1] = ctx->left_motor_amplitude;
  163. rumble_data[2] = ctx->right_motor_amplitude;
  164. ctx->rumble_update_pending = SDL_FALSE;
  165. ctx->last_rumble_time = SDL_GetTicks();
  166. return HIDAPI_DriverShield_SendCommand(device, CMD_RUMBLE, rumble_data, sizeof(rumble_data));
  167. }
  168. static int
  169. HIDAPI_DriverShield_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  170. {
  171. SDL_DriverShield_Context *ctx = device->context;
  172. /* The rumble motors are quite intense, so tone down the intensity like the official driver does */
  173. ctx->left_motor_amplitude = low_frequency_rumble >> 11;
  174. ctx->right_motor_amplitude = high_frequency_rumble >> 11;
  175. ctx->rumble_update_pending = SDL_TRUE;
  176. if (ctx->rumble_report_pending) {
  177. /* We will service this after the hardware acknowledges the previous request */
  178. return 0;
  179. }
  180. return HIDAPI_DriverShield_SendNextRumble(device);
  181. }
  182. static int
  183. HIDAPI_DriverShield_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
  184. {
  185. return SDL_Unsupported();
  186. }
  187. static Uint32
  188. HIDAPI_DriverShield_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  189. {
  190. return SDL_JOYCAP_RUMBLE;
  191. }
  192. static int
  193. HIDAPI_DriverShield_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
  194. {
  195. return SDL_Unsupported();
  196. }
  197. static int
  198. HIDAPI_DriverShield_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
  199. {
  200. const Uint8 *data_bytes = data;
  201. if (size > 1) {
  202. /* Single command byte followed by a variable length payload */
  203. return HIDAPI_DriverShield_SendCommand(device, data_bytes[0], &data_bytes[1], size - 1);
  204. } else if (size == 1) {
  205. /* Single command byte with no payload */
  206. return HIDAPI_DriverShield_SendCommand(device, data_bytes[0], NULL, 0);
  207. } else {
  208. return SDL_SetError("Effect data must at least contain a command byte");
  209. }
  210. }
  211. static int
  212. HIDAPI_DriverShield_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
  213. {
  214. return SDL_Unsupported();
  215. }
  216. static void
  217. HIDAPI_DriverShield_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverShield_Context *ctx, Uint8 *data, int size)
  218. {
  219. if (size < 23) {
  220. return;
  221. }
  222. if (ctx->last_state[2] != data[2]) {
  223. SDL_bool dpad_up = SDL_FALSE;
  224. SDL_bool dpad_down = SDL_FALSE;
  225. SDL_bool dpad_left = SDL_FALSE;
  226. SDL_bool dpad_right = SDL_FALSE;
  227. switch (data[2]) {
  228. case 0:
  229. dpad_up = SDL_TRUE;
  230. break;
  231. case 1:
  232. dpad_up = SDL_TRUE;
  233. dpad_right = SDL_TRUE;
  234. break;
  235. case 2:
  236. dpad_right = SDL_TRUE;
  237. break;
  238. case 3:
  239. dpad_right = SDL_TRUE;
  240. dpad_down = SDL_TRUE;
  241. break;
  242. case 4:
  243. dpad_down = SDL_TRUE;
  244. break;
  245. case 5:
  246. dpad_left = SDL_TRUE;
  247. dpad_down = SDL_TRUE;
  248. break;
  249. case 6:
  250. dpad_left = SDL_TRUE;
  251. break;
  252. case 7:
  253. dpad_up = SDL_TRUE;
  254. dpad_left = SDL_TRUE;
  255. break;
  256. default:
  257. break;
  258. }
  259. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
  260. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
  261. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
  262. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
  263. }
  264. if (ctx->last_state[3] != data[3]) {
  265. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  266. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  267. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
  268. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
  269. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
  270. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
  271. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
  272. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
  273. }
  274. if (ctx->last_state[4] != data[4]) {
  275. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  276. }
  277. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, SDL_SwapLE16(*(Sint16*)&data[9]) - 0x8000);
  278. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, SDL_SwapLE16(*(Sint16*)&data[11]) - 0x8000);
  279. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, SDL_SwapLE16(*(Sint16*)&data[13]) - 0x8000);
  280. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, SDL_SwapLE16(*(Sint16*)&data[15]) - 0x8000);
  281. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, SDL_SwapLE16(*(Sint16*)&data[19]) - 0x8000);
  282. SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, SDL_SwapLE16(*(Sint16*)&data[21]) - 0x8000);
  283. if (ctx->last_state[17] != data[17]) {
  284. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[17] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
  285. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[17] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
  286. SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[17] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
  287. }
  288. SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
  289. }
  290. static SDL_bool
  291. HIDAPI_DriverShield_UpdateDevice(SDL_HIDAPI_Device *device)
  292. {
  293. SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context;
  294. SDL_Joystick *joystick = NULL;
  295. Uint8 data[USB_PACKET_LENGTH];
  296. int size = 0;
  297. ShieldCommandReport_t *cmd_resp_report;
  298. if (device->num_joysticks > 0) {
  299. joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
  300. } else {
  301. return SDL_FALSE;
  302. }
  303. while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
  304. #ifdef DEBUG_SHIELD_PROTOCOL
  305. HIDAPI_DumpPacket("NVIDIA SHIELD packet: size = %d", data, size);
  306. #endif
  307. /* Byte 0 is HID report ID */
  308. switch (data[0]) {
  309. case k_ShieldReportIdControllerState:
  310. if (!joystick) {
  311. break;
  312. }
  313. HIDAPI_DriverShield_HandleStatePacket(joystick, ctx, data, size);
  314. break;
  315. case k_ShieldReportIdCommandResponse:
  316. cmd_resp_report = (ShieldCommandReport_t*)data;
  317. switch (cmd_resp_report->cmd) {
  318. case CMD_RUMBLE:
  319. ctx->rumble_report_pending = SDL_FALSE;
  320. HIDAPI_DriverShield_SendNextRumble(device);
  321. break;
  322. case CMD_CHARGE_STATE:
  323. ctx->charging = cmd_resp_report->payload[0] != 0;
  324. if (joystick) {
  325. SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level);
  326. }
  327. break;
  328. case CMD_BATTERY_STATE:
  329. switch (cmd_resp_report->payload[2]) {
  330. case 0:
  331. ctx->battery_level = SDL_JOYSTICK_POWER_EMPTY;
  332. break;
  333. case 1:
  334. ctx->battery_level = SDL_JOYSTICK_POWER_LOW;
  335. break;
  336. case 2: /* 40% */
  337. case 3: /* 60% */
  338. case 4: /* 80% */
  339. ctx->battery_level = SDL_JOYSTICK_POWER_MEDIUM;
  340. break;
  341. case 5:
  342. ctx->battery_level = SDL_JOYSTICK_POWER_FULL;
  343. break;
  344. default:
  345. ctx->battery_level = SDL_JOYSTICK_POWER_UNKNOWN;
  346. break;
  347. }
  348. if (joystick) {
  349. SDL_PrivateJoystickBatteryLevel(joystick, ctx->charging ? SDL_JOYSTICK_POWER_WIRED : ctx->battery_level);
  350. }
  351. break;
  352. }
  353. break;
  354. }
  355. }
  356. /* Ask for battery state again if we're due for an update */
  357. if (joystick && SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_battery_query_time + BATTERY_POLL_INTERVAL_MS)) {
  358. ctx->last_battery_query_time = SDL_GetTicks();
  359. HIDAPI_DriverShield_SendCommand(device, CMD_BATTERY_STATE, NULL, 0);
  360. }
  361. /* Retransmit rumble packets if they've lasted longer than the hardware supports */
  362. if ((ctx->left_motor_amplitude != 0 || ctx->right_motor_amplitude != 0) &&
  363. SDL_TICKS_PASSED(SDL_GetTicks(), ctx->last_rumble_time + RUMBLE_REFRESH_INTERVAL_MS)) {
  364. ctx->rumble_update_pending = SDL_TRUE;
  365. HIDAPI_DriverShield_SendNextRumble(device);
  366. }
  367. if (size < 0) {
  368. /* Read error, device is disconnected */
  369. HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
  370. }
  371. return (size >= 0);
  372. }
  373. static void
  374. HIDAPI_DriverShield_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
  375. {
  376. }
  377. static void
  378. HIDAPI_DriverShield_FreeDevice(SDL_HIDAPI_Device *device)
  379. {
  380. }
  381. SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield =
  382. {
  383. SDL_HINT_JOYSTICK_HIDAPI_SHIELD,
  384. SDL_TRUE,
  385. HIDAPI_DriverShield_RegisterHints,
  386. HIDAPI_DriverShield_UnregisterHints,
  387. HIDAPI_DriverShield_IsEnabled,
  388. HIDAPI_DriverShield_IsSupportedDevice,
  389. HIDAPI_DriverShield_InitDevice,
  390. HIDAPI_DriverShield_GetDevicePlayerIndex,
  391. HIDAPI_DriverShield_SetDevicePlayerIndex,
  392. HIDAPI_DriverShield_UpdateDevice,
  393. HIDAPI_DriverShield_OpenJoystick,
  394. HIDAPI_DriverShield_RumbleJoystick,
  395. HIDAPI_DriverShield_RumbleJoystickTriggers,
  396. HIDAPI_DriverShield_GetJoystickCapabilities,
  397. HIDAPI_DriverShield_SetJoystickLED,
  398. HIDAPI_DriverShield_SendJoystickEffect,
  399. HIDAPI_DriverShield_SetJoystickSensorsEnabled,
  400. HIDAPI_DriverShield_CloseJoystick,
  401. HIDAPI_DriverShield_FreeDevice,
  402. };
  403. #endif /* SDL_JOYSTICK_HIDAPI_SHIELD */
  404. #endif /* SDL_JOYSTICK_HIDAPI */
  405. /* vi: set ts=4 sw=4 expandtab: */