virtio_input.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-11-11 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <cpuport.h>
  13. #ifdef RT_USING_VIRTIO_INPUT
  14. #include <virtio_input.h>
  15. static void _set_bit(rt_uint32_t nr, volatile rt_ubase_t *addr)
  16. {
  17. rt_ubase_t mask = BIT_MASK(nr);
  18. rt_ubase_t *p = ((rt_ubase_t *)addr) + BIT_WORD(nr);
  19. *p |= mask;
  20. }
  21. static rt_ssize_t virtio_input_cfg_select(struct virtio_input_device *virtio_input_dev,
  22. rt_uint8_t select, rt_uint8_t subsel)
  23. {
  24. struct virtio_input_config *config = virtio_input_dev->config;
  25. rt_hw_dsb();
  26. config->select = select;
  27. config->subsel = subsel;
  28. rt_hw_dsb();
  29. return config->size;
  30. }
  31. static void virtio_input_cfg_bits(struct virtio_input_device *virtio_input_dev,
  32. rt_uint8_t select, rt_uint8_t subsel, rt_ubase_t *bits, rt_uint32_t bitcount)
  33. {
  34. int i;
  35. rt_uint32_t bit;
  36. rt_uint8_t bytes;
  37. rt_uint8_t *virtio_bits;
  38. void *config_base = virtio_input_dev->config;
  39. rt_off_t offset = (rt_size_t)&((struct virtio_input_config *)0)->bitmap;
  40. bytes = virtio_input_cfg_select(virtio_input_dev, select, subsel);
  41. if (bytes == 0)
  42. {
  43. return;
  44. }
  45. if (bitcount > bytes * 8)
  46. {
  47. bitcount = bytes * 8;
  48. }
  49. /*
  50. * Bitmap in virtio config space is a simple stream of bytes,
  51. * with the first byte carrying bits 0-7, second bits 8-15 and
  52. * so on.
  53. */
  54. virtio_bits = rt_malloc(bytes);
  55. if (virtio_bits == RT_NULL)
  56. {
  57. return;
  58. }
  59. for (i = 0; i < bytes; ++i)
  60. {
  61. void *buffer = (void *)virtio_bits + i;
  62. if (virtio_input_dev->virtio_dev.mmio_config->version == 1)
  63. {
  64. HWREG8(config_base + offset + i) = *((rt_uint8_t *)buffer);
  65. }
  66. else
  67. {
  68. rt_memcpy(config_base + offset + i, buffer, sizeof(rt_uint8_t));
  69. }
  70. }
  71. for (bit = 0; bit < bitcount; ++bit)
  72. {
  73. if (virtio_bits[bit / 8] & (1 << (bit % 8)))
  74. {
  75. _set_bit(bit, bits);
  76. }
  77. }
  78. rt_free(virtio_bits);
  79. if (select == VIRTIO_INPUT_CFG_EV_BITS)
  80. {
  81. _set_bit(subsel, virtio_input_dev->ev_bit);
  82. }
  83. }
  84. static rt_err_t virtio_input_init(rt_device_t dev)
  85. {
  86. int i;
  87. rt_uint16_t idx[VIRTIO_INPUT_QUEUE_MAX_SIZE];
  88. struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
  89. struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
  90. struct virtq *queue_event, *queue_status;
  91. virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_KEY, virtio_input_dev->key_bit, KEY_CNT);
  92. virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_REL, virtio_input_dev->rel_bit, REL_CNT);
  93. virtio_input_cfg_bits(virtio_input_dev, VIRTIO_INPUT_CFG_EV_BITS, EV_ABS, virtio_input_dev->abs_bit, ABS_CNT);
  94. queue_event = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_EVENT];
  95. queue_status = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_STATUS];
  96. virtio_alloc_desc_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, queue_event->num, idx);
  97. virtio_alloc_desc_chain(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, queue_status->num, idx);
  98. for (i = 0; i < queue_event->num; ++i)
  99. {
  100. rt_uint16_t id = i;
  101. void *addr = &virtio_input_dev->recv_events[i];
  102. virtio_fill_desc(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id,
  103. VIRTIO_VA2PA(addr), sizeof(struct virtio_input_event), VIRTQ_DESC_F_WRITE, 0);
  104. virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id);
  105. }
  106. rt_hw_dsb();
  107. queue_event->avail->flags = 0;
  108. queue_status->avail->flags = VIRTQ_AVAIL_F_NO_INTERRUPT;
  109. virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
  110. return RT_EOK;
  111. }
  112. static rt_ssize_t virtio_input_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  113. {
  114. struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
  115. if (buffer == RT_NULL || pos + size >= virtio_input_dev->virtio_dev.queues[VIRTIO_INPUT_QUEUE_EVENT].num)
  116. {
  117. return 0;
  118. }
  119. rt_mutex_take(&virtio_input_dev->rw_mutex, RT_WAITING_FOREVER);
  120. rt_memcpy(buffer, &virtio_input_dev->bcst_events[pos], size);
  121. rt_mutex_release(&virtio_input_dev->rw_mutex);
  122. return size;
  123. }
  124. static rt_ssize_t virtio_input_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  125. {
  126. struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
  127. if (buffer == RT_NULL || pos + size >= virtio_input_dev->virtio_dev.queues[VIRTIO_INPUT_QUEUE_EVENT].num)
  128. {
  129. return 0;
  130. }
  131. rt_mutex_take(&virtio_input_dev->rw_mutex, RT_WAITING_FOREVER);
  132. rt_memcpy(&virtio_input_dev->bcst_events[pos], buffer, size);
  133. rt_mutex_release(&virtio_input_dev->rw_mutex);
  134. return size;
  135. }
  136. static rt_err_t virtio_input_control(rt_device_t dev, int cmd, void *args)
  137. {
  138. rt_err_t status = RT_EOK;
  139. struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)dev;
  140. struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
  141. struct virtio_input_config *config = virtio_input_dev->config;
  142. if (args == RT_NULL)
  143. {
  144. return -RT_ERROR;
  145. }
  146. switch (cmd)
  147. {
  148. case VIRTIO_DEVICE_CTRL_INPUT_GET_TYPE:
  149. *(enum virtio_input_type *)args = virtio_input_dev->type;
  150. break;
  151. case VIRTIO_DEVICE_CTRL_INPUT_BIND_BSCT_HANDLER:
  152. virtio_input_dev->bsct_handler = args;
  153. break;
  154. case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_X_INFO:
  155. virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_ABS_AXIS_X);
  156. rt_memcpy(args, config, sizeof(struct virtio_input_config));
  157. break;
  158. case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_Y_INFO:
  159. virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_ABS_AXIS_Y);
  160. rt_memcpy(args, config, sizeof(struct virtio_input_config));
  161. break;
  162. case VIRTIO_DEVICE_CTRL_INPUT_SET_STATUS:
  163. {
  164. rt_uint16_t id;
  165. void *addr;
  166. struct virtq *queue_status = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_STATUS];
  167. #ifdef RT_USING_SMP
  168. rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
  169. #endif
  170. id = queue_status->avail->idx % queue_status->num;
  171. addr = &virtio_input_dev->xmit_events[id];
  172. rt_memcpy(addr, args, sizeof(struct virtio_input_event));
  173. virtio_free_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id);
  174. virtio_fill_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id,
  175. VIRTIO_VA2PA(addr), sizeof(struct virtio_input_event), 0, 0);
  176. virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, id);
  177. virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS);
  178. virtio_alloc_desc(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS);
  179. #ifdef RT_USING_SMP
  180. rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
  181. #endif
  182. }
  183. break;
  184. case VIRTIO_DEVICE_CTRL_INPUT_GET_EV_BIT:
  185. rt_memcpy(args, virtio_input_dev->ev_bit, sizeof(virtio_input_dev->ev_bit));
  186. break;
  187. case VIRTIO_DEVICE_CTRL_INPUT_GET_KEY_BIT:
  188. rt_memcpy(args, virtio_input_dev->key_bit, sizeof(virtio_input_dev->key_bit));
  189. break;
  190. case VIRTIO_DEVICE_CTRL_INPUT_GET_REL_BIT:
  191. rt_memcpy(args, virtio_input_dev->rel_bit, sizeof(virtio_input_dev->rel_bit));
  192. break;
  193. case VIRTIO_DEVICE_CTRL_INPUT_GET_ABS_BIT:
  194. rt_memcpy(args, virtio_input_dev->abs_bit, sizeof(virtio_input_dev->abs_bit));
  195. break;
  196. default:
  197. status = -RT_EINVAL;
  198. break;
  199. }
  200. return status;
  201. }
  202. #ifdef RT_USING_DEVICE_OPS
  203. const static struct rt_device_ops virtio_input_ops =
  204. {
  205. virtio_input_init,
  206. RT_NULL,
  207. RT_NULL,
  208. virtio_input_read,
  209. virtio_input_write,
  210. virtio_input_control
  211. };
  212. #endif
  213. static void virtio_input_isr(int irqno, void *param)
  214. {
  215. struct virtio_input_device *virtio_input_dev = (struct virtio_input_device *)param;
  216. struct virtio_device *virtio_dev = &virtio_input_dev->virtio_dev;
  217. struct virtq *event_queue = &virtio_dev->queues[VIRTIO_INPUT_QUEUE_EVENT];
  218. const char *dev_name = virtio_input_dev->parent.parent.name;
  219. #ifdef RT_USING_SMP
  220. rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
  221. #endif
  222. virtio_interrupt_ack(virtio_dev);
  223. rt_hw_dsb();
  224. while (event_queue->used_idx != event_queue->used->idx)
  225. {
  226. rt_uint16_t id = event_queue->used->ring[event_queue->used_idx % event_queue->num].id;
  227. rt_uint32_t len = event_queue->used->ring[event_queue->used_idx % event_queue->num].len;
  228. if (len == sizeof(struct virtio_input_event))
  229. {
  230. struct virtio_input_event *recv_events = &virtio_input_dev->recv_events[id];
  231. struct virtio_input_event *bcst_events = &virtio_input_dev->bcst_events[id];
  232. if (recv_events->type >= EV_SYN && recv_events->type <= EV_ABS)
  233. {
  234. bcst_events->type = recv_events->type;
  235. bcst_events->code = recv_events->code;
  236. bcst_events->value = recv_events->value;
  237. if (virtio_input_dev->bsct_handler != RT_NULL)
  238. {
  239. virtio_input_dev->bsct_handler(*bcst_events);
  240. }
  241. }
  242. else
  243. {
  244. rt_kprintf("%s: Unsupport event[type: %02x, code: %02x, value: %08x]!\n",
  245. dev_name, recv_events->type, recv_events->code, recv_events->value);
  246. }
  247. }
  248. else
  249. {
  250. rt_kprintf("%s: Invalid event!\n", dev_name);
  251. }
  252. event_queue->used_idx++;
  253. virtio_submit_chain(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, id);
  254. virtio_queue_notify(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
  255. }
  256. #ifdef RT_USING_SMP
  257. rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
  258. #endif
  259. }
  260. rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
  261. {
  262. rt_uint32_t flag;
  263. static int dev_no = 0;
  264. char dev_name[RT_NAME_MAX];
  265. struct virtio_device *virtio_dev;
  266. struct virtio_input_device *virtio_input_dev;
  267. virtio_input_dev = rt_malloc(sizeof(struct virtio_input_device));
  268. if (virtio_input_dev == RT_NULL)
  269. {
  270. goto _alloc_fail;
  271. }
  272. virtio_dev = &virtio_input_dev->virtio_dev;
  273. virtio_dev->irq = irq;
  274. virtio_dev->mmio_base = mmio_base;
  275. virtio_input_dev->config = (struct virtio_input_config *)virtio_dev->mmio_config->config;
  276. virtio_input_dev->bsct_handler = RT_NULL;
  277. #ifdef RT_USING_SMP
  278. rt_spin_lock_init(&virtio_dev->spinlock);
  279. #endif
  280. virtio_reset_device(virtio_dev);
  281. virtio_status_acknowledge_driver(virtio_dev);
  282. virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
  283. (1 << VIRTIO_F_RING_EVENT_IDX) |
  284. (1 << VIRTIO_F_RING_INDIRECT_DESC));
  285. virtio_status_driver_ok(virtio_dev);
  286. if (virtio_queues_alloc(virtio_dev, 2) != RT_EOK)
  287. {
  288. goto _alloc_fail;
  289. }
  290. if (virtio_queue_init(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT, VIRTIO_INPUT_EVENT_QUEUE_SIZE) != RT_EOK)
  291. {
  292. goto _alloc_fail;
  293. }
  294. if (virtio_queue_init(virtio_dev, VIRTIO_INPUT_QUEUE_STATUS, VIRTIO_INPUT_STATUS_QUEUE_SIZE) != RT_EOK)
  295. {
  296. virtio_queue_destroy(virtio_dev, VIRTIO_INPUT_QUEUE_EVENT);
  297. goto _alloc_fail;
  298. }
  299. virtio_input_cfg_select(virtio_input_dev, VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
  300. if (virtio_input_dev->config->ids.product == EV_ABS)
  301. {
  302. virtio_input_dev->type = VIRTIO_INPUT_TYPE_TABLET;
  303. virtio_input_dev->parent.type = RT_Device_Class_Touch;
  304. flag = RT_DEVICE_FLAG_STANDALONE | RT_DEVICE_FLAG_INT_RX;
  305. }
  306. else
  307. {
  308. if (virtio_input_dev->config->ids.product == EV_KEY)
  309. {
  310. virtio_input_dev->type = VIRTIO_INPUT_TYPE_KEYBOARD;
  311. }
  312. else
  313. {
  314. virtio_input_dev->type = VIRTIO_INPUT_TYPE_MOUSE;
  315. }
  316. /* Replace it to "KeyBoard" or "Mouse" if support in the future */
  317. virtio_input_dev->parent.type = RT_Device_Class_Miscellaneous;
  318. flag = RT_DEVICE_FLAG_RDWR;
  319. }
  320. #ifdef RT_USING_DEVICE_OPS
  321. virtio_input_dev->parent.ops = &virtio_input_ops;
  322. #else
  323. virtio_input_dev->parent.init = virtio_input_init;
  324. virtio_input_dev->parent.open = RT_NULL;
  325. virtio_input_dev->parent.close = RT_NULL;
  326. virtio_input_dev->parent.read = virtio_input_read;
  327. virtio_input_dev->parent.write = virtio_input_write;
  328. virtio_input_dev->parent.control = virtio_input_control;
  329. #endif
  330. rt_snprintf(dev_name, RT_NAME_MAX, "virtio-input%d", dev_no++);
  331. rt_mutex_init(&virtio_input_dev->rw_mutex, dev_name, RT_IPC_FLAG_PRIO);
  332. rt_hw_interrupt_install(irq, virtio_input_isr, virtio_input_dev, dev_name);
  333. rt_hw_interrupt_umask(irq);
  334. return rt_device_register((rt_device_t)virtio_input_dev, dev_name, flag);
  335. _alloc_fail:
  336. if (virtio_input_dev != RT_NULL)
  337. {
  338. virtio_queues_free(virtio_dev);
  339. rt_free(virtio_input_dev);
  340. }
  341. return -RT_ENOMEM;
  342. }
  343. #endif /* RT_USING_VIRTIO_INPUT */