Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

joystick.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /* USB EHCI Host for Teensy 3.6
  2. * Copyright 2017 Paul Stoffregen (paul@pjrc.com)
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <Arduino.h>
  24. #include "USBHost_t36.h" // Read this header first for key info
  25. #define print USBHost::print_
  26. #define println USBHost::println_
  27. void JoystickController::init()
  28. {
  29. contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
  30. contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
  31. contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
  32. driver_ready_for_device(this);
  33. USBHIDParser::driver_ready_for_hid_collection(this);
  34. }
  35. //*****************************************************************************
  36. // Some simple query functions depend on which interface we are using...
  37. //*****************************************************************************
  38. uint16_t JoystickController::idVendor()
  39. {
  40. if (device != nullptr) return device->idVendor;
  41. if (mydevice != nullptr) return mydevice->idVendor;
  42. return 0;
  43. }
  44. uint16_t JoystickController::idProduct()
  45. {
  46. if (device != nullptr) return device->idProduct;
  47. if (mydevice != nullptr) return mydevice->idProduct;
  48. return 0;
  49. }
  50. const uint8_t *JoystickController::manufacturer()
  51. {
  52. if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
  53. if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
  54. return nullptr;
  55. }
  56. const uint8_t *JoystickController::product()
  57. {
  58. if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
  59. if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
  60. return nullptr;
  61. }
  62. const uint8_t *JoystickController::serialNumber()
  63. {
  64. if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
  65. if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
  66. return nullptr;
  67. }
  68. //*****************************************************************************
  69. // Support for Joysticks that USe HID data.
  70. //*****************************************************************************
  71. hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage)
  72. {
  73. // only claim Desktop/Joystick and Desktop/Gamepad
  74. if (topusage != 0x10004 && topusage != 0x10005) return CLAIM_NO;
  75. // only claim from one physical device
  76. if (mydevice != NULL && dev != mydevice) return CLAIM_NO;
  77. mydevice = dev;
  78. collections_claimed++;
  79. anychange = true; // always report values on first read
  80. return CLAIM_REPORT;
  81. }
  82. void JoystickController::disconnect_collection(Device_t *dev)
  83. {
  84. if (--collections_claimed == 0) {
  85. mydevice = NULL;
  86. axis_mask_ = 0;
  87. }
  88. }
  89. void JoystickController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax)
  90. {
  91. // TODO: set up translation from logical min/max to consistent 16 bit scale
  92. }
  93. void JoystickController::hid_input_data(uint32_t usage, int32_t value)
  94. {
  95. //Serial.printf("Joystick: usage=%X, value=%d\n", usage, value);
  96. uint32_t usage_page = usage >> 16;
  97. usage &= 0xFFFF;
  98. if (usage_page == 9 && usage >= 1 && usage <= 32) {
  99. uint32_t bit = 1 << (usage -1);
  100. if (value == 0) {
  101. if (buttons & bit) {
  102. buttons &= ~bit;
  103. anychange = true;
  104. }
  105. } else {
  106. if (!(buttons & bit)) {
  107. buttons |= bit;
  108. anychange = true;
  109. }
  110. }
  111. } else if (usage_page == 1 && usage >= 0x30 && usage <= 0x39) {
  112. // TODO: need scaling of value to consistent API, 16 bit signed?
  113. // TODO: many joysticks repeat slider usage. Detect & map to axis?
  114. uint32_t i = usage - 0x30;
  115. axis_mask_ |= (1 << i); // Keep record of which axis we have data on.
  116. if (axis[i] != value) {
  117. axis[i] = value;
  118. anychange = true;
  119. }
  120. }
  121. // TODO: hat switch?
  122. }
  123. void JoystickController::hid_input_end()
  124. {
  125. if (anychange) {
  126. joystickEvent = true;
  127. }
  128. }
  129. void JoystickController::joystickDataClear() {
  130. joystickEvent = false;
  131. anychange = false;
  132. }
  133. //*****************************************************************************
  134. // Support for Joysticks that are class specific and do not use HID
  135. // Example: XBox One controller.
  136. //*****************************************************************************
  137. // Note: currently just XBOX one.
  138. JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = {
  139. { 0x045e, 0x02ea },{ 0x045e, 0x02dd } };
  140. static uint8_t start_input[] = {0x05, 0x20, 0x00, 0x01, 0x00};
  141. bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
  142. {
  143. println("JoystickController claim this=", (uint32_t)this, HEX);
  144. // only claim at device level
  145. if (type != 0) return false;
  146. print_hexbytes(descriptors, len);
  147. uint8_t i = 0;
  148. for (; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) {
  149. if ((dev->idVendor == pid_vid_mapping[i].idVendor) && (dev->idProduct == pid_vid_mapping[i].idProduct)) {
  150. break;
  151. }
  152. }
  153. if (i == (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0]))) return false; // Not in our list
  154. // 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1...
  155. // 09 04 00 00 02 FF 47 D0 00 07 05 02 03 40 00 04 07 05 82 03 40 00 04 09 04 01 00 00 FF 47 D0 00
  156. // Lets do some verifications to make sure.
  157. if (len < 9+7+7) return false;
  158. uint32_t count_end_points = descriptors[4];
  159. if (count_end_points < 2) return false;
  160. if (descriptors[5] != 0xff) return false; // bInterfaceClass, 3 = HID
  161. uint32_t rxep = 0;
  162. uint32_t txep = 0;
  163. rx_size_ = 0;
  164. tx_size_ = 0;
  165. uint32_t descriptor_index = 9;
  166. while (count_end_points-- && ((rxep == 0) || txep == 0)) {
  167. if (descriptors[descriptor_index] != 7) return false; // length 7
  168. if (descriptors[descriptor_index+1] != 5) return false; // ep desc
  169. if ((descriptors[descriptor_index+3] == 3) // Type 3...
  170. && (descriptors[descriptor_index+4] <= 64)
  171. && (descriptors[descriptor_index+5] == 0)) {
  172. // have a bulk EP size
  173. if (descriptors[descriptor_index+2] & 0x80 ) {
  174. rxep = descriptors[descriptor_index+2];
  175. rx_size_ = descriptors[descriptor_index+4];
  176. } else {
  177. txep = descriptors[descriptor_index+2];
  178. tx_size_ = descriptors[descriptor_index+4];
  179. }
  180. }
  181. descriptor_index += 7; // setup to look at next one...
  182. }
  183. if ((rxep == 0) || (txep == 0)) return false; // did not find two end points.
  184. print("JoystickController, rxep=", rxep & 15);
  185. print("(", rx_size_);
  186. print("), txep=", txep);
  187. print("(", tx_size_);
  188. println(")");
  189. rxpipe_ = new_Pipe(dev, 2, rxep & 15, 1, rx_size_);
  190. if (!rxpipe_) return false;
  191. txpipe_ = new_Pipe(dev, 2, txep, 0, tx_size_);
  192. if (!txpipe_) {
  193. //free_Pipe(rxpipe_);
  194. return false;
  195. }
  196. rxpipe_->callback_function = rx_callback;
  197. queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);
  198. txpipe_->callback_function = tx_callback;
  199. queue_Data_Transfer(txpipe_, start_input, sizeof(start_input), this);
  200. memset(axis, 0, sizeof(axis)); // clear out any data.
  201. return true;
  202. }
  203. void JoystickController::control(const Transfer_t *transfer)
  204. {
  205. }
  206. /************************************************************/
  207. // Interrupt-based Data Movement
  208. /************************************************************/
  209. void JoystickController::rx_callback(const Transfer_t *transfer)
  210. {
  211. if (!transfer->driver) return;
  212. ((JoystickController *)(transfer->driver))->rx_data(transfer);
  213. }
  214. void JoystickController::tx_callback(const Transfer_t *transfer)
  215. {
  216. if (!transfer->driver) return;
  217. ((JoystickController *)(transfer->driver))->tx_data(transfer);
  218. }
  219. /************************************************************/
  220. // Interrupt-based Data Movement
  221. // XBox one input data when type == 0x20
  222. // Information came from several places on the web including:
  223. // https://github.com/quantus/xbox-one-controller-protocol
  224. /************************************************************/
  225. typedef struct {
  226. uint8_t type;
  227. uint8_t const_0;
  228. uint16_t id;
  229. // From online references button order:
  230. // sync, dummy, start, back, a, b, x, y
  231. // dpad up, down left, right
  232. // lb, rb, left stick, right stick
  233. // Axis:
  234. // lt, rt, lx, xy, rx, ry
  235. //
  236. uint16_t buttons;
  237. int16_t axis[6];
  238. } xbox1data20_t;
  239. static const uint8_t xbox_axis_order_mapping[] = {4, 5, 0, 1, 2, 3};
  240. void JoystickController::rx_data(const Transfer_t *transfer)
  241. {
  242. // print("JoystickController::rx_data: ");
  243. // print_hexbytes((uint8_t*)transfer->buffer, transfer->length);
  244. axis_mask_ = 0x3f;
  245. xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
  246. if ((xb1d->type == 0x20) && (transfer->length >= sizeof (xbox1data20_t))) {
  247. // We have a data transfer. Lets see what is new...
  248. if (xb1d->buttons != buttons) {
  249. buttons = xb1d->buttons;
  250. anychange = true;
  251. }
  252. for (uint8_t i = 0; i < sizeof (xbox_axis_order_mapping); i++) {
  253. // The first two values were unsigned.
  254. int axis_value = (i < 2)? (int)(uint16_t)xb1d->axis[i] : xb1d->axis[i];
  255. if (axis_value != axis[xbox_axis_order_mapping[i]]) {
  256. axis[xbox_axis_order_mapping[i]] = axis_value;
  257. anychange = true;
  258. }
  259. }
  260. joystickEvent = true;
  261. }
  262. queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);
  263. }
  264. void JoystickController::tx_data(const Transfer_t *transfer)
  265. {
  266. }
  267. void JoystickController::disconnect()
  268. {
  269. axis_mask_ = 0;
  270. // TODO: free resources
  271. }