2
0

virtio-input-hid.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*
  2. * This work is licensed under the terms of the GNU GPL, version 2 or
  3. * (at your option) any later version. See the COPYING file in the
  4. * top-level directory.
  5. */
  6. #include "qemu/osdep.h"
  7. #include "qemu/iov.h"
  8. #include "qemu/module.h"
  9. #include "hw/virtio/virtio.h"
  10. #include "hw/qdev-properties.h"
  11. #include "hw/virtio/virtio-input.h"
  12. #undef CONFIG_CURSES
  13. #include "ui/console.h"
  14. #include "standard-headers/linux/input.h"
  15. #define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
  16. #define VIRTIO_ID_NAME_MOUSE "QEMU Virtio Mouse"
  17. #define VIRTIO_ID_NAME_TABLET "QEMU Virtio Tablet"
  18. /* ----------------------------------------------------------------- */
  19. static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
  20. [INPUT_BUTTON_LEFT] = BTN_LEFT,
  21. [INPUT_BUTTON_RIGHT] = BTN_RIGHT,
  22. [INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
  23. [INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
  24. [INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
  25. [INPUT_BUTTON_SIDE] = BTN_SIDE,
  26. [INPUT_BUTTON_EXTRA] = BTN_EXTRA,
  27. };
  28. static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
  29. [INPUT_AXIS_X] = REL_X,
  30. [INPUT_AXIS_Y] = REL_Y,
  31. };
  32. static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
  33. [INPUT_AXIS_X] = ABS_X,
  34. [INPUT_AXIS_Y] = ABS_Y,
  35. };
  36. /* ----------------------------------------------------------------- */
  37. static void virtio_input_key_config(VirtIOInput *vinput,
  38. const unsigned short *keymap,
  39. size_t mapsize)
  40. {
  41. virtio_input_config keys;
  42. int i, bit, byte, bmax = 0;
  43. memset(&keys, 0, sizeof(keys));
  44. for (i = 0; i < mapsize; i++) {
  45. bit = keymap[i];
  46. if (!bit) {
  47. continue;
  48. }
  49. byte = bit / 8;
  50. bit = bit % 8;
  51. keys.u.bitmap[byte] |= (1 << bit);
  52. if (bmax < byte+1) {
  53. bmax = byte+1;
  54. }
  55. }
  56. keys.select = VIRTIO_INPUT_CFG_EV_BITS;
  57. keys.subsel = EV_KEY;
  58. keys.size = bmax;
  59. virtio_input_add_config(vinput, &keys);
  60. }
  61. static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
  62. InputEvent *evt)
  63. {
  64. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  65. VirtIOInput *vinput = VIRTIO_INPUT(dev);
  66. virtio_input_event event;
  67. int qcode;
  68. InputKeyEvent *key;
  69. InputMoveEvent *move;
  70. InputBtnEvent *btn;
  71. switch (evt->type) {
  72. case INPUT_EVENT_KIND_KEY:
  73. key = evt->u.key.data;
  74. qcode = qemu_input_key_value_to_qcode(key->key);
  75. if (qcode < qemu_input_map_qcode_to_linux_len &&
  76. qemu_input_map_qcode_to_linux[qcode]) {
  77. event.type = cpu_to_le16(EV_KEY);
  78. event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
  79. event.value = cpu_to_le32(key->down ? 1 : 0);
  80. virtio_input_send(vinput, &event);
  81. } else {
  82. if (key->down) {
  83. fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
  84. qcode, QKeyCode_str(qcode));
  85. }
  86. }
  87. break;
  88. case INPUT_EVENT_KIND_BTN:
  89. btn = evt->u.btn.data;
  90. if (vhid->wheel_axis &&
  91. (btn->button == INPUT_BUTTON_WHEEL_UP ||
  92. btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
  93. btn->down) {
  94. event.type = cpu_to_le16(EV_REL);
  95. event.code = cpu_to_le16(REL_WHEEL);
  96. event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
  97. ? 1 : -1);
  98. virtio_input_send(vinput, &event);
  99. } else if (keymap_button[btn->button]) {
  100. event.type = cpu_to_le16(EV_KEY);
  101. event.code = cpu_to_le16(keymap_button[btn->button]);
  102. event.value = cpu_to_le32(btn->down ? 1 : 0);
  103. virtio_input_send(vinput, &event);
  104. } else {
  105. if (btn->down) {
  106. fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
  107. btn->button,
  108. InputButton_str(btn->button));
  109. }
  110. }
  111. break;
  112. case INPUT_EVENT_KIND_REL:
  113. move = evt->u.rel.data;
  114. event.type = cpu_to_le16(EV_REL);
  115. event.code = cpu_to_le16(axismap_rel[move->axis]);
  116. event.value = cpu_to_le32(move->value);
  117. virtio_input_send(vinput, &event);
  118. break;
  119. case INPUT_EVENT_KIND_ABS:
  120. move = evt->u.abs.data;
  121. event.type = cpu_to_le16(EV_ABS);
  122. event.code = cpu_to_le16(axismap_abs[move->axis]);
  123. event.value = cpu_to_le32(move->value);
  124. virtio_input_send(vinput, &event);
  125. break;
  126. default:
  127. /* keep gcc happy */
  128. break;
  129. }
  130. }
  131. static void virtio_input_handle_sync(DeviceState *dev)
  132. {
  133. VirtIOInput *vinput = VIRTIO_INPUT(dev);
  134. virtio_input_event event = {
  135. .type = cpu_to_le16(EV_SYN),
  136. .code = cpu_to_le16(SYN_REPORT),
  137. .value = 0,
  138. };
  139. virtio_input_send(vinput, &event);
  140. }
  141. static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
  142. {
  143. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  144. vhid->hs = qemu_input_handler_register(dev, vhid->handler);
  145. if (vhid->display && vhid->hs) {
  146. qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
  147. }
  148. }
  149. static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp)
  150. {
  151. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  152. qemu_input_handler_unregister(vhid->hs);
  153. }
  154. static void virtio_input_hid_change_active(VirtIOInput *vinput)
  155. {
  156. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
  157. if (vinput->active) {
  158. qemu_input_handler_activate(vhid->hs);
  159. } else {
  160. qemu_input_handler_deactivate(vhid->hs);
  161. }
  162. }
  163. static void virtio_input_hid_handle_status(VirtIOInput *vinput,
  164. virtio_input_event *event)
  165. {
  166. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
  167. int ledbit = 0;
  168. switch (le16_to_cpu(event->type)) {
  169. case EV_LED:
  170. if (event->code == LED_NUML) {
  171. ledbit = QEMU_NUM_LOCK_LED;
  172. } else if (event->code == LED_CAPSL) {
  173. ledbit = QEMU_CAPS_LOCK_LED;
  174. } else if (event->code == LED_SCROLLL) {
  175. ledbit = QEMU_SCROLL_LOCK_LED;
  176. }
  177. if (event->value) {
  178. vhid->ledstate |= ledbit;
  179. } else {
  180. vhid->ledstate &= ~ledbit;
  181. }
  182. kbd_put_ledstate(vhid->ledstate);
  183. break;
  184. default:
  185. fprintf(stderr, "%s: unknown type %d\n", __func__,
  186. le16_to_cpu(event->type));
  187. break;
  188. }
  189. }
  190. static Property virtio_input_hid_properties[] = {
  191. DEFINE_PROP_STRING("display", VirtIOInputHID, display),
  192. DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
  193. DEFINE_PROP_END_OF_LIST(),
  194. };
  195. static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
  196. {
  197. DeviceClass *dc = DEVICE_CLASS(klass);
  198. VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
  199. dc->props = virtio_input_hid_properties;
  200. vic->realize = virtio_input_hid_realize;
  201. vic->unrealize = virtio_input_hid_unrealize;
  202. vic->change_active = virtio_input_hid_change_active;
  203. vic->handle_status = virtio_input_hid_handle_status;
  204. }
  205. static const TypeInfo virtio_input_hid_info = {
  206. .name = TYPE_VIRTIO_INPUT_HID,
  207. .parent = TYPE_VIRTIO_INPUT,
  208. .instance_size = sizeof(VirtIOInputHID),
  209. .class_init = virtio_input_hid_class_init,
  210. .abstract = true,
  211. };
  212. /* ----------------------------------------------------------------- */
  213. static QemuInputHandler virtio_keyboard_handler = {
  214. .name = VIRTIO_ID_NAME_KEYBOARD,
  215. .mask = INPUT_EVENT_MASK_KEY,
  216. .event = virtio_input_handle_event,
  217. .sync = virtio_input_handle_sync,
  218. };
  219. static struct virtio_input_config virtio_keyboard_config[] = {
  220. {
  221. .select = VIRTIO_INPUT_CFG_ID_NAME,
  222. .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
  223. .u.string = VIRTIO_ID_NAME_KEYBOARD,
  224. },{
  225. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  226. .size = sizeof(struct virtio_input_devids),
  227. .u.ids = {
  228. .bustype = const_le16(BUS_VIRTUAL),
  229. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  230. .product = const_le16(0x0001),
  231. .version = const_le16(0x0001),
  232. },
  233. },{
  234. .select = VIRTIO_INPUT_CFG_EV_BITS,
  235. .subsel = EV_REP,
  236. .size = 1,
  237. },{
  238. .select = VIRTIO_INPUT_CFG_EV_BITS,
  239. .subsel = EV_LED,
  240. .size = 1,
  241. .u.bitmap = {
  242. (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
  243. },
  244. },
  245. { /* end of list */ },
  246. };
  247. static void virtio_keyboard_init(Object *obj)
  248. {
  249. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  250. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  251. vhid->handler = &virtio_keyboard_handler;
  252. virtio_input_init_config(vinput, virtio_keyboard_config);
  253. virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux,
  254. qemu_input_map_qcode_to_linux_len);
  255. }
  256. static const TypeInfo virtio_keyboard_info = {
  257. .name = TYPE_VIRTIO_KEYBOARD,
  258. .parent = TYPE_VIRTIO_INPUT_HID,
  259. .instance_size = sizeof(VirtIOInputHID),
  260. .instance_init = virtio_keyboard_init,
  261. };
  262. /* ----------------------------------------------------------------- */
  263. static QemuInputHandler virtio_mouse_handler = {
  264. .name = VIRTIO_ID_NAME_MOUSE,
  265. .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
  266. .event = virtio_input_handle_event,
  267. .sync = virtio_input_handle_sync,
  268. };
  269. static struct virtio_input_config virtio_mouse_config_v1[] = {
  270. {
  271. .select = VIRTIO_INPUT_CFG_ID_NAME,
  272. .size = sizeof(VIRTIO_ID_NAME_MOUSE),
  273. .u.string = VIRTIO_ID_NAME_MOUSE,
  274. },{
  275. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  276. .size = sizeof(struct virtio_input_devids),
  277. .u.ids = {
  278. .bustype = const_le16(BUS_VIRTUAL),
  279. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  280. .product = const_le16(0x0002),
  281. .version = const_le16(0x0001),
  282. },
  283. },{
  284. .select = VIRTIO_INPUT_CFG_EV_BITS,
  285. .subsel = EV_REL,
  286. .size = 1,
  287. .u.bitmap = {
  288. (1 << REL_X) | (1 << REL_Y),
  289. },
  290. },
  291. { /* end of list */ },
  292. };
  293. static struct virtio_input_config virtio_mouse_config_v2[] = {
  294. {
  295. .select = VIRTIO_INPUT_CFG_ID_NAME,
  296. .size = sizeof(VIRTIO_ID_NAME_MOUSE),
  297. .u.string = VIRTIO_ID_NAME_MOUSE,
  298. },{
  299. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  300. .size = sizeof(struct virtio_input_devids),
  301. .u.ids = {
  302. .bustype = const_le16(BUS_VIRTUAL),
  303. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  304. .product = const_le16(0x0002),
  305. .version = const_le16(0x0002),
  306. },
  307. },{
  308. .select = VIRTIO_INPUT_CFG_EV_BITS,
  309. .subsel = EV_REL,
  310. .size = 2,
  311. .u.bitmap = {
  312. (1 << REL_X) | (1 << REL_Y),
  313. (1 << (REL_WHEEL - 8))
  314. },
  315. },
  316. { /* end of list */ },
  317. };
  318. static Property virtio_mouse_properties[] = {
  319. DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
  320. DEFINE_PROP_END_OF_LIST(),
  321. };
  322. static void virtio_mouse_class_init(ObjectClass *klass, void *data)
  323. {
  324. DeviceClass *dc = DEVICE_CLASS(klass);
  325. dc->props = virtio_mouse_properties;
  326. }
  327. static void virtio_mouse_init(Object *obj)
  328. {
  329. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  330. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  331. vhid->handler = &virtio_mouse_handler;
  332. virtio_input_init_config(vinput, vhid->wheel_axis
  333. ? virtio_mouse_config_v2
  334. : virtio_mouse_config_v1);
  335. virtio_input_key_config(vinput, keymap_button,
  336. ARRAY_SIZE(keymap_button));
  337. }
  338. static const TypeInfo virtio_mouse_info = {
  339. .name = TYPE_VIRTIO_MOUSE,
  340. .parent = TYPE_VIRTIO_INPUT_HID,
  341. .instance_size = sizeof(VirtIOInputHID),
  342. .instance_init = virtio_mouse_init,
  343. .class_init = virtio_mouse_class_init,
  344. };
  345. /* ----------------------------------------------------------------- */
  346. static QemuInputHandler virtio_tablet_handler = {
  347. .name = VIRTIO_ID_NAME_TABLET,
  348. .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
  349. .event = virtio_input_handle_event,
  350. .sync = virtio_input_handle_sync,
  351. };
  352. static struct virtio_input_config virtio_tablet_config_v1[] = {
  353. {
  354. .select = VIRTIO_INPUT_CFG_ID_NAME,
  355. .size = sizeof(VIRTIO_ID_NAME_TABLET),
  356. .u.string = VIRTIO_ID_NAME_TABLET,
  357. },{
  358. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  359. .size = sizeof(struct virtio_input_devids),
  360. .u.ids = {
  361. .bustype = const_le16(BUS_VIRTUAL),
  362. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  363. .product = const_le16(0x0003),
  364. .version = const_le16(0x0001),
  365. },
  366. },{
  367. .select = VIRTIO_INPUT_CFG_EV_BITS,
  368. .subsel = EV_ABS,
  369. .size = 1,
  370. .u.bitmap = {
  371. (1 << ABS_X) | (1 << ABS_Y),
  372. },
  373. },{
  374. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  375. .subsel = ABS_X,
  376. .size = sizeof(virtio_input_absinfo),
  377. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  378. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  379. },{
  380. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  381. .subsel = ABS_Y,
  382. .size = sizeof(virtio_input_absinfo),
  383. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  384. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  385. },
  386. { /* end of list */ },
  387. };
  388. static struct virtio_input_config virtio_tablet_config_v2[] = {
  389. {
  390. .select = VIRTIO_INPUT_CFG_ID_NAME,
  391. .size = sizeof(VIRTIO_ID_NAME_TABLET),
  392. .u.string = VIRTIO_ID_NAME_TABLET,
  393. },{
  394. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  395. .size = sizeof(struct virtio_input_devids),
  396. .u.ids = {
  397. .bustype = const_le16(BUS_VIRTUAL),
  398. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  399. .product = const_le16(0x0003),
  400. .version = const_le16(0x0002),
  401. },
  402. },{
  403. .select = VIRTIO_INPUT_CFG_EV_BITS,
  404. .subsel = EV_ABS,
  405. .size = 1,
  406. .u.bitmap = {
  407. (1 << ABS_X) | (1 << ABS_Y),
  408. },
  409. },{
  410. .select = VIRTIO_INPUT_CFG_EV_BITS,
  411. .subsel = EV_REL,
  412. .size = 2,
  413. .u.bitmap = {
  414. 0,
  415. (1 << (REL_WHEEL - 8))
  416. },
  417. },{
  418. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  419. .subsel = ABS_X,
  420. .size = sizeof(virtio_input_absinfo),
  421. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  422. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  423. },{
  424. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  425. .subsel = ABS_Y,
  426. .size = sizeof(virtio_input_absinfo),
  427. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  428. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  429. },
  430. { /* end of list */ },
  431. };
  432. static Property virtio_tablet_properties[] = {
  433. DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
  434. DEFINE_PROP_END_OF_LIST(),
  435. };
  436. static void virtio_tablet_class_init(ObjectClass *klass, void *data)
  437. {
  438. DeviceClass *dc = DEVICE_CLASS(klass);
  439. dc->props = virtio_tablet_properties;
  440. }
  441. static void virtio_tablet_init(Object *obj)
  442. {
  443. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  444. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  445. vhid->handler = &virtio_tablet_handler;
  446. virtio_input_init_config(vinput, vhid->wheel_axis
  447. ? virtio_tablet_config_v2
  448. : virtio_tablet_config_v1);
  449. virtio_input_key_config(vinput, keymap_button,
  450. ARRAY_SIZE(keymap_button));
  451. }
  452. static const TypeInfo virtio_tablet_info = {
  453. .name = TYPE_VIRTIO_TABLET,
  454. .parent = TYPE_VIRTIO_INPUT_HID,
  455. .instance_size = sizeof(VirtIOInputHID),
  456. .instance_init = virtio_tablet_init,
  457. .class_init = virtio_tablet_class_init,
  458. };
  459. /* ----------------------------------------------------------------- */
  460. static void virtio_register_types(void)
  461. {
  462. type_register_static(&virtio_input_hid_info);
  463. type_register_static(&virtio_keyboard_info);
  464. type_register_static(&virtio_mouse_info);
  465. type_register_static(&virtio_tablet_info);
  466. }
  467. type_init(virtio_register_types)