app_usbd_hid.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(APP_USBD_HID)
  42. #include "app_usbd.h"
  43. #include "app_usbd_core.h"
  44. #include "app_usbd_hid.h"
  45. #include "nrf_log.h"
  46. /**
  47. * @ingroup app_usbd_hid_internals USBD HID internals
  48. * @{
  49. * @ingroup app_usbd_hid
  50. * @internal
  51. */
  52. #define APP_USBD_HID_SOF_NOT_REQ_FLAG 0xFFFF
  53. /**
  54. * @brief Test whether SOF HID transfer is required.
  55. *
  56. * This function handles idle period IN transfer.
  57. *
  58. * @param[in,out] p_hid_ctx Internal HID context.
  59. * @param[in] framecnt SOF event frame counter.
  60. *
  61. * @retval report_id If transfer with ID required
  62. * @retval APP_USBD_HID_SOF_NOT_REQ_FLAG If no transfer required
  63. */
  64. static uint16_t hid_sof_required(app_usbd_hid_ctx_t * p_hid_ctx, uint16_t framecnt)
  65. {
  66. if (!p_hid_ctx->idle_on)
  67. {
  68. /* Infinite idle rate */
  69. return APP_USBD_HID_SOF_NOT_REQ_FLAG;
  70. }
  71. uint8_t i = 0;
  72. uint16_t rate_ms[APP_USBD_HID_REPORT_IDLE_TABLE_SIZE] = {0};
  73. for(i = 0; i < APP_USBD_HID_REPORT_IDLE_TABLE_SIZE; i++)
  74. {
  75. rate_ms[i] = p_hid_ctx->idle_rate[i] * 4;
  76. if((framecnt == APP_USBD_SOF_MAX) && (p_hid_ctx->first_idle[i] != (APP_USBD_SOF_MAX + 1)))
  77. {
  78. /* SOF has only 2047 frame count maximum - adjust m_first_idle */
  79. p_hid_ctx->first_idle[i] = ((p_hid_ctx->first_idle[i] + APP_USBD_SOF_MAX) % rate_ms[i]) + 1;
  80. }
  81. if (p_hid_ctx->access_lock)
  82. {
  83. /* Access to internal data locked. Buffer is BUSY.
  84. * Don't send anything. Clear transfer flag. Next transfer will be triggered
  85. * from API context.*/
  86. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_TRANS_IN_PROGRESS);
  87. return APP_USBD_HID_SOF_NOT_REQ_FLAG;
  88. }
  89. /* Idle transfer required if SOF is correct with an accuracy of +/-10% + 2ms*/
  90. if (((framecnt + p_hid_ctx->first_idle[i]) % rate_ms[i]) < (2 + (rate_ms[i] / 10)))
  91. {
  92. return i;
  93. }
  94. /* Only 0 id has set idle rate. No need to check whole table. */
  95. if(!p_hid_ctx->idle_id_report)
  96. {
  97. return APP_USBD_HID_SOF_NOT_REQ_FLAG;
  98. }
  99. }
  100. return APP_USBD_HID_SOF_NOT_REQ_FLAG;
  101. }
  102. /**
  103. * @brief User event handler.
  104. *
  105. * @param[in] p_inst Class instance.
  106. * @param[in] p_hinst HID class instance.
  107. * @param[in] event user Event type.
  108. */
  109. static inline void user_event_handler(app_usbd_class_inst_t const * p_inst,
  110. app_usbd_hid_inst_t const * p_hinst,
  111. app_usbd_hid_user_event_t event)
  112. {
  113. if (p_hinst->user_event_handler != NULL)
  114. {
  115. p_hinst->user_event_handler(p_inst, event);
  116. }
  117. }
  118. /**
  119. * @brief Internal SETUP standard IN request handler.
  120. *
  121. * @param[in] p_inst Generic class instance.
  122. * @param[in] p_hinst HID class instance.
  123. * @param[in,out] p_hid_ctx HID context.
  124. * @param[in] p_setup_ev Setup event.
  125. *
  126. * @return Standard error code.
  127. */
  128. static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst,
  129. app_usbd_hid_inst_t const * p_hinst,
  130. app_usbd_hid_ctx_t * p_hid_ctx,
  131. app_usbd_setup_evt_t const * p_setup_ev)
  132. {
  133. /* Only Get Descriptor standard IN request is supported by HID class */
  134. if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE)
  135. &&
  136. (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR))
  137. {
  138. size_t dsc_len = 0;
  139. size_t max_size;
  140. uint8_t descr_type = p_setup_ev->setup.wValue.hb;
  141. uint8_t descr_idx = p_setup_ev->setup.wValue.lb;
  142. uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size);
  143. /* Validation for Class Descriptors. Only HID and REPORT are supported */
  144. if ((descr_type < APP_USBD_HID_DESCRIPTOR_HID) || (descr_type >= APP_USBD_HID_DESCRIPTOR_PHYSICAL))
  145. {
  146. return NRF_ERROR_NOT_SUPPORTED;
  147. }
  148. /* Try to find descriptor in class internals*/
  149. ret_code_t ret = app_usbd_class_descriptor_find(
  150. p_inst,
  151. descr_type,
  152. descr_idx,
  153. p_trans_buff,
  154. &dsc_len);
  155. if (ret == NRF_SUCCESS)
  156. {
  157. ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE);
  158. return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len);
  159. }
  160. /* If not found try HID specific descriptors*/
  161. if (descr_idx >= p_hinst->p_hid_methods->subclass_count(p_inst) )
  162. {
  163. /* requested index out of range */
  164. return NRF_ERROR_NOT_SUPPORTED;
  165. }
  166. else
  167. {
  168. uint32_t report_size =
  169. p_hinst->p_hid_methods->subclass_length(p_inst, descr_idx);
  170. const uint8_t * p_first_byte =
  171. p_hinst->p_hid_methods->subclass_data(p_inst, descr_idx, 0);
  172. return app_usbd_core_setup_rsp(&p_setup_ev->setup, p_first_byte, report_size);
  173. }
  174. }
  175. return NRF_ERROR_NOT_SUPPORTED;
  176. }
  177. /**
  178. * @brief Internal SETUP standard OUT request handler.
  179. *
  180. * @param[in] p_inst Generic class instance.
  181. * @param[in] p_hinst HID class instance.
  182. * @param[in,out] p_hid_ctx HID context.
  183. * @param[in] p_setup_ev Setup event.
  184. *
  185. * @return Standard error code.
  186. */
  187. static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst,
  188. app_usbd_hid_inst_t const * p_hinst,
  189. app_usbd_hid_ctx_t * p_hid_ctx,
  190. app_usbd_setup_evt_t const * p_setup_ev)
  191. {
  192. /*Only Set Descriptor standard OUT request is supported by HID class. However, it is optional
  193. * and useless in HID cases.*/
  194. return NRF_ERROR_NOT_SUPPORTED;
  195. }
  196. /**
  197. * @brief Internal SETUP class IN request handler.
  198. *
  199. * @param[in] p_inst Generic class instance.
  200. * @param[in] p_hinst HID class instance.
  201. * @param[in,out] p_hid_ctx HID context.
  202. * @param[in] p_setup_ev Setup event.
  203. *
  204. * @return Standard error code.
  205. */
  206. static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst,
  207. app_usbd_hid_inst_t const * p_hinst,
  208. app_usbd_hid_ctx_t * p_hid_ctx,
  209. app_usbd_setup_evt_t const * p_setup_ev)
  210. {
  211. switch (p_setup_ev->setup.bRequest)
  212. {
  213. case APP_USBD_HID_REQ_GET_REPORT:
  214. {
  215. if ((p_setup_ev->setup.wValue.hb == APP_USBD_HID_REPORT_TYPE_INPUT) ||
  216. (p_setup_ev->setup.wValue.hb == APP_USBD_HID_REPORT_TYPE_OUTPUT) ||
  217. (p_setup_ev->setup.wValue.hb == APP_USBD_HID_REPORT_TYPE_FEATURE))
  218. {
  219. return p_hinst->p_hid_methods->on_get_report(p_inst, p_setup_ev);
  220. }
  221. else
  222. {
  223. break;
  224. }
  225. }
  226. case APP_USBD_HID_REQ_GET_IDLE:
  227. {
  228. return app_usbd_core_setup_rsp(&p_setup_ev->setup,
  229. &p_hid_ctx->idle_rate[p_setup_ev->setup.wValue.lb],
  230. sizeof(p_hid_ctx->idle_rate[p_setup_ev->setup.wValue.lb]));
  231. }
  232. case APP_USBD_HID_REQ_GET_PROTOCOL:
  233. {
  234. return app_usbd_core_setup_rsp(&p_setup_ev->setup,
  235. &p_hid_ctx->selected_protocol,
  236. sizeof(p_hid_ctx->selected_protocol));
  237. }
  238. default:
  239. break;
  240. }
  241. return NRF_ERROR_NOT_SUPPORTED;
  242. }
  243. /**
  244. * @brief Internal SETUP class OUT request handler.
  245. *
  246. * @param[in] p_inst Generic class instance.
  247. * @param[in] p_hinst HID class instance.
  248. * @param[in,out] p_hid_ctx HID context.
  249. * @param[in] p_setup_ev Setup event.
  250. *
  251. * @return Standard error code.
  252. */
  253. static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst,
  254. app_usbd_hid_inst_t const * p_hinst,
  255. app_usbd_hid_ctx_t * p_hid_ctx,
  256. app_usbd_setup_evt_t const * p_setup_ev)
  257. {
  258. switch (p_setup_ev->setup.bRequest)
  259. {
  260. case APP_USBD_HID_REQ_SET_REPORT:
  261. if (((p_setup_ev->setup.wValue.hb != APP_USBD_HID_REPORT_TYPE_OUTPUT) &&
  262. (p_setup_ev->setup.wValue.hb != APP_USBD_HID_REPORT_TYPE_FEATURE)) ||
  263. p_hinst->p_hid_methods->on_set_report == NULL)
  264. {
  265. break;
  266. }
  267. return p_hinst->p_hid_methods->on_set_report(p_inst, p_setup_ev);
  268. case APP_USBD_HID_REQ_SET_IDLE:
  269. {
  270. p_hid_ctx->idle_rate[p_setup_ev->setup.wValue.lb] = p_setup_ev->setup.wValue.hb;
  271. p_hid_ctx->first_idle[p_setup_ev->setup.wValue.lb] = APP_USBD_SOF_MAX + 1;
  272. /* Clear idle, high byte is interval. */
  273. if(p_setup_ev->setup.wValue.hb == 0)
  274. {
  275. /* Set global idle flags according to values in channels.
  276. If only idle rate with id 0 is non 0 set idle_id_report to false. */
  277. bool clear = true;
  278. uint8_t i = 0;
  279. /* Loop starts at 1 to skip the "global" channel 0. */
  280. for(i=1; i < APP_USBD_HID_REPORT_IDLE_TABLE_SIZE; i++)
  281. {
  282. if(p_hid_ctx->idle_rate[i] != 0)
  283. {
  284. clear = false;
  285. break;
  286. }
  287. }
  288. /* If all channels 1..N have frequency 0 then switch off global handling of idle. */
  289. if(clear)
  290. {
  291. /* Distinguish between "report-specific" reports and "global" flag. */
  292. p_hid_ctx->idle_id_report = false;
  293. if(p_hid_ctx->idle_rate[0] == 0)
  294. {
  295. /* If all are 0 set m_idle_on to false. */
  296. p_hid_ctx->idle_on = false;
  297. }
  298. }
  299. }
  300. /* Set idle because Interval was != 0 */
  301. else
  302. {
  303. /* If any idle rate is not 0 set m_idle_on to true. */
  304. p_hid_ctx->idle_on = true;
  305. /* If any idle rate with id != 0 is non 0 set idle_id_report to true. */
  306. if(p_setup_ev->setup.wValue.lb != 0)
  307. {
  308. /* Separate handling when only a single report is used. */
  309. p_hid_ctx->idle_id_report = true;
  310. }
  311. }
  312. return NRF_SUCCESS;
  313. }
  314. case APP_USBD_HID_REQ_SET_PROTOCOL:
  315. {
  316. app_usbd_hid_user_event_t ev = (p_setup_ev->setup.wValue.w == APP_USBD_HID_PROTO_BOOT) ?
  317. APP_USBD_HID_USER_EVT_SET_BOOT_PROTO :
  318. APP_USBD_HID_USER_EVT_SET_REPORT_PROTO;
  319. if (ev == APP_USBD_HID_USER_EVT_SET_BOOT_PROTO)
  320. {
  321. p_hid_ctx->selected_protocol = APP_USBD_HID_PROTO_BOOT;
  322. }
  323. else if (ev == APP_USBD_HID_USER_EVT_SET_REPORT_PROTO)
  324. {
  325. p_hid_ctx->selected_protocol = APP_USBD_HID_PROTO_REPORT;
  326. }
  327. else
  328. {
  329. return NRF_ERROR_INVALID_PARAM;
  330. }
  331. user_event_handler(p_inst, p_hinst, ev);
  332. }
  333. return NRF_SUCCESS;
  334. default:
  335. break;
  336. }
  337. return NRF_ERROR_NOT_SUPPORTED;
  338. }
  339. /**
  340. * @brief Internal SETUP event handler.
  341. *
  342. * @param[in] p_inst Generic class instance.
  343. * @param[in] p_hinst HID class instance.
  344. * @param[in,out] p_hid_ctx HID context.
  345. * @param[in] p_setup_ev Setup event.
  346. *
  347. * @return Standard error code.
  348. */
  349. static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst,
  350. app_usbd_hid_inst_t const * p_hinst,
  351. app_usbd_hid_ctx_t * p_hid_ctx,
  352. app_usbd_setup_evt_t const * p_setup_ev)
  353. {
  354. ASSERT(p_hinst != NULL);
  355. ASSERT(p_hid_ctx != NULL);
  356. ASSERT(p_setup_ev != NULL);
  357. if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN)
  358. {
  359. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  360. {
  361. case APP_USBD_SETUP_REQTYPE_STD:
  362. return setup_req_std_in(p_inst, p_hinst, p_hid_ctx, p_setup_ev);
  363. case APP_USBD_SETUP_REQTYPE_CLASS:
  364. return setup_req_class_in(p_inst, p_hinst, p_hid_ctx, p_setup_ev);
  365. default:
  366. break;
  367. }
  368. }
  369. else /*APP_USBD_SETUP_REQDIR_OUT*/
  370. {
  371. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  372. {
  373. case APP_USBD_SETUP_REQTYPE_STD:
  374. return setup_req_std_out(p_inst, p_hinst, p_hid_ctx, p_setup_ev);
  375. case APP_USBD_SETUP_REQTYPE_CLASS:
  376. return setup_req_class_out(p_inst, p_hinst, p_hid_ctx, p_setup_ev);
  377. default:
  378. break;
  379. }
  380. }
  381. return NRF_ERROR_NOT_SUPPORTED;
  382. }
  383. /**
  384. * @brief Endpoint IN event handler.
  385. *
  386. * @param[in] p_inst Generic class instance.
  387. * @param[in] p_hinst HID class instance.
  388. * @param[in,out] p_hid_ctx HID context.
  389. * @param[in] p_setup_ev Setup event.
  390. *
  391. * @return Standard error code.
  392. */
  393. static ret_code_t endpoint_in_event_handler(app_usbd_class_inst_t const * p_inst,
  394. app_usbd_hid_inst_t const * p_hinst,
  395. app_usbd_hid_ctx_t * p_hid_ctx,
  396. app_usbd_complex_evt_t const * p_event)
  397. {
  398. if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_OK)
  399. {
  400. /* Notify user about last successful transfer. */
  401. user_event_handler(p_inst, p_hinst, APP_USBD_HID_USER_EVT_IN_REPORT_DONE);
  402. }
  403. if (app_usbd_hid_access_lock_test(p_hid_ctx))
  404. {
  405. /* Access to internal data locked. Buffer is BUSY.
  406. * Don't send anything. Clear transfer flag. Next transfer will be triggered
  407. * from main loop context. */
  408. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_TRANS_IN_PROGRESS);
  409. return NRF_SUCCESS;
  410. }
  411. {
  412. uint8_t i = 0;
  413. for(i=0; i < APP_USBD_HID_REPORT_IDLE_TABLE_SIZE; i++)
  414. {
  415. if (p_hid_ctx->first_idle[i] == (APP_USBD_SOF_MAX + 1))
  416. {
  417. p_hid_ctx->lock_idle[i] = true;
  418. }
  419. /* Only 0 id has set idle rate. No need to check whole table. */
  420. if(!p_hid_ctx->idle_id_report)
  421. {
  422. break;
  423. }
  424. }
  425. }
  426. /* HID 1.11 specification states that in case the report has changed,
  427. it should be transfered immediately even when idle is enabled. */
  428. return p_hinst->p_hid_methods->ep_transfer_in(p_inst);
  429. }
  430. /**
  431. * @brief Endpoint OUT event handler.
  432. *
  433. * @param[in] p_inst Generic class instance.
  434. * @param[in] p_hinst HID class instance.
  435. * @param[in,out] p_hid_ctx HID context.
  436. * @param[in] p_setup_ev Setup event.
  437. *
  438. * @return Standard error code.
  439. */
  440. static ret_code_t endpoint_out_event_handler(app_usbd_class_inst_t const * p_inst,
  441. app_usbd_hid_inst_t const * p_hinst,
  442. app_usbd_hid_ctx_t * p_hid_ctx,
  443. app_usbd_complex_evt_t const * p_event)
  444. {
  445. if (p_hinst->p_hid_methods->ep_transfer_out == NULL)
  446. {
  447. return NRF_ERROR_NOT_SUPPORTED;
  448. }
  449. if (p_event->drv_evt.data.eptransfer.status == NRF_USBD_EP_OK)
  450. {
  451. /* Notify user about last successful transfer. */
  452. user_event_handler(p_inst, p_hinst, APP_USBD_HID_USER_EVT_OUT_REPORT_READY);
  453. }
  454. ASSERT(p_hinst->p_rep_buffer_out->size <= NRF_DRV_USBD_EPSIZE);
  455. return p_hinst->p_hid_methods->ep_transfer_out(p_inst);
  456. }
  457. static void app_usbd_clear_idle_ctx(app_usbd_hid_ctx_t * p_hid_ctx)
  458. {
  459. uint8_t i = 0;
  460. for(i=0; i < APP_USBD_HID_REPORT_IDLE_TABLE_SIZE; i++)
  461. {
  462. p_hid_ctx->idle_rate[i] = APP_USBD_HID_DEFAULT_IDLE_RATE;
  463. p_hid_ctx->first_idle[i] = APP_USBD_SOF_MAX + 1;
  464. }
  465. p_hid_ctx->idle_id_report = false;
  466. p_hid_ctx->idle_on = false;
  467. }
  468. /** @} */
  469. ret_code_t app_usbd_hid_event_handler(app_usbd_class_inst_t const * p_inst,
  470. app_usbd_hid_inst_t const * p_hinst,
  471. app_usbd_hid_ctx_t * p_hid_ctx,
  472. app_usbd_complex_evt_t const * p_event)
  473. {
  474. ret_code_t ret = NRF_SUCCESS;
  475. switch (p_event->app_evt.type)
  476. {
  477. case APP_USBD_EVT_DRV_SOF:
  478. {
  479. uint16_t sof_req = hid_sof_required(p_hid_ctx, p_event->drv_evt.data.sof.framecnt);
  480. if (sof_req != APP_USBD_HID_SOF_NOT_REQ_FLAG)
  481. {
  482. uint8_t i = 0;
  483. for(i=0; i < APP_USBD_HID_REPORT_IDLE_TABLE_SIZE; i++)
  484. {
  485. if(p_hid_ctx->lock_idle[i])
  486. {
  487. p_hid_ctx->first_idle[i] = p_event->drv_evt.data.sof.framecnt;
  488. p_hid_ctx->lock_idle[i] = false;
  489. }
  490. /* Only 0 id has set idle rate. No need to check whole table. */
  491. if(!p_hid_ctx->idle_id_report)
  492. {
  493. break;
  494. }
  495. }
  496. ret = p_hinst->p_hid_methods->on_idle(p_inst, sof_req);
  497. }
  498. break;
  499. }
  500. case APP_USBD_EVT_DRV_RESET:
  501. {
  502. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_TRANS_IN_PROGRESS);
  503. p_hid_ctx->selected_protocol = APP_USBD_HID_PROTO_REPORT;
  504. app_usbd_clear_idle_ctx(p_hid_ctx);
  505. break;
  506. }
  507. case APP_USBD_EVT_DRV_SETUP:
  508. ret = setup_event_handler(p_inst, p_hinst, p_hid_ctx, &p_event->setup_evt);
  509. break;
  510. case APP_USBD_EVT_DRV_EPTRANSFER:
  511. if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep))
  512. {
  513. ret = endpoint_in_event_handler(p_inst, p_hinst, p_hid_ctx, p_event);
  514. }
  515. else
  516. {
  517. ret = endpoint_out_event_handler(p_inst, p_hinst, p_hid_ctx, p_event);
  518. }
  519. break;
  520. case APP_USBD_EVT_DRV_SUSPEND:
  521. app_usbd_hid_state_flag_set(p_hid_ctx, APP_USBD_HID_STATE_FLAG_SUSPENDED);
  522. break;
  523. case APP_USBD_EVT_DRV_RESUME:
  524. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_SUSPENDED);
  525. /* Always try to trigger transfer on resume event*/
  526. ret = p_hinst->p_hid_methods->ep_transfer_in(p_inst);
  527. break;
  528. case APP_USBD_EVT_INST_APPEND:
  529. /*SOF register: GetIdle/SetIdle support*/
  530. ret = app_usbd_class_sof_register(p_inst);
  531. if (ret != NRF_SUCCESS)
  532. {
  533. break;
  534. }
  535. ret = app_usbd_class_rwu_register(p_inst);
  536. if (ret != NRF_SUCCESS)
  537. {
  538. break;
  539. }
  540. app_usbd_clear_idle_ctx(p_hid_ctx);
  541. app_usbd_hid_state_flag_set(p_hid_ctx, APP_USBD_HID_STATE_FLAG_APPENDED);
  542. break;
  543. case APP_USBD_EVT_INST_REMOVE:
  544. /*SOF unregister: GetIdle/SetIdle support*/
  545. ret = app_usbd_class_sof_unregister(p_inst);
  546. if (ret != NRF_SUCCESS)
  547. {
  548. break;
  549. }
  550. ret = app_usbd_class_rwu_unregister(p_inst);
  551. if (ret != NRF_SUCCESS)
  552. {
  553. break;
  554. }
  555. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_APPENDED);
  556. break;
  557. case APP_USBD_EVT_STARTED:
  558. app_usbd_hid_state_flag_set(p_hid_ctx, APP_USBD_HID_STATE_FLAG_STARTED);
  559. break;
  560. case APP_USBD_EVT_STOPPED:
  561. app_usbd_hid_state_flag_clr(p_hid_ctx, APP_USBD_HID_STATE_FLAG_STARTED);
  562. break;
  563. default:
  564. ret = NRF_ERROR_NOT_SUPPORTED;
  565. break;
  566. }
  567. return ret;
  568. }
  569. app_usbd_hid_report_buffer_t * app_usbd_hid_rep_buff_in_get(app_usbd_hid_inst_t const * p_hinst)
  570. {
  571. ASSERT(p_hinst);
  572. return p_hinst->p_rep_buffer_in;
  573. }
  574. app_usbd_hid_report_buffer_t const * app_usbd_hid_rep_buff_feature_get(app_usbd_hid_inst_t const * p_hinst)
  575. {
  576. ASSERT(p_hinst);
  577. return p_hinst->p_rep_buffer_feature;
  578. }
  579. #endif //NRF_MODULE_ENABLED(APP_USBD_HID)