input.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-3-08 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #define DBG_TAG "rtdm.input"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. static RT_DEFINE_SPINLOCK(input_device_lock);
  17. static rt_list_t input_device_nodes = RT_LIST_OBJECT_INIT(input_device_nodes);
  18. static struct rt_dm_ida input_ida = RT_DM_IDA_INIT(INPUT);
  19. #ifdef RT_INPUT_TOUCHSCREEN
  20. extern void input_touch_register(struct rt_input_device *idev);
  21. extern void input_touch_unregister(struct rt_input_device *idev);
  22. #endif
  23. #ifdef RT_INPUT_UAPI
  24. extern void input_uapi_init(struct rt_input_device *idev);
  25. extern void input_uapi_finit(struct rt_input_device *idev);
  26. extern void input_uapi_event(struct rt_input_device *idev, struct rt_input_event *event);
  27. #endif
  28. #ifdef RT_USING_DEVICE_OPS
  29. const static struct rt_device_ops _input_ops =
  30. {
  31. };
  32. #endif
  33. rt_err_t rt_input_device_register(struct rt_input_device *idev)
  34. {
  35. rt_err_t err;
  36. int device_id;
  37. const char *dev_name;
  38. if (!idev)
  39. {
  40. return -RT_EINVAL;
  41. }
  42. if ((device_id = rt_dm_ida_alloc(&input_ida)) < 0)
  43. {
  44. err = -RT_EFULL;
  45. goto _remove_config;
  46. }
  47. rt_dm_dev_set_name(&idev->parent, "input%u", device_id);
  48. dev_name = rt_dm_dev_get_name(&idev->parent);
  49. rt_list_init(&idev->list);
  50. rt_list_init(&idev->handler_nodes);
  51. rt_spin_lock_init(&idev->lock);
  52. /* Just make a search interface */
  53. idev->parent.type = RT_Device_Class_Char;
  54. #ifdef RT_USING_DEVICE_OPS
  55. idev->parent.ops = idev->parent.ops ? : &_input_ops;
  56. #endif
  57. idev->parent.master_id = input_ida.master_id;
  58. idev->parent.device_id = device_id;
  59. if ((err = rt_device_register(&idev->parent, dev_name, RT_DEVICE_FLAG_DEACTIVATE)))
  60. {
  61. goto _fail;
  62. }
  63. #ifdef RT_INPUT_UAPI
  64. input_uapi_init(idev);
  65. #endif
  66. rt_spin_lock(&input_device_lock);
  67. rt_list_insert_before(&input_device_nodes, &idev->list);
  68. rt_spin_unlock(&input_device_lock);
  69. #ifdef RT_INPUT_TOUCHSCREEN
  70. /* MUST be registered after the list is inserted */
  71. input_touch_register(idev);
  72. #endif
  73. if (idev->poller)
  74. {
  75. rt_timer_start(&idev->poller->timer);
  76. }
  77. return RT_EOK;
  78. _fail:
  79. rt_dm_ida_free(&input_ida, device_id);
  80. _remove_config:
  81. rt_input_remove_config(idev);
  82. return err;
  83. }
  84. rt_err_t rt_input_device_unregister(struct rt_input_device *idev)
  85. {
  86. const char *dev_name;
  87. if (!idev)
  88. {
  89. return -RT_EINVAL;
  90. }
  91. dev_name = rt_dm_dev_get_name(&idev->parent);
  92. if (idev->parent.ref_count)
  93. {
  94. LOG_E("%s: there is %u user", dev_name, idev->parent.ref_count);
  95. return -RT_EINVAL;
  96. }
  97. #ifdef RT_INPUT_UAPI
  98. input_uapi_finit(idev);
  99. #endif
  100. #ifdef RT_INPUT_TOUCHSCREEN
  101. input_touch_unregister(idev);
  102. #endif
  103. rt_input_remove_config(idev);
  104. rt_dm_ida_free(&input_ida, idev->parent.device_id);
  105. rt_device_unregister(&idev->parent);
  106. rt_spin_lock(&input_device_lock);
  107. rt_list_remove(&idev->list);
  108. rt_spin_unlock(&input_device_lock);
  109. return RT_EOK;
  110. }
  111. rt_err_t rt_input_set_capability(struct rt_input_device *idev,
  112. rt_uint16_t type, rt_uint16_t code)
  113. {
  114. if (!idev)
  115. {
  116. return -RT_EINVAL;
  117. }
  118. switch (type)
  119. {
  120. case EV_KEY:
  121. rt_bitmap_set_bit(idev->key_map, code);
  122. break;
  123. case EV_REL:
  124. rt_bitmap_set_bit(idev->rel_map, code);
  125. break;
  126. case EV_ABS:
  127. if (!idev->absinfo)
  128. {
  129. idev->absinfo = rt_calloc(ABS_CNT, sizeof(*idev->absinfo));
  130. if (!idev->absinfo)
  131. {
  132. return -RT_ENOMEM;
  133. }
  134. }
  135. rt_bitmap_set_bit(idev->abs_map, code);
  136. break;
  137. case EV_MSC:
  138. case EV_SW:
  139. case EV_LED:
  140. case EV_SND:
  141. case EV_REP:
  142. case EV_FF:
  143. case EV_PWR:
  144. case EV_FF_STATUS:
  145. return -RT_ENOSYS;
  146. default:
  147. return -RT_EINVAL;
  148. }
  149. rt_bitmap_set_bit(idev->cap, type);
  150. return RT_EOK;
  151. }
  152. rt_err_t rt_input_set_absinfo(struct rt_input_device *idev, rt_uint32_t axis,
  153. rt_int32_t min, rt_int32_t max, rt_int32_t fuzz, rt_int32_t flat)
  154. {
  155. struct rt_input_absinfo *absinfo;
  156. if (!idev || !idev->absinfo)
  157. {
  158. return -RT_EINVAL;
  159. }
  160. rt_bitmap_set_bit(idev->abs_map, axis);
  161. absinfo = &idev->absinfo[axis];
  162. absinfo->minimum = min;
  163. absinfo->maximum = max;
  164. absinfo->fuzz = fuzz;
  165. absinfo->flat = flat;
  166. return RT_EOK;
  167. }
  168. static void input_poll(void *param)
  169. {
  170. struct rt_input_device *idev = param;
  171. idev->poller->poll(idev);
  172. }
  173. rt_err_t rt_input_setup_polling(struct rt_input_device *idev,
  174. void (*poll)(struct rt_input_device *idev))
  175. {
  176. const char *dev_name;
  177. if (!idev || !poll)
  178. {
  179. return -RT_EINVAL;
  180. }
  181. dev_name = rt_dm_dev_get_name(&idev->parent);
  182. idev->poller = rt_malloc(sizeof(*idev->poller));
  183. if (!idev->poller)
  184. {
  185. return -RT_ENOMEM;
  186. }
  187. idev->poller->poll = poll;
  188. rt_timer_init(&idev->poller->timer, dev_name, input_poll, idev,
  189. rt_tick_from_millisecond(RT_INPUT_POLL_INTERVAL_DEFAULT),
  190. RT_TIMER_FLAG_PERIODIC);
  191. return RT_EOK;
  192. }
  193. void rt_input_remove_config(struct rt_input_device *idev)
  194. {
  195. if (!idev)
  196. {
  197. return;
  198. }
  199. if (idev->poller)
  200. {
  201. rt_timer_stop(&idev->poller->timer);
  202. rt_timer_detach(&idev->poller->timer);
  203. rt_free(idev->poller);
  204. idev->poller = RT_NULL;
  205. }
  206. if (idev->absinfo)
  207. {
  208. rt_free(idev->absinfo);
  209. idev->absinfo = RT_NULL;
  210. }
  211. #ifdef RT_INPUT_TOUCHSCREEN
  212. if (idev->touch)
  213. {
  214. rt_free(idev->touch);
  215. idev->touch = RT_NULL;
  216. }
  217. #endif /* RT_INPUT_TOUCHSCREEN */
  218. }
  219. rt_err_t rt_input_set_poll_interval(struct rt_input_device *idev,
  220. rt_uint32_t interval_ms)
  221. {
  222. rt_tick_t tick;
  223. if (!idev || !idev->poller)
  224. {
  225. return -RT_EINVAL;
  226. }
  227. tick = rt_tick_from_millisecond(interval_ms);
  228. return rt_timer_control(&idev->poller->timer, RT_TIMER_CTRL_SET_TIME, &tick);
  229. }
  230. rt_err_t rt_input_trigger(struct rt_input_device *idev,
  231. rt_uint16_t type, rt_uint16_t code, rt_int32_t value)
  232. {
  233. RT_ASSERT(idev != RT_NULL);
  234. if (idev->trigger)
  235. {
  236. return idev->trigger(idev, type, code, value);
  237. }
  238. return -RT_ENOSYS;
  239. }
  240. void rt_input_event(struct rt_input_device *idev,
  241. rt_uint16_t type, rt_uint16_t code, rt_int32_t value)
  242. {
  243. struct rt_input_event event;
  244. struct rt_input_handler *handler, *handler_next;
  245. RT_ASSERT(idev != RT_NULL);
  246. RT_ASSERT(type < EV_MAX);
  247. event.tick = rt_tick_get();
  248. event.type = type;
  249. event.code = code;
  250. event.value = value;
  251. rt_spin_lock(&idev->lock);
  252. #ifdef RT_INPUT_UAPI
  253. input_uapi_event(idev, &event);
  254. #endif
  255. rt_list_for_each_entry_safe(handler, handler_next, &idev->handler_nodes, list)
  256. {
  257. if (handler->callback(handler, &event))
  258. {
  259. break;
  260. }
  261. }
  262. rt_spin_unlock(&idev->lock);
  263. }
  264. rt_err_t rt_input_add_handler(struct rt_input_handler *handler)
  265. {
  266. struct rt_input_device *idev = RT_NULL, *idev_tmp;
  267. if (!handler || !handler->callback)
  268. {
  269. return -RT_EINVAL;
  270. }
  271. if (!handler->idev && !handler->identify)
  272. {
  273. return -RT_EINVAL;
  274. }
  275. rt_spin_lock(&input_device_lock);
  276. rt_list_for_each_entry(idev_tmp, &input_device_nodes, list)
  277. {
  278. if (handler->idev)
  279. {
  280. if (handler->idev == idev_tmp)
  281. {
  282. idev = idev_tmp;
  283. break;
  284. }
  285. }
  286. else if (handler->identify(handler, idev_tmp))
  287. {
  288. idev = idev_tmp;
  289. break;
  290. }
  291. }
  292. rt_spin_unlock(&input_device_lock);
  293. if (!idev)
  294. {
  295. return -RT_ENOSYS;
  296. }
  297. handler->idev = idev;
  298. rt_list_init(&handler->list);
  299. rt_spin_lock(&idev->lock);
  300. rt_list_insert_before(&idev->handler_nodes, &handler->list);
  301. rt_spin_unlock(&idev->lock);
  302. return RT_EOK;
  303. }
  304. rt_err_t rt_input_del_handler(struct rt_input_handler *handler)
  305. {
  306. struct rt_input_device *idev;
  307. if (!handler)
  308. {
  309. return -RT_EINVAL;
  310. }
  311. idev = handler->idev;
  312. rt_spin_lock(&idev->lock);
  313. rt_list_remove(&handler->list);
  314. rt_spin_unlock(&idev->lock);
  315. return RT_EOK;
  316. }