virtio-input-hid.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  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. #define VIRTIO_ID_NAME_MULTITOUCH "QEMU Virtio MultiTouch"
  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. [INPUT_BUTTON_TOUCH] = BTN_TOUCH,
  28. };
  29. static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
  30. [INPUT_AXIS_X] = REL_X,
  31. [INPUT_AXIS_Y] = REL_Y,
  32. };
  33. static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
  34. [INPUT_AXIS_X] = ABS_X,
  35. [INPUT_AXIS_Y] = ABS_Y,
  36. };
  37. static const unsigned short axismap_tch[INPUT_AXIS__MAX] = {
  38. [INPUT_AXIS_X] = ABS_MT_POSITION_X,
  39. [INPUT_AXIS_Y] = ABS_MT_POSITION_Y,
  40. };
  41. /* ----------------------------------------------------------------- */
  42. static void virtio_input_extend_config(VirtIOInput *vinput,
  43. const unsigned short *map,
  44. size_t mapsize,
  45. uint8_t select, uint8_t subsel)
  46. {
  47. virtio_input_config ext;
  48. int i, bit, byte, bmax = 0;
  49. memset(&ext, 0, sizeof(ext));
  50. for (i = 0; i < mapsize; i++) {
  51. bit = map[i];
  52. if (!bit) {
  53. continue;
  54. }
  55. byte = bit / 8;
  56. bit = bit % 8;
  57. ext.u.bitmap[byte] |= (1 << bit);
  58. if (bmax < byte+1) {
  59. bmax = byte+1;
  60. }
  61. }
  62. ext.select = select;
  63. ext.subsel = subsel;
  64. ext.size = bmax;
  65. virtio_input_add_config(vinput, &ext);
  66. }
  67. static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
  68. InputEvent *evt)
  69. {
  70. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  71. VirtIOInput *vinput = VIRTIO_INPUT(dev);
  72. virtio_input_event event;
  73. int qcode;
  74. InputKeyEvent *key;
  75. InputMoveEvent *move;
  76. InputBtnEvent *btn;
  77. InputMultiTouchEvent *mtt;
  78. switch (evt->type) {
  79. case INPUT_EVENT_KIND_KEY:
  80. key = evt->u.key.data;
  81. qcode = qemu_input_key_value_to_qcode(key->key);
  82. if (qcode < qemu_input_map_qcode_to_linux_len &&
  83. qemu_input_map_qcode_to_linux[qcode]) {
  84. event.type = cpu_to_le16(EV_KEY);
  85. event.code = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
  86. event.value = cpu_to_le32(key->down ? 1 : 0);
  87. virtio_input_send(vinput, &event);
  88. } else {
  89. if (key->down) {
  90. fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
  91. qcode, QKeyCode_str(qcode));
  92. }
  93. }
  94. break;
  95. case INPUT_EVENT_KIND_BTN:
  96. btn = evt->u.btn.data;
  97. if (vhid->wheel_axis &&
  98. (btn->button == INPUT_BUTTON_WHEEL_UP ||
  99. btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
  100. btn->down) {
  101. event.type = cpu_to_le16(EV_REL);
  102. event.code = cpu_to_le16(REL_WHEEL);
  103. event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
  104. ? 1 : -1);
  105. virtio_input_send(vinput, &event);
  106. } else if (keymap_button[btn->button]) {
  107. event.type = cpu_to_le16(EV_KEY);
  108. event.code = cpu_to_le16(keymap_button[btn->button]);
  109. event.value = cpu_to_le32(btn->down ? 1 : 0);
  110. virtio_input_send(vinput, &event);
  111. } else {
  112. if (btn->down) {
  113. fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
  114. btn->button,
  115. InputButton_str(btn->button));
  116. }
  117. }
  118. break;
  119. case INPUT_EVENT_KIND_REL:
  120. move = evt->u.rel.data;
  121. event.type = cpu_to_le16(EV_REL);
  122. event.code = cpu_to_le16(axismap_rel[move->axis]);
  123. event.value = cpu_to_le32(move->value);
  124. virtio_input_send(vinput, &event);
  125. break;
  126. case INPUT_EVENT_KIND_ABS:
  127. move = evt->u.abs.data;
  128. event.type = cpu_to_le16(EV_ABS);
  129. event.code = cpu_to_le16(axismap_abs[move->axis]);
  130. event.value = cpu_to_le32(move->value);
  131. virtio_input_send(vinput, &event);
  132. break;
  133. case INPUT_EVENT_KIND_MTT:
  134. mtt = evt->u.mtt.data;
  135. if (mtt->type == INPUT_MULTI_TOUCH_TYPE_DATA) {
  136. event.type = cpu_to_le16(EV_ABS);
  137. event.code = cpu_to_le16(axismap_tch[mtt->axis]);
  138. event.value = cpu_to_le32(mtt->value);
  139. virtio_input_send(vinput, &event);
  140. } else {
  141. event.type = cpu_to_le16(EV_ABS);
  142. event.code = cpu_to_le16(ABS_MT_SLOT);
  143. event.value = cpu_to_le32(mtt->slot);
  144. virtio_input_send(vinput, &event);
  145. event.type = cpu_to_le16(EV_ABS);
  146. event.code = cpu_to_le16(ABS_MT_TRACKING_ID);
  147. event.value = cpu_to_le32(mtt->tracking_id);
  148. virtio_input_send(vinput, &event);
  149. }
  150. break;
  151. default:
  152. /* keep gcc happy */
  153. break;
  154. }
  155. }
  156. static void virtio_input_handle_sync(DeviceState *dev)
  157. {
  158. VirtIOInput *vinput = VIRTIO_INPUT(dev);
  159. virtio_input_event event = {
  160. .type = cpu_to_le16(EV_SYN),
  161. .code = cpu_to_le16(SYN_REPORT),
  162. .value = 0,
  163. };
  164. virtio_input_send(vinput, &event);
  165. }
  166. static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
  167. {
  168. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  169. vhid->hs = qemu_input_handler_register(dev, vhid->handler);
  170. if (vhid->display && vhid->hs) {
  171. qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
  172. }
  173. }
  174. static void virtio_input_hid_unrealize(DeviceState *dev)
  175. {
  176. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
  177. qemu_input_handler_unregister(vhid->hs);
  178. }
  179. static void virtio_input_hid_change_active(VirtIOInput *vinput)
  180. {
  181. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
  182. if (vinput->active) {
  183. qemu_input_handler_activate(vhid->hs);
  184. } else {
  185. qemu_input_handler_deactivate(vhid->hs);
  186. }
  187. }
  188. static void virtio_input_hid_handle_status(VirtIOInput *vinput,
  189. virtio_input_event *event)
  190. {
  191. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
  192. int ledbit = 0;
  193. switch (le16_to_cpu(event->type)) {
  194. case EV_LED:
  195. if (event->code == LED_NUML) {
  196. ledbit = QEMU_NUM_LOCK_LED;
  197. } else if (event->code == LED_CAPSL) {
  198. ledbit = QEMU_CAPS_LOCK_LED;
  199. } else if (event->code == LED_SCROLLL) {
  200. ledbit = QEMU_SCROLL_LOCK_LED;
  201. }
  202. if (event->value) {
  203. vhid->ledstate |= ledbit;
  204. } else {
  205. vhid->ledstate &= ~ledbit;
  206. }
  207. kbd_put_ledstate(vhid->ledstate);
  208. break;
  209. default:
  210. fprintf(stderr, "%s: unknown type %d\n", __func__,
  211. le16_to_cpu(event->type));
  212. break;
  213. }
  214. }
  215. static Property virtio_input_hid_properties[] = {
  216. DEFINE_PROP_STRING("display", VirtIOInputHID, display),
  217. DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
  218. DEFINE_PROP_END_OF_LIST(),
  219. };
  220. static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
  221. {
  222. DeviceClass *dc = DEVICE_CLASS(klass);
  223. VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
  224. device_class_set_props(dc, virtio_input_hid_properties);
  225. vic->realize = virtio_input_hid_realize;
  226. vic->unrealize = virtio_input_hid_unrealize;
  227. vic->change_active = virtio_input_hid_change_active;
  228. vic->handle_status = virtio_input_hid_handle_status;
  229. }
  230. static const TypeInfo virtio_input_hid_info = {
  231. .name = TYPE_VIRTIO_INPUT_HID,
  232. .parent = TYPE_VIRTIO_INPUT,
  233. .instance_size = sizeof(VirtIOInputHID),
  234. .class_init = virtio_input_hid_class_init,
  235. .abstract = true,
  236. };
  237. /* ----------------------------------------------------------------- */
  238. static QemuInputHandler virtio_keyboard_handler = {
  239. .name = VIRTIO_ID_NAME_KEYBOARD,
  240. .mask = INPUT_EVENT_MASK_KEY,
  241. .event = virtio_input_handle_event,
  242. .sync = virtio_input_handle_sync,
  243. };
  244. static struct virtio_input_config virtio_keyboard_config[] = {
  245. {
  246. .select = VIRTIO_INPUT_CFG_ID_NAME,
  247. .size = sizeof(VIRTIO_ID_NAME_KEYBOARD),
  248. .u.string = VIRTIO_ID_NAME_KEYBOARD,
  249. },{
  250. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  251. .size = sizeof(struct virtio_input_devids),
  252. .u.ids = {
  253. .bustype = const_le16(BUS_VIRTUAL),
  254. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  255. .product = const_le16(0x0001),
  256. .version = const_le16(0x0001),
  257. },
  258. },{
  259. .select = VIRTIO_INPUT_CFG_EV_BITS,
  260. .subsel = EV_REP,
  261. .size = 1,
  262. },{
  263. .select = VIRTIO_INPUT_CFG_EV_BITS,
  264. .subsel = EV_LED,
  265. .size = 1,
  266. .u.bitmap = {
  267. (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
  268. },
  269. },
  270. { /* end of list */ },
  271. };
  272. static void virtio_keyboard_init(Object *obj)
  273. {
  274. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  275. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  276. vhid->handler = &virtio_keyboard_handler;
  277. virtio_input_init_config(vinput, virtio_keyboard_config);
  278. virtio_input_extend_config(vinput, qemu_input_map_qcode_to_linux,
  279. qemu_input_map_qcode_to_linux_len,
  280. VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
  281. }
  282. static const TypeInfo virtio_keyboard_info = {
  283. .name = TYPE_VIRTIO_KEYBOARD,
  284. .parent = TYPE_VIRTIO_INPUT_HID,
  285. .instance_size = sizeof(VirtIOInputHID),
  286. .instance_init = virtio_keyboard_init,
  287. };
  288. /* ----------------------------------------------------------------- */
  289. static QemuInputHandler virtio_mouse_handler = {
  290. .name = VIRTIO_ID_NAME_MOUSE,
  291. .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
  292. .event = virtio_input_handle_event,
  293. .sync = virtio_input_handle_sync,
  294. };
  295. static struct virtio_input_config virtio_mouse_config_v1[] = {
  296. {
  297. .select = VIRTIO_INPUT_CFG_ID_NAME,
  298. .size = sizeof(VIRTIO_ID_NAME_MOUSE),
  299. .u.string = VIRTIO_ID_NAME_MOUSE,
  300. },{
  301. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  302. .size = sizeof(struct virtio_input_devids),
  303. .u.ids = {
  304. .bustype = const_le16(BUS_VIRTUAL),
  305. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  306. .product = const_le16(0x0002),
  307. .version = const_le16(0x0001),
  308. },
  309. },{
  310. .select = VIRTIO_INPUT_CFG_EV_BITS,
  311. .subsel = EV_REL,
  312. .size = 1,
  313. .u.bitmap = {
  314. (1 << REL_X) | (1 << REL_Y),
  315. },
  316. },
  317. { /* end of list */ },
  318. };
  319. static struct virtio_input_config virtio_mouse_config_v2[] = {
  320. {
  321. .select = VIRTIO_INPUT_CFG_ID_NAME,
  322. .size = sizeof(VIRTIO_ID_NAME_MOUSE),
  323. .u.string = VIRTIO_ID_NAME_MOUSE,
  324. },{
  325. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  326. .size = sizeof(struct virtio_input_devids),
  327. .u.ids = {
  328. .bustype = const_le16(BUS_VIRTUAL),
  329. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  330. .product = const_le16(0x0002),
  331. .version = const_le16(0x0002),
  332. },
  333. },{
  334. .select = VIRTIO_INPUT_CFG_EV_BITS,
  335. .subsel = EV_REL,
  336. .size = 2,
  337. .u.bitmap = {
  338. (1 << REL_X) | (1 << REL_Y),
  339. (1 << (REL_WHEEL - 8))
  340. },
  341. },
  342. { /* end of list */ },
  343. };
  344. static Property virtio_mouse_properties[] = {
  345. DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
  346. DEFINE_PROP_END_OF_LIST(),
  347. };
  348. static void virtio_mouse_class_init(ObjectClass *klass, void *data)
  349. {
  350. DeviceClass *dc = DEVICE_CLASS(klass);
  351. device_class_set_props(dc, virtio_mouse_properties);
  352. }
  353. static void virtio_mouse_init(Object *obj)
  354. {
  355. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  356. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  357. vhid->handler = &virtio_mouse_handler;
  358. virtio_input_init_config(vinput, vhid->wheel_axis
  359. ? virtio_mouse_config_v2
  360. : virtio_mouse_config_v1);
  361. virtio_input_extend_config(vinput, keymap_button,
  362. ARRAY_SIZE(keymap_button),
  363. VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
  364. }
  365. static const TypeInfo virtio_mouse_info = {
  366. .name = TYPE_VIRTIO_MOUSE,
  367. .parent = TYPE_VIRTIO_INPUT_HID,
  368. .instance_size = sizeof(VirtIOInputHID),
  369. .instance_init = virtio_mouse_init,
  370. .class_init = virtio_mouse_class_init,
  371. };
  372. /* ----------------------------------------------------------------- */
  373. static QemuInputHandler virtio_tablet_handler = {
  374. .name = VIRTIO_ID_NAME_TABLET,
  375. .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
  376. .event = virtio_input_handle_event,
  377. .sync = virtio_input_handle_sync,
  378. };
  379. static struct virtio_input_config virtio_tablet_config_v1[] = {
  380. {
  381. .select = VIRTIO_INPUT_CFG_ID_NAME,
  382. .size = sizeof(VIRTIO_ID_NAME_TABLET),
  383. .u.string = VIRTIO_ID_NAME_TABLET,
  384. },{
  385. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  386. .size = sizeof(struct virtio_input_devids),
  387. .u.ids = {
  388. .bustype = const_le16(BUS_VIRTUAL),
  389. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  390. .product = const_le16(0x0003),
  391. .version = const_le16(0x0001),
  392. },
  393. },{
  394. .select = VIRTIO_INPUT_CFG_EV_BITS,
  395. .subsel = EV_ABS,
  396. .size = 1,
  397. .u.bitmap = {
  398. (1 << ABS_X) | (1 << ABS_Y),
  399. },
  400. },{
  401. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  402. .subsel = ABS_X,
  403. .size = sizeof(virtio_input_absinfo),
  404. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  405. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  406. },{
  407. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  408. .subsel = ABS_Y,
  409. .size = sizeof(virtio_input_absinfo),
  410. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  411. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  412. },
  413. { /* end of list */ },
  414. };
  415. static struct virtio_input_config virtio_tablet_config_v2[] = {
  416. {
  417. .select = VIRTIO_INPUT_CFG_ID_NAME,
  418. .size = sizeof(VIRTIO_ID_NAME_TABLET),
  419. .u.string = VIRTIO_ID_NAME_TABLET,
  420. },{
  421. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  422. .size = sizeof(struct virtio_input_devids),
  423. .u.ids = {
  424. .bustype = const_le16(BUS_VIRTUAL),
  425. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  426. .product = const_le16(0x0003),
  427. .version = const_le16(0x0002),
  428. },
  429. },{
  430. .select = VIRTIO_INPUT_CFG_EV_BITS,
  431. .subsel = EV_ABS,
  432. .size = 1,
  433. .u.bitmap = {
  434. (1 << ABS_X) | (1 << ABS_Y),
  435. },
  436. },{
  437. .select = VIRTIO_INPUT_CFG_EV_BITS,
  438. .subsel = EV_REL,
  439. .size = 2,
  440. .u.bitmap = {
  441. 0,
  442. (1 << (REL_WHEEL - 8))
  443. },
  444. },{
  445. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  446. .subsel = ABS_X,
  447. .size = sizeof(virtio_input_absinfo),
  448. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  449. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  450. },{
  451. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  452. .subsel = ABS_Y,
  453. .size = sizeof(virtio_input_absinfo),
  454. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  455. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  456. },
  457. { /* end of list */ },
  458. };
  459. static Property virtio_tablet_properties[] = {
  460. DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
  461. DEFINE_PROP_END_OF_LIST(),
  462. };
  463. static void virtio_tablet_class_init(ObjectClass *klass, void *data)
  464. {
  465. DeviceClass *dc = DEVICE_CLASS(klass);
  466. device_class_set_props(dc, virtio_tablet_properties);
  467. }
  468. static void virtio_tablet_init(Object *obj)
  469. {
  470. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  471. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  472. vhid->handler = &virtio_tablet_handler;
  473. virtio_input_init_config(vinput, vhid->wheel_axis
  474. ? virtio_tablet_config_v2
  475. : virtio_tablet_config_v1);
  476. virtio_input_extend_config(vinput, keymap_button,
  477. ARRAY_SIZE(keymap_button),
  478. VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
  479. }
  480. static const TypeInfo virtio_tablet_info = {
  481. .name = TYPE_VIRTIO_TABLET,
  482. .parent = TYPE_VIRTIO_INPUT_HID,
  483. .instance_size = sizeof(VirtIOInputHID),
  484. .instance_init = virtio_tablet_init,
  485. .class_init = virtio_tablet_class_init,
  486. };
  487. /* ----------------------------------------------------------------- */
  488. static QemuInputHandler virtio_multitouch_handler = {
  489. .name = VIRTIO_ID_NAME_MULTITOUCH,
  490. .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_MTT,
  491. .event = virtio_input_handle_event,
  492. .sync = virtio_input_handle_sync,
  493. };
  494. static struct virtio_input_config virtio_multitouch_config[] = {
  495. {
  496. .select = VIRTIO_INPUT_CFG_ID_NAME,
  497. .size = sizeof(VIRTIO_ID_NAME_MULTITOUCH),
  498. .u.string = VIRTIO_ID_NAME_MULTITOUCH,
  499. },{
  500. .select = VIRTIO_INPUT_CFG_ID_DEVIDS,
  501. .size = sizeof(struct virtio_input_devids),
  502. .u.ids = {
  503. .bustype = const_le16(BUS_VIRTUAL),
  504. .vendor = const_le16(0x0627), /* same we use for usb hid devices */
  505. .product = const_le16(0x0003),
  506. .version = const_le16(0x0001),
  507. },
  508. },{
  509. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  510. .subsel = ABS_MT_SLOT,
  511. .size = sizeof(virtio_input_absinfo),
  512. .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
  513. .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
  514. },{
  515. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  516. .subsel = ABS_MT_TRACKING_ID,
  517. .size = sizeof(virtio_input_absinfo),
  518. .u.abs.min = const_le32(INPUT_EVENT_SLOTS_MIN),
  519. .u.abs.max = const_le32(INPUT_EVENT_SLOTS_MAX),
  520. },{
  521. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  522. .subsel = ABS_MT_POSITION_X,
  523. .size = sizeof(virtio_input_absinfo),
  524. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  525. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  526. },{
  527. .select = VIRTIO_INPUT_CFG_ABS_INFO,
  528. .subsel = ABS_MT_POSITION_Y,
  529. .size = sizeof(virtio_input_absinfo),
  530. .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
  531. .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
  532. },
  533. { /* end of list */ },
  534. };
  535. static void virtio_multitouch_init(Object *obj)
  536. {
  537. VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
  538. VirtIOInput *vinput = VIRTIO_INPUT(obj);
  539. unsigned short abs_props[] = {
  540. INPUT_PROP_DIRECT,
  541. };
  542. unsigned short abs_bits[] = {
  543. ABS_MT_SLOT,
  544. ABS_MT_TRACKING_ID,
  545. ABS_MT_POSITION_X,
  546. ABS_MT_POSITION_Y,
  547. };
  548. vhid->handler = &virtio_multitouch_handler;
  549. virtio_input_init_config(vinput, virtio_multitouch_config);
  550. virtio_input_extend_config(vinput, keymap_button,
  551. ARRAY_SIZE(keymap_button),
  552. VIRTIO_INPUT_CFG_EV_BITS, EV_KEY);
  553. virtio_input_extend_config(vinput, abs_props,
  554. ARRAY_SIZE(abs_props),
  555. VIRTIO_INPUT_CFG_PROP_BITS, 0);
  556. virtio_input_extend_config(vinput, abs_bits,
  557. ARRAY_SIZE(abs_bits),
  558. VIRTIO_INPUT_CFG_EV_BITS, EV_ABS);
  559. }
  560. static const TypeInfo virtio_multitouch_info = {
  561. .name = TYPE_VIRTIO_MULTITOUCH,
  562. .parent = TYPE_VIRTIO_INPUT_HID,
  563. .instance_size = sizeof(VirtIOInputHID),
  564. .instance_init = virtio_multitouch_init,
  565. };
  566. /* ----------------------------------------------------------------- */
  567. static void virtio_register_types(void)
  568. {
  569. type_register_static(&virtio_input_hid_info);
  570. type_register_static(&virtio_keyboard_info);
  571. type_register_static(&virtio_mouse_info);
  572. type_register_static(&virtio_tablet_info);
  573. type_register_static(&virtio_multitouch_info);
  574. }
  575. type_init(virtio_register_types)