pof_usb.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. #include "pof_usb.h"
  2. #define TAG "POF USB"
  3. #define HID_INTERVAL 1
  4. #define USB_EP0_SIZE 8
  5. #define POF_USB_VID (0x1430)
  6. #define POF_USB_PID (0x0150)
  7. #define POF_USB_PID_X360 (0x1F17)
  8. #define POF_USB_EP_IN (0x81)
  9. #define POF_USB_EP_OUT (0x02)
  10. #define POF_USB_X360_AUDIO_EP_IN1 (0x83)
  11. #define POF_USB_X360_AUDIO_EP_OUT1 (0x04)
  12. #define POF_USB_X360_AUDIO_EP_IN2 (0x85)
  13. #define POF_USB_X360_AUDIO_EP_OUT2 (0x06)
  14. #define POF_USB_X360_PLUGIN_MODULE_EP_IN (0x87)
  15. #define POF_USB_EP_IN_SIZE (64UL)
  16. #define POF_USB_EP_OUT_SIZE (64UL)
  17. #define POF_USB_RX_MAX_SIZE (POF_USB_EP_OUT_SIZE)
  18. #define POF_USB_TX_MAX_SIZE (POF_USB_EP_IN_SIZE)
  19. #define POF_USB_ACTUAL_OUTPUT_SIZE 0x20
  20. static const struct usb_string_descriptor dev_manuf_desc =
  21. USB_ARRAY_DESC(0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x00);
  22. static const struct usb_string_descriptor dev_product_desc =
  23. USB_ARRAY_DESC(0x53, 0x70, 0x79, 0x72, 0x6f, 0x20, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x00);
  24. static const struct usb_string_descriptor dev_security_desc =
  25. USB_STRING_DESC("Xbox Security Method 3, Version 1.00, © 2005 Microsoft Corporation. All rights reserved.");
  26. static const uint8_t hid_report_desc[] = {0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x19,
  27. 0x01, 0x29, 0x40, 0x15, 0x00, 0x26, 0xFF, 0x00,
  28. 0x75, 0x08, 0x95, 0x20, 0x81, 0x00, 0x19, 0x01,
  29. 0x29, 0x40, 0x91, 0x00, 0xC0};
  30. static usbd_respond pof_usb_ep_config(usbd_device* dev, uint8_t cfg);
  31. static usbd_respond
  32. pof_hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  33. static usbd_respond
  34. pof_xbox_360_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
  35. static void pof_usb_send(usbd_device* dev, uint8_t* buf, uint16_t len);
  36. static int32_t pof_usb_receive(usbd_device* dev, uint8_t* buf, uint16_t max_len);
  37. typedef enum {
  38. EventExit = (1 << 0),
  39. EventReset = (1 << 1),
  40. EventRx = (1 << 2),
  41. EventTx = (1 << 3),
  42. EventTxComplete = (1 << 4),
  43. EventResetSio = (1 << 5),
  44. EventTxImmediate = (1 << 6),
  45. EventAll = EventExit | EventReset | EventRx | EventTx | EventTxComplete | EventResetSio |
  46. EventTxImmediate,
  47. } PoFEvent;
  48. struct PoFUsb {
  49. FuriHalUsbInterface usb;
  50. FuriHalUsbInterface* usb_prev;
  51. FuriThread* thread;
  52. usbd_device* dev;
  53. VirtualPortal* virtual_portal;
  54. uint8_t data_recvest[8];
  55. uint16_t data_recvest_len;
  56. bool tx_complete;
  57. bool tx_immediate;
  58. uint8_t dataAvailable;
  59. uint8_t data[POF_USB_RX_MAX_SIZE];
  60. uint8_t tx_data[POF_USB_TX_MAX_SIZE];
  61. };
  62. static PoFUsb* pof_cur = NULL;
  63. static int32_t pof_thread_worker(void* context) {
  64. PoFUsb* pof_usb = context;
  65. usbd_device* dev = pof_usb->dev;
  66. VirtualPortal* virtual_portal = pof_usb->virtual_portal;
  67. UNUSED(dev);
  68. uint32_t len_data = 0;
  69. uint8_t tx_data[POF_USB_TX_MAX_SIZE] = {0};
  70. uint32_t timeout = 30; // FuriWaitForever; //ms
  71. uint32_t lastStatus = 0x0;
  72. while(true) {
  73. uint32_t now = furi_get_tick();
  74. uint32_t flags = furi_thread_flags_wait(EventAll, FuriFlagWaitAny, timeout);
  75. if(flags & EventRx) { //fast flag
  76. UNUSED(pof_usb_receive);
  77. if(virtual_portal->speaker) {
  78. uint8_t buf[POF_USB_RX_MAX_SIZE];
  79. len_data = pof_usb_receive(dev, buf, POF_USB_RX_MAX_SIZE);
  80. // https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/wav_player/wav_player_hal.c
  81. if(len_data > 0) {
  82. /*
  83. FURI_LOG_RAW_I("pof_usb_receive: ");
  84. for(uint32_t i = 0; i < len_data; i++) {
  85. FURI_LOG_RAW_I("%02x", buf[i]);
  86. }
  87. FURI_LOG_RAW_I("\r\n");
  88. */
  89. }
  90. }
  91. if(pof_usb->dataAvailable > 0) {
  92. memset(tx_data, 0, sizeof(tx_data));
  93. int send_len =
  94. virtual_portal_process_message(virtual_portal, pof_usb->data, tx_data);
  95. if(send_len > 0) {
  96. pof_usb_send(dev, tx_data, POF_USB_ACTUAL_OUTPUT_SIZE);
  97. }
  98. pof_usb->dataAvailable = 0;
  99. }
  100. // Check next status time since the timeout based one might be starved by incoming packets.
  101. if(now > lastStatus + timeout) {
  102. lastStatus = now;
  103. memset(tx_data, 0, sizeof(tx_data));
  104. len_data = virtual_portal_send_status(virtual_portal, tx_data);
  105. if(len_data > 0) {
  106. pof_usb_send(dev, tx_data, POF_USB_ACTUAL_OUTPUT_SIZE);
  107. }
  108. }
  109. flags &= ~EventRx; // clear flag
  110. }
  111. if(flags) {
  112. if(flags & EventResetSio) {
  113. }
  114. if(flags & EventTxComplete) {
  115. pof_usb->tx_complete = true;
  116. }
  117. if(flags & EventTxImmediate) {
  118. pof_usb->tx_immediate = true;
  119. if(pof_usb->tx_complete) {
  120. flags |= EventTx;
  121. }
  122. }
  123. if(flags & EventTx) {
  124. pof_usb->tx_complete = false;
  125. pof_usb->tx_immediate = false;
  126. }
  127. if(flags & EventExit) {
  128. FURI_LOG_I(TAG, "exit");
  129. break;
  130. }
  131. }
  132. if(flags == (uint32_t)FuriFlagErrorISR) { // timeout
  133. memset(tx_data, 0, sizeof(tx_data));
  134. len_data = virtual_portal_send_status(virtual_portal, tx_data);
  135. if(len_data > 0) {
  136. pof_usb_send(dev, tx_data, POF_USB_ACTUAL_OUTPUT_SIZE);
  137. }
  138. lastStatus = now;
  139. }
  140. }
  141. return 0;
  142. }
  143. static void pof_usb_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  144. UNUSED(intf);
  145. PoFUsb* pof_usb = ctx;
  146. pof_cur = pof_usb;
  147. pof_usb->dev = dev;
  148. usbd_reg_config(dev, pof_usb_ep_config);
  149. usbd_reg_control(dev, pof_hid_control);
  150. UNUSED(pof_hid_control);
  151. usbd_connect(dev, true);
  152. pof_usb->thread = furi_thread_alloc();
  153. furi_thread_set_name(pof_usb->thread, "PoFUsb");
  154. furi_thread_set_stack_size(pof_usb->thread, 2 * 1024);
  155. furi_thread_set_context(pof_usb->thread, ctx);
  156. furi_thread_set_callback(pof_usb->thread, pof_thread_worker);
  157. furi_thread_start(pof_usb->thread);
  158. }
  159. static void pof_usb_init_xbox_360(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
  160. UNUSED(intf);
  161. PoFUsb* pof_usb = ctx;
  162. pof_cur = pof_usb;
  163. pof_usb->dev = dev;
  164. usbd_reg_config(dev, pof_usb_ep_config);
  165. usbd_reg_control(dev, pof_xbox_360_control);
  166. UNUSED(pof_xbox_360_control);
  167. usbd_connect(dev, true);
  168. pof_usb->thread = furi_thread_alloc();
  169. furi_thread_set_name(pof_usb->thread, "PoFUsb");
  170. furi_thread_set_stack_size(pof_usb->thread, 2 * 1024);
  171. furi_thread_set_context(pof_usb->thread, ctx);
  172. furi_thread_set_callback(pof_usb->thread, pof_thread_worker);
  173. furi_thread_start(pof_usb->thread);
  174. }
  175. static void pof_usb_deinit(usbd_device* dev) {
  176. usbd_reg_config(dev, NULL);
  177. usbd_reg_control(dev, NULL);
  178. PoFUsb* pof_usb = pof_cur;
  179. if(!pof_usb || pof_usb->dev != dev) {
  180. return;
  181. }
  182. pof_cur = NULL;
  183. furi_assert(pof_usb->thread);
  184. furi_thread_flags_set(furi_thread_get_id(pof_usb->thread), EventExit);
  185. furi_thread_join(pof_usb->thread);
  186. furi_thread_free(pof_usb->thread);
  187. pof_usb->thread = NULL;
  188. free(pof_usb->usb.str_prod_descr);
  189. pof_usb->usb.str_prod_descr = NULL;
  190. free(pof_usb->usb.str_serial_descr);
  191. pof_usb->usb.str_serial_descr = NULL;
  192. free(pof_usb);
  193. }
  194. static void pof_usb_send(usbd_device* dev, uint8_t* buf, uint16_t len) {
  195. // Hide frequent responses
  196. /*
  197. if(buf[0] != 'S' && buf[0] != 'J') {
  198. FURI_LOG_RAW_D("> ");
  199. for(size_t i = 0; i < len; i++) {
  200. FURI_LOG_RAW_D("%02x", buf[i]);
  201. }
  202. FURI_LOG_RAW_D("\r\n");
  203. }
  204. */
  205. usbd_ep_write(dev, POF_USB_EP_IN, buf, len);
  206. }
  207. static int32_t pof_usb_receive(usbd_device* dev, uint8_t* buf, uint16_t max_len) {
  208. int32_t len = usbd_ep_read(dev, POF_USB_EP_OUT, buf, max_len);
  209. return ((len < 0) ? 0 : len);
  210. }
  211. static void pof_usb_wakeup(usbd_device* dev) {
  212. UNUSED(dev);
  213. }
  214. static void pof_usb_suspend(usbd_device* dev) {
  215. PoFUsb* pof_usb = pof_cur;
  216. if(!pof_usb || pof_usb->dev != dev) return;
  217. }
  218. static void pof_usb_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  219. UNUSED(dev);
  220. UNUSED(event);
  221. UNUSED(ep);
  222. PoFUsb* pof_usb = pof_cur;
  223. furi_thread_flags_set(furi_thread_get_id(pof_usb->thread), EventRx);
  224. }
  225. static void pof_usb_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
  226. UNUSED(dev);
  227. UNUSED(event);
  228. UNUSED(ep);
  229. PoFUsb* pof_usb = pof_cur;
  230. furi_thread_flags_set(furi_thread_get_id(pof_usb->thread), EventTxComplete);
  231. }
  232. static usbd_respond pof_usb_ep_config(usbd_device* dev, uint8_t cfg) {
  233. switch(cfg) {
  234. case 0: // deconfig
  235. usbd_ep_deconfig(dev, POF_USB_EP_OUT);
  236. usbd_ep_deconfig(dev, POF_USB_EP_IN);
  237. usbd_reg_endpoint(dev, POF_USB_EP_OUT, NULL);
  238. usbd_reg_endpoint(dev, POF_USB_EP_IN, NULL);
  239. return usbd_ack;
  240. case 1: // config
  241. usbd_ep_config(dev, POF_USB_EP_IN, USB_EPTYPE_INTERRUPT, POF_USB_EP_IN_SIZE);
  242. usbd_ep_config(dev, POF_USB_EP_OUT, USB_EPTYPE_INTERRUPT, POF_USB_EP_OUT_SIZE);
  243. usbd_reg_endpoint(dev, POF_USB_EP_IN, pof_usb_tx_ep_callback);
  244. usbd_reg_endpoint(dev, POF_USB_EP_OUT, pof_usb_rx_ep_callback);
  245. return usbd_ack;
  246. }
  247. return usbd_fail;
  248. }
  249. struct PoFUsbDescriptor {
  250. struct usb_config_descriptor config;
  251. struct usb_interface_descriptor intf;
  252. struct usb_hid_descriptor hid_desc;
  253. struct usb_endpoint_descriptor ep_in;
  254. struct usb_endpoint_descriptor ep_out;
  255. } __attribute__((packed));
  256. struct usb_xbox_intf_descriptor {
  257. uint8_t bLength;
  258. uint8_t bDescriptorType;
  259. uint8_t reserved[2];
  260. uint8_t subtype;
  261. uint8_t reserved2;
  262. uint8_t bEndpointAddressIn;
  263. uint8_t bMaxDataSizeIn;
  264. uint8_t reserved3[5];
  265. uint8_t bEndpointAddressOut;
  266. uint8_t bMaxDataSizeOut;
  267. uint8_t reserved4[2];
  268. } __attribute__((packed));
  269. struct PoFUsbDescriptorXbox360 {
  270. struct usb_config_descriptor config;
  271. struct usb_interface_descriptor intf;
  272. struct usb_xbox_intf_descriptor xbox_desc;
  273. struct usb_endpoint_descriptor ep_in;
  274. struct usb_endpoint_descriptor ep_out;
  275. struct usb_interface_descriptor intfAudio;
  276. uint8_t audio_desc[0x1B];
  277. struct usb_endpoint_descriptor ep_in_audio1;
  278. struct usb_endpoint_descriptor ep_out_audio1;
  279. struct usb_endpoint_descriptor ep_in_audio2;
  280. struct usb_endpoint_descriptor ep_out_audio2;
  281. struct usb_interface_descriptor intfPluginModule;
  282. uint8_t plugin_module_desc[0x09];
  283. struct usb_endpoint_descriptor ep_in_plugin_module;
  284. struct usb_interface_descriptor intfSecurity;
  285. uint8_t security_desc[0x06];
  286. } __attribute__((packed));
  287. static const struct usb_device_descriptor usb_pof_dev_descr = {
  288. .bLength = sizeof(struct usb_device_descriptor),
  289. .bDescriptorType = USB_DTYPE_DEVICE,
  290. .bcdUSB = VERSION_BCD(2, 0, 0),
  291. .bDeviceClass = USB_CLASS_PER_INTERFACE,
  292. .bDeviceSubClass = USB_SUBCLASS_NONE,
  293. .bDeviceProtocol = USB_PROTO_NONE,
  294. .bMaxPacketSize0 = USB_EP0_SIZE,
  295. .idVendor = POF_USB_VID,
  296. .idProduct = POF_USB_PID,
  297. .bcdDevice = VERSION_BCD(1, 0, 0),
  298. .iManufacturer = 1, // UsbDevManuf
  299. .iProduct = 2, // UsbDevProduct
  300. .iSerialNumber = 0,
  301. .bNumConfigurations = 1,
  302. };
  303. static const struct usb_device_descriptor usb_pof_dev_descr_xbox_360 = {
  304. .bLength = sizeof(struct usb_device_descriptor),
  305. .bDescriptorType = USB_DTYPE_DEVICE,
  306. .bcdUSB = VERSION_BCD(2, 0, 0),
  307. .bDeviceClass = USB_CLASS_PER_INTERFACE,
  308. .bDeviceSubClass = USB_SUBCLASS_NONE,
  309. .bDeviceProtocol = USB_PROTO_NONE,
  310. .bMaxPacketSize0 = USB_EP0_SIZE,
  311. .idVendor = POF_USB_VID,
  312. .idProduct = POF_USB_PID_X360,
  313. .bcdDevice = VERSION_BCD(1, 0, 0),
  314. .iManufacturer = 1, // UsbDevManuf
  315. .iProduct = 2, // UsbDevProduct
  316. .iSerialNumber = 0,
  317. .bNumConfigurations = 1,
  318. };
  319. static const struct PoFUsbDescriptor usb_pof_cfg_descr = {
  320. .config =
  321. {
  322. .bLength = sizeof(struct usb_config_descriptor),
  323. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  324. .wTotalLength = sizeof(struct PoFUsbDescriptor),
  325. .bNumInterfaces = 1,
  326. .bConfigurationValue = 1,
  327. .iConfiguration = NO_DESCRIPTOR,
  328. .bmAttributes = USB_CFG_ATTR_RESERVED,
  329. .bMaxPower = USB_CFG_POWER_MA(500),
  330. },
  331. .intf =
  332. {
  333. .bLength = sizeof(struct usb_interface_descriptor),
  334. .bDescriptorType = USB_DTYPE_INTERFACE,
  335. .bInterfaceNumber = 0,
  336. .bAlternateSetting = 0,
  337. .bNumEndpoints = 2,
  338. .bInterfaceClass = USB_CLASS_HID,
  339. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  340. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  341. .iInterface = NO_DESCRIPTOR,
  342. },
  343. .hid_desc =
  344. {
  345. .bLength = sizeof(struct usb_hid_descriptor),
  346. .bDescriptorType = USB_DTYPE_HID,
  347. .bcdHID = VERSION_BCD(1, 1, 1),
  348. .bCountryCode = USB_HID_COUNTRY_NONE,
  349. .bNumDescriptors = 1,
  350. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  351. .wDescriptorLength0 = sizeof(hid_report_desc),
  352. },
  353. .ep_in =
  354. {
  355. .bLength = sizeof(struct usb_endpoint_descriptor),
  356. .bDescriptorType = USB_DTYPE_ENDPOINT,
  357. .bEndpointAddress = POF_USB_EP_IN,
  358. .bmAttributes = USB_EPTYPE_INTERRUPT,
  359. .wMaxPacketSize = 0x40,
  360. .bInterval = HID_INTERVAL,
  361. },
  362. .ep_out =
  363. {
  364. .bLength = sizeof(struct usb_endpoint_descriptor),
  365. .bDescriptorType = USB_DTYPE_ENDPOINT,
  366. .bEndpointAddress = POF_USB_EP_OUT,
  367. .bmAttributes = USB_EPTYPE_INTERRUPT,
  368. .wMaxPacketSize = 0x40,
  369. .bInterval = HID_INTERVAL,
  370. },
  371. };
  372. static const struct PoFUsbDescriptorXbox360 usb_pof_cfg_descr_x360 = {
  373. .config =
  374. {
  375. .bLength = sizeof(struct usb_config_descriptor),
  376. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  377. .wTotalLength = sizeof(struct PoFUsbDescriptorXbox360),
  378. .bNumInterfaces = 4,
  379. .bConfigurationValue = 1,
  380. .iConfiguration = NO_DESCRIPTOR,
  381. .bmAttributes = USB_CFG_ATTR_RESERVED,
  382. .bMaxPower = USB_CFG_POWER_MA(500),
  383. },
  384. .intf =
  385. {
  386. .bLength = sizeof(struct usb_interface_descriptor),
  387. .bDescriptorType = USB_DTYPE_INTERFACE,
  388. .bInterfaceNumber = 0,
  389. .bAlternateSetting = 0,
  390. .bNumEndpoints = 2,
  391. .bInterfaceClass = 0xFF,
  392. .bInterfaceSubClass = 0x5D,
  393. .bInterfaceProtocol = 0x01,
  394. .iInterface = NO_DESCRIPTOR,
  395. },
  396. .xbox_desc =
  397. {
  398. .bLength = sizeof(struct usb_xbox_intf_descriptor),
  399. .bDescriptorType = 0x21,
  400. .reserved = {0x10, 0x01},
  401. .subtype = 0x24,
  402. .reserved2 = 0x25,
  403. .bEndpointAddressIn = POF_USB_EP_IN,
  404. .bMaxDataSizeIn = 0x14,
  405. .reserved3 = {0x03, 0x03, 0x03, 0x04, 0x13},
  406. .bEndpointAddressOut = POF_USB_EP_OUT,
  407. .bMaxDataSizeOut = 0x08,
  408. .reserved4 = {0x03, 0x03},
  409. },
  410. .ep_in =
  411. {
  412. .bLength = sizeof(struct usb_endpoint_descriptor),
  413. .bDescriptorType = USB_DTYPE_ENDPOINT,
  414. .bEndpointAddress = POF_USB_EP_IN,
  415. .bmAttributes = USB_EPTYPE_INTERRUPT,
  416. .wMaxPacketSize = 0x40,
  417. .bInterval = HID_INTERVAL,
  418. },
  419. .ep_out =
  420. {
  421. .bLength = sizeof(struct usb_endpoint_descriptor),
  422. .bDescriptorType = USB_DTYPE_ENDPOINT,
  423. .bEndpointAddress = POF_USB_EP_OUT,
  424. .bmAttributes = USB_EPTYPE_INTERRUPT,
  425. .wMaxPacketSize = 0x40,
  426. .bInterval = HID_INTERVAL,
  427. },
  428. .intfAudio =
  429. {
  430. .bLength = sizeof(struct usb_interface_descriptor),
  431. .bDescriptorType = USB_DTYPE_INTERFACE,
  432. .bInterfaceNumber = 1,
  433. .bAlternateSetting = 0,
  434. .bNumEndpoints = 4,
  435. .bInterfaceClass = 0xFF,
  436. .bInterfaceSubClass = 0x5D,
  437. .bInterfaceProtocol = 0x03,
  438. .iInterface = NO_DESCRIPTOR,
  439. },
  440. .audio_desc =
  441. {0x1B, 0x21, 0x00, 0x01, 0x01, 0x01, POF_USB_X360_AUDIO_EP_IN1, 0x40, 0x01, POF_USB_X360_AUDIO_EP_OUT1,
  442. 0x20, 0x16, POF_USB_X360_AUDIO_EP_IN2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
  443. POF_USB_X360_AUDIO_EP_OUT2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  444. .ep_in_audio1 =
  445. {
  446. .bLength = sizeof(struct usb_endpoint_descriptor),
  447. .bDescriptorType = USB_DTYPE_ENDPOINT,
  448. .bEndpointAddress = POF_USB_X360_AUDIO_EP_IN1,
  449. .bmAttributes = USB_EPTYPE_INTERRUPT,
  450. .wMaxPacketSize = 0x20,
  451. .bInterval = 2,
  452. },
  453. .ep_out_audio1 =
  454. {
  455. .bLength = sizeof(struct usb_endpoint_descriptor),
  456. .bDescriptorType = USB_DTYPE_ENDPOINT,
  457. .bEndpointAddress = POF_USB_X360_AUDIO_EP_OUT1,
  458. .bmAttributes = USB_EPTYPE_INTERRUPT,
  459. .wMaxPacketSize = 0x20,
  460. .bInterval = 4,
  461. },
  462. .ep_in_audio2 =
  463. {
  464. .bLength = sizeof(struct usb_endpoint_descriptor),
  465. .bDescriptorType = USB_DTYPE_ENDPOINT,
  466. .bEndpointAddress = POF_USB_X360_AUDIO_EP_IN2,
  467. .bmAttributes = USB_EPTYPE_INTERRUPT,
  468. .wMaxPacketSize = 0x20,
  469. .bInterval = 0x40,
  470. },
  471. .ep_out_audio2 =
  472. {
  473. .bLength = sizeof(struct usb_endpoint_descriptor),
  474. .bDescriptorType = USB_DTYPE_ENDPOINT,
  475. .bEndpointAddress = POF_USB_X360_AUDIO_EP_OUT2,
  476. .bmAttributes = USB_EPTYPE_INTERRUPT,
  477. .wMaxPacketSize = 0x10,
  478. .bInterval = 0x10,
  479. },
  480. .plugin_module_desc =
  481. {0x09, 0x21, 0x00, 0x01, 0x01, 0x22, POF_USB_X360_PLUGIN_MODULE_EP_IN, 0x07, 0x00},
  482. .ep_in_plugin_module =
  483. {
  484. .bLength = sizeof(struct usb_endpoint_descriptor),
  485. .bDescriptorType = USB_DTYPE_ENDPOINT,
  486. .bEndpointAddress = POF_USB_X360_PLUGIN_MODULE_EP_IN,
  487. .bmAttributes = USB_EPTYPE_INTERRUPT,
  488. .wMaxPacketSize = 0x20,
  489. .bInterval = 16,
  490. },
  491. .intfSecurity =
  492. {
  493. .bLength = sizeof(struct usb_interface_descriptor),
  494. .bDescriptorType = USB_DTYPE_INTERFACE,
  495. .bInterfaceNumber = 2,
  496. .bAlternateSetting = 0,
  497. .bNumEndpoints = 0,
  498. .bInterfaceClass = 0xFF,
  499. .bInterfaceSubClass = 0xFD,
  500. .bInterfaceProtocol = 0x13,
  501. .iInterface = 4,
  502. },
  503. .security_desc =
  504. {0x06, 0x41, 0x00, 0x01, 0x01, 0x03},
  505. };
  506. /* Control requests handler */
  507. static usbd_respond
  508. pof_hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  509. UNUSED(callback);
  510. uint8_t wValueH = req->wValue >> 8;
  511. uint8_t wValueL = req->wValue & 0xFF;
  512. uint16_t length = req->wLength;
  513. PoFUsb* pof_usb = pof_cur;
  514. /* HID control requests */
  515. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  516. (USB_REQ_INTERFACE | USB_REQ_CLASS) &&
  517. req->wIndex == 0) {
  518. switch(req->bRequest) {
  519. case USB_HID_SETIDLE:
  520. return usbd_ack;
  521. case USB_HID_SETPROTOCOL:
  522. return usbd_ack;
  523. case USB_HID_GETREPORT:
  524. dev->status.data_ptr = pof_usb->tx_data;
  525. dev->status.data_count = sizeof(pof_usb->tx_data);
  526. return usbd_ack;
  527. case USB_HID_SETREPORT:
  528. if(wValueH == HID_REPORT_TYPE_INPUT) {
  529. if(length == POF_USB_RX_MAX_SIZE) {
  530. return usbd_ack;
  531. }
  532. } else if(wValueH == HID_REPORT_TYPE_OUTPUT) {
  533. memcpy(pof_usb->data, req->data, req->wLength);
  534. pof_usb->dataAvailable += req->wLength;
  535. furi_thread_flags_set(furi_thread_get_id(pof_usb->thread), EventRx);
  536. return usbd_ack;
  537. } else if(wValueH == HID_REPORT_TYPE_FEATURE) {
  538. return usbd_ack;
  539. }
  540. return usbd_fail;
  541. default:
  542. return usbd_fail;
  543. }
  544. }
  545. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  546. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  547. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  548. switch(wValueH) {
  549. case USB_DTYPE_HID:
  550. dev->status.data_ptr = (uint8_t*)&(usb_pof_cfg_descr.hid_desc);
  551. dev->status.data_count = sizeof(usb_pof_cfg_descr.hid_desc);
  552. return usbd_ack;
  553. case USB_DTYPE_HID_REPORT:
  554. dev->status.data_ptr = (uint8_t*)hid_report_desc;
  555. dev->status.data_count = sizeof(hid_report_desc);
  556. return usbd_ack;
  557. case USB_DTYPE_STRING:
  558. if (wValueL == 4) {
  559. dev->status.data_ptr = (uint8_t*)&dev_security_desc;
  560. dev->status.data_count = sizeof(dev_security_desc);
  561. return usbd_ack;
  562. }
  563. return usbd_fail;
  564. default:
  565. return usbd_fail;
  566. }
  567. }
  568. return usbd_fail;
  569. }
  570. static usbd_respond
  571. pof_xbox_360_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
  572. UNUSED(callback);
  573. uint8_t wValueH = req->wValue >> 8;
  574. uint8_t wValueL = req->wValue & 0xFF;
  575. if(((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) ==
  576. (USB_REQ_INTERFACE | USB_REQ_STANDARD) &&
  577. req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  578. switch(wValueH) {
  579. case USB_DTYPE_STRING:
  580. if (wValueL == 4) {
  581. dev->status.data_ptr = (uint8_t*)&dev_security_desc;
  582. dev->status.data_count = sizeof(dev_security_desc);
  583. return usbd_ack;
  584. }
  585. return usbd_fail;
  586. default:
  587. return usbd_fail;
  588. }
  589. }
  590. return usbd_fail;
  591. }
  592. PoFUsb* pof_usb_start_xbox_360(VirtualPortal* virtual_portal) {
  593. PoFUsb* pof_usb = malloc(sizeof(PoFUsb));
  594. pof_usb->virtual_portal = virtual_portal;
  595. pof_usb->dataAvailable = 0;
  596. pof_usb->usb_prev = furi_hal_usb_get_config();
  597. pof_usb->usb.init = pof_usb_init_xbox_360;
  598. pof_usb->usb.deinit = pof_usb_deinit;
  599. pof_usb->usb.wakeup = pof_usb_wakeup;
  600. pof_usb->usb.suspend = pof_usb_suspend;
  601. pof_usb->usb.dev_descr = (struct usb_device_descriptor*)&usb_pof_dev_descr_xbox_360;
  602. pof_usb->usb.str_manuf_descr = (void*)&dev_manuf_desc;
  603. pof_usb->usb.str_prod_descr = (void*)&dev_product_desc;
  604. pof_usb->usb.str_serial_descr = NULL;
  605. pof_usb->usb.cfg_descr = (void*)&usb_pof_cfg_descr_x360;
  606. if(!furi_hal_usb_set_config(&pof_usb->usb, pof_usb)) {
  607. FURI_LOG_E(TAG, "USB locked, can not start");
  608. if(pof_usb->usb.str_manuf_descr) {
  609. free(pof_usb->usb.str_manuf_descr);
  610. }
  611. if(pof_usb->usb.str_prod_descr) {
  612. free(pof_usb->usb.str_prod_descr);
  613. }
  614. if(pof_usb->usb.str_serial_descr) {
  615. free(pof_usb->usb.str_serial_descr);
  616. }
  617. free(pof_usb);
  618. return NULL;
  619. }
  620. return pof_usb;
  621. }
  622. PoFUsb* pof_usb_start(VirtualPortal* virtual_portal) {
  623. PoFUsb* pof_usb = malloc(sizeof(PoFUsb));
  624. pof_usb->virtual_portal = virtual_portal;
  625. pof_usb->dataAvailable = 0;
  626. pof_usb->usb_prev = furi_hal_usb_get_config();
  627. pof_usb->usb.init = pof_usb_init;
  628. pof_usb->usb.deinit = pof_usb_deinit;
  629. pof_usb->usb.wakeup = pof_usb_wakeup;
  630. pof_usb->usb.suspend = pof_usb_suspend;
  631. pof_usb->usb.dev_descr = (struct usb_device_descriptor*)&usb_pof_dev_descr;
  632. pof_usb->usb.str_manuf_descr = (void*)&dev_manuf_desc;
  633. pof_usb->usb.str_prod_descr = (void*)&dev_product_desc;
  634. pof_usb->usb.str_serial_descr = NULL;
  635. pof_usb->usb.cfg_descr = (void*)&usb_pof_cfg_descr;
  636. if(!furi_hal_usb_set_config(&pof_usb->usb, pof_usb)) {
  637. FURI_LOG_E(TAG, "USB locked, can not start");
  638. if(pof_usb->usb.str_manuf_descr) {
  639. free(pof_usb->usb.str_manuf_descr);
  640. }
  641. if(pof_usb->usb.str_prod_descr) {
  642. free(pof_usb->usb.str_prod_descr);
  643. }
  644. if(pof_usb->usb.str_serial_descr) {
  645. free(pof_usb->usb.str_serial_descr);
  646. }
  647. free(pof_usb);
  648. pof_usb = NULL;
  649. return NULL;
  650. }
  651. return pof_usb;
  652. }
  653. void pof_usb_stop(PoFUsb* pof_usb) {
  654. if(pof_usb) {
  655. furi_hal_usb_set_config(pof_usb->usb_prev, NULL);
  656. }
  657. }