virtio-input-hid.c 16 KB

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