^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Xen para-virtual input device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on linux/drivers/input/mouse/sermouse.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/xen/hypervisor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <xen/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <xen/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <xen/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <xen/grant_table.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <xen/interface/grant_table.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <xen/interface/io/fbif.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <xen/interface/io/kbdif.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <xen/xenbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <xen/platform_pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct xenkbd_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct input_dev *kbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct input_dev *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct input_dev *mtouch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct xenkbd_page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int gref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct xenbus_device *xbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) char phys[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* current MT slot/contact ID we are injecting events in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int mtouch_cur_contact_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) enum { KPARAM_X, KPARAM_Y, KPARAM_CNT };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int ptr_size[KPARAM_CNT] = { XENFB_WIDTH, XENFB_HEIGHT };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) module_param_array(ptr_size, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MODULE_PARM_DESC(ptr_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "Pointing device width, height in pixels (default 800,600)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int xenkbd_remove(struct xenbus_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void xenkbd_disconnect_backend(struct xenkbd_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Note: if you need to send out events, see xenfb_do_update() for how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * to do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void xenkbd_handle_motion_event(struct xenkbd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct xenkbd_motion *motion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (unlikely(!info->ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) input_report_rel(info->ptr, REL_X, motion->rel_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) input_report_rel(info->ptr, REL_Y, motion->rel_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (motion->rel_z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) input_report_rel(info->ptr, REL_WHEEL, -motion->rel_z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) input_sync(info->ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void xenkbd_handle_position_event(struct xenkbd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct xenkbd_position *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (unlikely(!info->ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) input_report_abs(info->ptr, ABS_X, pos->abs_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) input_report_abs(info->ptr, ABS_Y, pos->abs_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (pos->rel_z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) input_report_rel(info->ptr, REL_WHEEL, -pos->rel_z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) input_sync(info->ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void xenkbd_handle_key_event(struct xenkbd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct xenkbd_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int value = key->pressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (test_bit(key->keycode, info->ptr->keybit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dev = info->ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) } else if (test_bit(key->keycode, info->kbd->keybit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dev = info->kbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (key->pressed && test_bit(key->keycode, info->kbd->key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) value = 2; /* Mark as autorepeat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pr_warn("unhandled keycode 0x%x\n", key->keycode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (unlikely(!dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) input_event(dev, EV_KEY, key->keycode, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void xenkbd_handle_mt_event(struct xenkbd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct xenkbd_mtouch *mtouch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (unlikely(!info->mtouch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (mtouch->contact_id != info->mtouch_cur_contact_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) info->mtouch_cur_contact_id = mtouch->contact_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) input_mt_slot(info->mtouch, mtouch->contact_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) switch (mtouch->event_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case XENKBD_MT_EV_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case XENKBD_MT_EV_MOTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) input_report_abs(info->mtouch, ABS_MT_POSITION_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) mtouch->u.pos.abs_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) input_report_abs(info->mtouch, ABS_MT_POSITION_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mtouch->u.pos.abs_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case XENKBD_MT_EV_SHAPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) input_report_abs(info->mtouch, ABS_MT_TOUCH_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mtouch->u.shape.major);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) input_report_abs(info->mtouch, ABS_MT_TOUCH_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) mtouch->u.shape.minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case XENKBD_MT_EV_ORIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) input_report_abs(info->mtouch, ABS_MT_ORIENTATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mtouch->u.orientation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case XENKBD_MT_EV_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) input_mt_report_slot_inactive(info->mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case XENKBD_MT_EV_SYN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) input_mt_sync_frame(info->mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) input_sync(info->mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static void xenkbd_handle_event(struct xenkbd_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) union xenkbd_in_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) switch (event->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case XENKBD_TYPE_MOTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) xenkbd_handle_motion_event(info, &event->motion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case XENKBD_TYPE_KEY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) xenkbd_handle_key_event(info, &event->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case XENKBD_TYPE_POS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) xenkbd_handle_position_event(info, &event->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case XENKBD_TYPE_MTOUCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) xenkbd_handle_mt_event(info, &event->mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static irqreturn_t input_handler(int rq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct xenkbd_info *info = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct xenkbd_page *page = info->page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) __u32 cons, prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) prod = page->in_prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (prod == page->in_cons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) rmb(); /* ensure we see ring contents up to prod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (cons = page->in_cons; cons != prod; cons++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) xenkbd_handle_event(info, &XENKBD_IN_RING_REF(page, cons));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mb(); /* ensure we got ring contents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) page->in_cons = cons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) notify_remote_via_irq(info->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int xenkbd_probe(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) const struct xenbus_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) bool with_mtouch, with_kbd, with_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct xenkbd_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct input_dev *kbd, *ptr, *mtouch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) info = kzalloc(sizeof(*info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dev_set_drvdata(&dev->dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) info->xbdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) info->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) info->gref = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!info->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * The below are reverse logic, e.g. if the feature is set, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * do not expose the corresponding virtual device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) with_kbd = !xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) with_ptr = !xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Direct logic: if set, then create multi-touch device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) with_mtouch = xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) XENKBD_FIELD_FEAT_MTOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (with_mtouch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ret = xenbus_write(XBT_NIL, dev->nodename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) XENKBD_FIELD_REQ_MTOUCH, "1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pr_warn("xenkbd: can't request multi-touch");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) with_mtouch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (with_kbd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) kbd = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) kbd->name = "Xen Virtual Keyboard";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) kbd->phys = info->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) kbd->id.bustype = BUS_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) kbd->id.vendor = 0x5853;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) kbd->id.product = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) __set_bit(EV_KEY, kbd->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) __set_bit(i, kbd->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) for (i = KEY_OK; i < KEY_MAX; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) __set_bit(i, kbd->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = input_register_device(kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) input_free_device(kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) xenbus_dev_fatal(dev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) "input_register_device(kbd)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) info->kbd = kbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* pointing device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (with_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) unsigned int abs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* Set input abs params to match backend screen res */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) abs = xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) XENKBD_FIELD_FEAT_ABS_POINTER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) XENKBD_FIELD_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ptr_size[KPARAM_X]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) XENKBD_FIELD_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ptr_size[KPARAM_Y]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (abs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = xenbus_write(XBT_NIL, dev->nodename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) XENKBD_FIELD_REQ_ABS_POINTER, "1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) pr_warn("xenkbd: can't request abs-pointer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) abs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ptr = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ptr->name = "Xen Virtual Pointer";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ptr->phys = info->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ptr->id.bustype = BUS_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ptr->id.vendor = 0x5853;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ptr->id.product = 0xfffe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (abs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) __set_bit(EV_ABS, ptr->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) input_set_abs_params(ptr, ABS_X, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ptr_size[KPARAM_X], 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) input_set_abs_params(ptr, ABS_Y, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ptr_size[KPARAM_Y], 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) input_set_capability(ptr, EV_REL, REL_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) input_set_capability(ptr, EV_REL, REL_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) input_set_capability(ptr, EV_REL, REL_WHEEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) __set_bit(EV_KEY, ptr->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) for (i = BTN_LEFT; i <= BTN_TASK; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) __set_bit(i, ptr->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = input_register_device(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) input_free_device(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) xenbus_dev_fatal(dev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) "input_register_device(ptr)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) info->ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* multi-touch device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (with_mtouch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int num_cont, width, height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) mtouch = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!mtouch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) num_cont = xenbus_read_unsigned(info->xbdev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) XENKBD_FIELD_MT_NUM_CONTACTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) width = xenbus_read_unsigned(info->xbdev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) XENKBD_FIELD_MT_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) XENFB_WIDTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) height = xenbus_read_unsigned(info->xbdev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) XENKBD_FIELD_MT_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) XENFB_HEIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) mtouch->name = "Xen Virtual Multi-touch";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mtouch->phys = info->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mtouch->id.bustype = BUS_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mtouch->id.vendor = 0x5853;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) mtouch->id.product = 0xfffd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) input_set_abs_params(mtouch, ABS_MT_TOUCH_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 0, 255, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) input_set_abs_params(mtouch, ABS_MT_POSITION_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 0, width, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) input_set_abs_params(mtouch, ABS_MT_POSITION_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 0, height, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ret = input_mt_init_slots(mtouch, num_cont, INPUT_MT_DIRECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) input_free_device(mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) xenbus_dev_fatal(info->xbdev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "input_mt_init_slots");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret = input_register_device(mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) input_free_device(mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) xenbus_dev_fatal(info->xbdev, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) "input_register_device(mtouch)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) info->mtouch_cur_contact_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) info->mtouch = mtouch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!(with_kbd || with_ptr || with_mtouch)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = xenkbd_connect_backend(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) error_nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) xenbus_dev_fatal(dev, ret, "allocating device memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) xenkbd_remove(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int xenkbd_resume(struct xenbus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) xenkbd_disconnect_backend(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) memset(info->page, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return xenkbd_connect_backend(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static int xenkbd_remove(struct xenbus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) xenkbd_disconnect_backend(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (info->kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) input_unregister_device(info->kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (info->ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) input_unregister_device(info->ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (info->mtouch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) input_unregister_device(info->mtouch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) free_page((unsigned long)info->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int xenkbd_connect_backend(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct xenkbd_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int ret, evtchn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct xenbus_transaction xbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = gnttab_grant_foreign_access(dev->otherend_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) virt_to_gfn(info->page), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) info->gref = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ret = xenbus_alloc_evtchn(dev, &evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) goto error_grant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 0, dev->devicetype, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto error_evtchan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) info->irq = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ret = xenbus_transaction_start(&xbt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) xenbus_dev_fatal(dev, ret, "starting transaction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto error_irqh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_REF, "%lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) virt_to_gfn(info->page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_GREF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) "%u", info->gref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_EVT_CHANNEL, "%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ret = xenbus_transaction_end(xbt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (ret == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) xenbus_dev_fatal(dev, ret, "completing transaction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) goto error_irqh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) xenbus_switch_state(dev, XenbusStateInitialised);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) error_xenbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) xenbus_transaction_end(xbt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) xenbus_dev_fatal(dev, ret, "writing xenstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) error_irqh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) unbind_from_irqhandler(info->irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) info->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) error_evtchan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) xenbus_free_evtchn(dev, evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) error_grant:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) gnttab_end_foreign_access(info->gref, 0, 0UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) info->gref = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static void xenkbd_disconnect_backend(struct xenkbd_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (info->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unbind_from_irqhandler(info->irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) info->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (info->gref >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) gnttab_end_foreign_access(info->gref, 0, 0UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) info->gref = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void xenkbd_backend_changed(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) enum xenbus_state backend_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) switch (backend_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case XenbusStateInitialising:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) case XenbusStateInitialised:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) case XenbusStateReconfiguring:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case XenbusStateReconfigured:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case XenbusStateUnknown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case XenbusStateInitWait:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) xenbus_switch_state(dev, XenbusStateConnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case XenbusStateConnected:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * Work around xenbus race condition: If backend goes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * through InitWait to Connected fast enough, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * get Connected twice here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (dev->state != XenbusStateConnected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) xenbus_switch_state(dev, XenbusStateConnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case XenbusStateClosed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (dev->state == XenbusStateClosed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) fallthrough; /* Missed the backend's CLOSING state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case XenbusStateClosing:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) xenbus_frontend_closed(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static const struct xenbus_device_id xenkbd_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) { XENKBD_DRIVER_NAME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) { "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static struct xenbus_driver xenkbd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .ids = xenkbd_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .probe = xenkbd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .remove = xenkbd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .resume = xenkbd_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) .otherend_changed = xenkbd_backend_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static int __init xenkbd_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!xen_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* Nothing to do if running in dom0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (xen_initial_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!xen_has_pv_devices())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return xenbus_register_frontend(&xenkbd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) static void __exit xenkbd_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) xenbus_unregister_driver(&xenkbd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) module_init(xenkbd_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) module_exit(xenkbd_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) MODULE_ALIAS("xen:" XENKBD_DRIVER_NAME);