1d514b0f3Smrg/* 2d514b0f3Smrg * Copyright 2011 Red Hat, Inc. 3d514b0f3Smrg * 4d514b0f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5d514b0f3Smrg * copy of this software and associated documentation files (the "Software"), 6d514b0f3Smrg * to deal in the Software without restriction, including without limitation 7d514b0f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 8d514b0f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9d514b0f3Smrg * the Software is furnished to do so, subject to the following conditions: 10d514b0f3Smrg * 11d514b0f3Smrg * The above copyright notice and this permission notice (including the next 12d514b0f3Smrg * paragraph) shall be included in all copies or substantial portions of the 13d514b0f3Smrg * Software. 14d514b0f3Smrg * 15d514b0f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16d514b0f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17d514b0f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18d514b0f3Smrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19d514b0f3Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20d514b0f3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21d514b0f3Smrg */ 22d514b0f3Smrg 23d514b0f3Smrg/* Handle inputs channel for spice, and register the X parts, 24d514b0f3Smrg * a mouse and a keyboard device pair. 25d514b0f3Smrg */ 26d514b0f3Smrg#ifdef HAVE_CONFIG_H 27d514b0f3Smrg#include "config.h" 28d514b0f3Smrg#endif 29d514b0f3Smrg 30d514b0f3Smrg#include <xf86Xinput.h> 31d514b0f3Smrg#include <exevents.h> 32d514b0f3Smrg#include <xserver-properties.h> 33d514b0f3Smrg#include <list.h> 34d514b0f3Smrg#include <input.h> 35d514b0f3Smrg#include <xkbsrv.h> 36d514b0f3Smrg#include <spice.h> 37d514b0f3Smrg#include "qxl.h" 38d514b0f3Smrg#include "spiceqxl_inputs.h" 39d514b0f3Smrg 40d514b0f3Smrgstatic 41d514b0f3Smrgint XSpicePointerPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 42d514b0f3Smrgstatic 43d514b0f3Smrgint XSpiceKeyboardPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 44d514b0f3Smrgstatic 45d514b0f3Smrgvoid XSpicePointerUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 46d514b0f3Smrgstatic 47d514b0f3Smrgvoid XSpiceKeyboardUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 48d514b0f3Smrg 49d514b0f3Smrgstatic char xspice_pointer_name[] = "xspice pointer"; 50d514b0f3Smrgstatic InputDriverRec XSPICE_POINTER = { 51d514b0f3Smrg 1, 52d514b0f3Smrg xspice_pointer_name, 53d514b0f3Smrg NULL, 54d514b0f3Smrg XSpicePointerPreInit, 55d514b0f3Smrg XSpicePointerUnInit, 56d514b0f3Smrg NULL, 57d514b0f3Smrg NULL /* defaults */ 58d514b0f3Smrg}; 59d514b0f3Smrg 60d514b0f3Smrgstatic char xspice_keyboard_name[] = "xspice keyboard"; 61d514b0f3Smrgstatic InputDriverRec XSPICE_KEYBOARD = { 62d514b0f3Smrg 1, 63d514b0f3Smrg xspice_keyboard_name, 64d514b0f3Smrg NULL, 65d514b0f3Smrg XSpiceKeyboardPreInit, 66d514b0f3Smrg XSpiceKeyboardUnInit, 67d514b0f3Smrg NULL, 68d514b0f3Smrg NULL 69d514b0f3Smrg}; 70d514b0f3Smrg 71d514b0f3Smrg#define BUTTONS 5 72d514b0f3Smrg 73d514b0f3Smrgtypedef struct XSpiceKbd { 74d514b0f3Smrg SpiceKbdInstance sin; 75d514b0f3Smrg uint8_t ledstate; 76d514b0f3Smrg InputInfoPtr pInfo; /* xf86 device handle to post events */ 77d514b0f3Smrg /* Note: spice sends some of the keys escaped by this. 78d514b0f3Smrg * This is supposed to be AT key codes, but I can't figure out where that 79d514b0f3Smrg * thing is defined after looking at xf86-input-keyboard. Ended up reverse 80d514b0f3Smrg * engineering a escaped table using xev. 81d514b0f3Smrg */ 82d514b0f3Smrg int escape; 83d514b0f3Smrg} XSpiceKbd; 84d514b0f3Smrg 85d514b0f3Smrgstatic int xspice_pointer_proc(DeviceIntPtr pDevice, int onoff) 86d514b0f3Smrg{ 87d514b0f3Smrg DevicePtr pDev = (DevicePtr)pDevice; 88d514b0f3Smrg BYTE map[BUTTONS + 1]; 89d514b0f3Smrg Atom btn_labels[BUTTONS]; 90d514b0f3Smrg Atom axes_labels[2]; 91d514b0f3Smrg int i; 92d514b0f3Smrg 93d514b0f3Smrg switch (onoff) { 94d514b0f3Smrg case DEVICE_INIT: 95d514b0f3Smrg for (i = 0; i < BUTTONS + 1; i++) { 96d514b0f3Smrg map[i] = i; 97d514b0f3Smrg } 98d514b0f3Smrg btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 99d514b0f3Smrg btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 100d514b0f3Smrg btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 101d514b0f3Smrg btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 102d514b0f3Smrg btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 103d514b0f3Smrg axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 104d514b0f3Smrg axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 105d514b0f3Smrg InitPointerDeviceStruct(pDev, map, BUTTONS,btn_labels,(PtrCtrlProcPtr)NoopDDA, 106d514b0f3Smrg GetMotionHistorySize(), 2, axes_labels); 107d514b0f3Smrg break; 108d514b0f3Smrg case DEVICE_ON: 109d514b0f3Smrg pDev->on = TRUE; 110d514b0f3Smrg break; 111d514b0f3Smrg case DEVICE_OFF: 112d514b0f3Smrg pDev->on = FALSE; 113d514b0f3Smrg break; 114d514b0f3Smrg } 115d514b0f3Smrg return Success; 116d514b0f3Smrg} 117d514b0f3Smrg 118d514b0f3Smrgstatic void xspice_keyboard_bell(int percent, DeviceIntPtr device, pointer ctrl, int class_) 119d514b0f3Smrg{ 120d514b0f3Smrg} 121d514b0f3Smrg 122d514b0f3Smrg#define CAPSFLAG 1 123d514b0f3Smrg#define NUMFLAG 2 124d514b0f3Smrg#define SCROLLFLAG 4 125d514b0f3Smrg/* MODEFLAG and COMPOSEFLAG currently unused (reminder for future) */ 126d514b0f3Smrg#define MODEFLAG 8 127d514b0f3Smrg#define COMPOSEFLAG 16 128d514b0f3Smrg 129d514b0f3Smrg#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) 130d514b0f3Smrg 131d514b0f3Smrgstatic void xspice_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl) 132d514b0f3Smrg{ 133d514b0f3Smrg static struct { int xbit, code; } bits[] = { 134d514b0f3Smrg { CAPSFLAG, SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK }, 135d514b0f3Smrg { NUMFLAG, SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK }, 136d514b0f3Smrg { SCROLLFLAG, SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK }, 137d514b0f3Smrg /* TODO: there is no MODEFLAG nor COMPOSEFLAG in SPICE. */ 138d514b0f3Smrg }; 139d514b0f3Smrg 140d514b0f3Smrg XSpiceKbd *kbd; 141d514b0f3Smrg InputInfoPtr pInfo; 142d514b0f3Smrg int i; 143d514b0f3Smrg 144d514b0f3Smrg pInfo = device->public.devicePrivate; 145d514b0f3Smrg kbd = pInfo->private; 146d514b0f3Smrg kbd->ledstate = 0; 147d514b0f3Smrg for (i = 0; i < ArrayLength(bits); i++) { 148d514b0f3Smrg if (ctrl->leds & bits[i].xbit) { 149d514b0f3Smrg kbd->ledstate |= bits[i].code; 150d514b0f3Smrg } else { 151d514b0f3Smrg kbd->ledstate &= ~bits[i].code; 152d514b0f3Smrg } 153d514b0f3Smrg } 154d514b0f3Smrg} 155d514b0f3Smrg 156d514b0f3Smrgstatic char xspice_keyboard_rules[] = "evdev"; 157d514b0f3Smrgstatic char xspice_keyboard_model[] = "pc105"; 158d514b0f3Smrgstatic char xspice_keyboard_layout[] = "us"; 159d514b0f3Smrgstatic char xspice_keyboard_variant[] = ""; 160d514b0f3Smrgstatic char xspice_keyboard_options[] = ""; 161d514b0f3Smrgstatic int xspice_keyboard_proc(DeviceIntPtr pDevice, int onoff) 162d514b0f3Smrg{ 163d514b0f3Smrg DevicePtr pDev = (DevicePtr)pDevice; 164d514b0f3Smrg XkbRMLVOSet rmlvo = { 165d514b0f3Smrg .rules = xspice_keyboard_rules, 166d514b0f3Smrg .model = xspice_keyboard_model, 167d514b0f3Smrg .layout = xspice_keyboard_layout, 168d514b0f3Smrg .variant = xspice_keyboard_variant, 169d514b0f3Smrg .options = xspice_keyboard_options, 170d514b0f3Smrg }; 171d514b0f3Smrg 172d514b0f3Smrg switch (onoff) { 173d514b0f3Smrg case DEVICE_INIT: 174d514b0f3Smrg InitKeyboardDeviceStruct( 175d514b0f3Smrg pDevice, &rmlvo, xspice_keyboard_bell, xspice_keyboard_control 176d514b0f3Smrg ); 177d514b0f3Smrg break; 178d514b0f3Smrg case DEVICE_ON: 179d514b0f3Smrg pDev->on = TRUE; 180d514b0f3Smrg break; 181d514b0f3Smrg case DEVICE_OFF: 182d514b0f3Smrg pDev->on = FALSE; 183d514b0f3Smrg break; 184d514b0f3Smrg } 185d514b0f3Smrg return Success; 186d514b0f3Smrg} 187d514b0f3Smrg 188d514b0f3Smrg/* from spice-input.c */ 189d514b0f3Smrg/* keyboard bits */ 190d514b0f3Smrg 191d514b0f3Smrgstatic void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag); 192d514b0f3Smrgstatic uint8_t kbd_get_leds(SpiceKbdInstance *sin); 193d514b0f3Smrg 194d514b0f3Smrgstatic const SpiceKbdInterface kbd_interface = { 195d514b0f3Smrg .base.type = SPICE_INTERFACE_KEYBOARD, 196d514b0f3Smrg .base.description = "xspice keyboard", 197d514b0f3Smrg .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR, 198d514b0f3Smrg .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR, 199d514b0f3Smrg .push_scan_freg = kbd_push_key, 200d514b0f3Smrg .get_leds = kbd_get_leds, 201d514b0f3Smrg}; 202d514b0f3Smrg 203d514b0f3Smrg/* spice sends AT scancodes (with a strange escape). 204d514b0f3Smrg * But xf86PostKeyboardEvent expects scancodes. Apparently most of the time 205d514b0f3Smrg * you just need to add MIN_KEYCODE, see xf86-input-keyboard/src/atKeynames 206d514b0f3Smrg * and xf86-input-keyboard/src/kbd.c:PostKbdEvent: 207d514b0f3Smrg * xf86PostKeyboardEvent(device, scanCode + MIN_KEYCODE, down); */ 208d514b0f3Smrg#define MIN_KEYCODE 8 209d514b0f3Smrg 210d514b0f3Smrgstatic uint8_t escaped_map[256] = { 211d514b0f3Smrg [0x1c] = 104, //KEY_KP_Enter, 212d514b0f3Smrg [0x1d] = 105, //KEY_RCtrl, 213d514b0f3Smrg [0x2a] = 0,//KEY_LMeta, // REDKEY_FAKE_L_SHIFT 214d514b0f3Smrg [0x35] = 106,//KEY_KP_Divide, 215d514b0f3Smrg [0x36] = 0,//KEY_RMeta, // REDKEY_FAKE_R_SHIFT 216d514b0f3Smrg [0x37] = 107,//KEY_Print, 217d514b0f3Smrg [0x38] = 108,//KEY_AltLang, 218d514b0f3Smrg [0x46] = 127,//KEY_Break, 219d514b0f3Smrg [0x47] = 110,//KEY_Home, 220d514b0f3Smrg [0x48] = 111,//KEY_Up, 221d514b0f3Smrg [0x49] = 112,//KEY_PgUp, 222d514b0f3Smrg [0x4b] = 113,//KEY_Left, 223d514b0f3Smrg [0x4d] = 114,//KEY_Right, 224d514b0f3Smrg [0x4f] = 115,//KEY_End, 225d514b0f3Smrg [0x50] = 116,//KEY_Down, 226d514b0f3Smrg [0x51] = 117,//KEY_PgDown, 227d514b0f3Smrg [0x52] = 118,//KEY_Insert, 228d514b0f3Smrg [0x53] = 119,//KEY_Delete, 229d514b0f3Smrg [0x5b] = 133,//0, // REDKEY_LEFT_CMD, 230d514b0f3Smrg [0x5c] = 134,//0, // REDKEY_RIGHT_CMD, 231d514b0f3Smrg [0x5d] = 135,//KEY_Menu, 232d514b0f3Smrg}; 233d514b0f3Smrg 234d514b0f3Smrgstatic void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag) 235d514b0f3Smrg{ 236d514b0f3Smrg XSpiceKbd *kbd = container_of(sin, XSpiceKbd, sin); 237d514b0f3Smrg int is_down; 238d514b0f3Smrg 239d514b0f3Smrg if (frag == 224) { 240d514b0f3Smrg kbd->escape = frag; 241d514b0f3Smrg return; 242d514b0f3Smrg } 243d514b0f3Smrg is_down = frag & 0x80 ? FALSE : TRUE; 244d514b0f3Smrg frag = frag & 0x7f; 245d514b0f3Smrg if (kbd->escape == 224) { 246d514b0f3Smrg kbd->escape = 0; 247d514b0f3Smrg if (escaped_map[frag] == 0) { 248d514b0f3Smrg fprintf(stderr, "spiceqxl_inputs.c: kbd_push_key: escaped_map[%d] == 0\n", frag); 249d514b0f3Smrg } 250d514b0f3Smrg frag = escaped_map[frag]; 251d514b0f3Smrg } else { 252d514b0f3Smrg frag += MIN_KEYCODE; 253d514b0f3Smrg } 254d514b0f3Smrg 255d514b0f3Smrg xf86PostKeyboardEvent(kbd->pInfo->dev, frag, is_down); 256d514b0f3Smrg} 257d514b0f3Smrg 258d514b0f3Smrgstatic uint8_t kbd_get_leds(SpiceKbdInstance *sin) 259d514b0f3Smrg{ 260d514b0f3Smrg XSpiceKbd *kbd = container_of(sin, XSpiceKbd, sin); 261d514b0f3Smrg 262d514b0f3Smrg return kbd->ledstate; 263d514b0f3Smrg} 264d514b0f3Smrg 265d514b0f3Smrg/* mouse bits */ 266d514b0f3Smrg 267d514b0f3Smrgtypedef struct XSpicePointer { 268d514b0f3Smrg SpiceMouseInstance mouse; 269d514b0f3Smrg SpiceTabletInstance tablet; 270d514b0f3Smrg int width, height, x, y; 271d514b0f3Smrg Bool absolute; 272d514b0f3Smrg InputInfoPtr pInfo; /* xf86 device handle to post events */ 273d514b0f3Smrg} XSpicePointer; 274d514b0f3Smrg 275d514b0f3Smrgstatic XSpicePointer *g_xspice_pointer; 276d514b0f3Smrg 277d514b0f3Smrgstatic void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz, 278d514b0f3Smrg uint32_t buttons_state) 279d514b0f3Smrg{ 280d514b0f3Smrg // TODO 281d514b0f3Smrg} 282d514b0f3Smrg 283d514b0f3Smrgstatic void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state) 284d514b0f3Smrg{ 285d514b0f3Smrg // TODO 286d514b0f3Smrg} 287d514b0f3Smrg 288d514b0f3Smrgstatic const SpiceMouseInterface mouse_interface = { 289d514b0f3Smrg .base.type = SPICE_INTERFACE_MOUSE, 290d514b0f3Smrg .base.description = "xspice mouse", 291d514b0f3Smrg .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR, 292d514b0f3Smrg .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR, 293d514b0f3Smrg .motion = mouse_motion, 294d514b0f3Smrg .buttons = mouse_buttons, 295d514b0f3Smrg}; 296d514b0f3Smrg 297d514b0f3Smrgstatic void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height) 298d514b0f3Smrg{ 299d514b0f3Smrg XSpicePointer *spice_pointer = container_of(sin, XSpicePointer, tablet); 300d514b0f3Smrg 301d514b0f3Smrg if (height < 16) { 302d514b0f3Smrg height = 16; 303d514b0f3Smrg } 304d514b0f3Smrg if (width < 16) { 305d514b0f3Smrg width = 16; 306d514b0f3Smrg } 307d514b0f3Smrg spice_pointer->width = width; 308d514b0f3Smrg spice_pointer->height = height; 309d514b0f3Smrg} 310d514b0f3Smrg 311d514b0f3Smrgvoid spiceqxl_tablet_position(int x, int y, uint32_t buttons_state) 312d514b0f3Smrg{ 313d514b0f3Smrg // TODO: don't ignore buttons_state 314d514b0f3Smrg xf86PostMotionEvent(g_xspice_pointer->pInfo->dev, 1, 0, 2, x, y); 315d514b0f3Smrg} 316d514b0f3Smrg 317d514b0f3Smrgstatic void tablet_position(SpiceTabletInstance* sin, int x, int y, 318d514b0f3Smrg uint32_t buttons_state) 319d514b0f3Smrg{ 320d514b0f3Smrg spiceqxl_tablet_position(x, y, buttons_state); 321d514b0f3Smrg} 322d514b0f3Smrg 323d514b0f3Smrgvoid spiceqxl_tablet_buttons(uint32_t buttons_state) 324d514b0f3Smrg{ 325d514b0f3Smrg static uint32_t old_buttons_state = 0; 326d514b0f3Smrg int i; 327d514b0f3Smrg 328d514b0f3Smrg for (i = 0; i < BUTTONS; i++) { 329d514b0f3Smrg if ((buttons_state ^ old_buttons_state) & (1 << i)) { 330d514b0f3Smrg int action = (buttons_state & (1 << i)); 331d514b0f3Smrg xf86PostButtonEvent(g_xspice_pointer->pInfo->dev, 0, i + 1, action, 0, 0); 332d514b0f3Smrg } 333d514b0f3Smrg } 334d514b0f3Smrg old_buttons_state = buttons_state; 335d514b0f3Smrg} 336d514b0f3Smrg 337d514b0f3Smrgstatic void tablet_buttons(SpiceTabletInstance *sin, 338d514b0f3Smrg uint32_t buttons_state) 339d514b0f3Smrg{ 340d514b0f3Smrg // For some reason spice switches the second and third button, undo that. 341d514b0f3Smrg // basically undo RED_MOUSE_STATE_TO_LOCAL 342d514b0f3Smrg buttons_state = (buttons_state & SPICE_MOUSE_BUTTON_MASK_LEFT) | 343d514b0f3Smrg ((buttons_state & SPICE_MOUSE_BUTTON_MASK_MIDDLE) << 1) | 344d514b0f3Smrg ((buttons_state & SPICE_MOUSE_BUTTON_MASK_RIGHT) >> 1) | 345d514b0f3Smrg (buttons_state & ~(SPICE_MOUSE_BUTTON_MASK_LEFT | SPICE_MOUSE_BUTTON_MASK_MIDDLE 346d514b0f3Smrg |SPICE_MOUSE_BUTTON_MASK_RIGHT)); 347d514b0f3Smrg spiceqxl_tablet_buttons(buttons_state); 348d514b0f3Smrg} 349d514b0f3Smrg 350d514b0f3Smrgstatic void tablet_wheel(SpiceTabletInstance* sin, int wheel, 351d514b0f3Smrg uint32_t buttons_state) 352d514b0f3Smrg{ 353d514b0f3Smrg // convert wheel into fourth and fifth buttons 354d514b0f3Smrg tablet_buttons(sin, buttons_state 355d514b0f3Smrg | (wheel > 0 ? (1<<4) : 0) 356d514b0f3Smrg | (wheel < 0 ? (1<<3) : 0)); 357d514b0f3Smrg} 358d514b0f3Smrg 359d514b0f3Smrgstatic const SpiceTabletInterface tablet_interface = { 360d514b0f3Smrg .base.type = SPICE_INTERFACE_TABLET, 361d514b0f3Smrg .base.description = "xspice tablet", 362d514b0f3Smrg .base.major_version = SPICE_INTERFACE_TABLET_MAJOR, 363d514b0f3Smrg .base.minor_version = SPICE_INTERFACE_TABLET_MINOR, 364d514b0f3Smrg .set_logical_size = tablet_set_logical_size, 365d514b0f3Smrg .position = tablet_position, 366d514b0f3Smrg .wheel = tablet_wheel, 367d514b0f3Smrg .buttons = tablet_buttons, 368d514b0f3Smrg}; 369d514b0f3Smrg 370d514b0f3Smrgstatic char unknown_type_string[] = "UNKNOWN"; 371d514b0f3Smrg 372d514b0f3Smrgstatic int 373d514b0f3SmrgXSpiceKeyboardPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 374d514b0f3Smrg{ 375d514b0f3Smrg XSpiceKbd *kbd; 376d514b0f3Smrg 377d514b0f3Smrg kbd = calloc(sizeof(*kbd), 1); 378d514b0f3Smrg kbd->sin.base.sif = &kbd_interface.base; 379d514b0f3Smrg kbd->pInfo = pInfo; 380d514b0f3Smrg 381d514b0f3Smrg pInfo->private = kbd; 382d514b0f3Smrg pInfo->type_name = unknown_type_string; 383d514b0f3Smrg pInfo->device_control = xspice_keyboard_proc; 384d514b0f3Smrg pInfo->read_input = NULL; 385d514b0f3Smrg pInfo->switch_mode = NULL; 386d514b0f3Smrg 387d514b0f3Smrg spice_server_add_interface(xspice_get_spice_server(), &kbd->sin.base); 388d514b0f3Smrg return Success; 389d514b0f3Smrg} 390d514b0f3Smrg 391d514b0f3Smrgstatic int 392d514b0f3SmrgXSpicePointerPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 393d514b0f3Smrg{ 394d514b0f3Smrg XSpicePointer *spice_pointer; 395d514b0f3Smrg 396d514b0f3Smrg g_xspice_pointer = spice_pointer = calloc(sizeof(*spice_pointer), 1); 397d514b0f3Smrg spice_pointer->mouse.base.sif = &mouse_interface.base; 398d514b0f3Smrg spice_pointer->tablet.base.sif = &tablet_interface.base; 399d514b0f3Smrg spice_pointer->absolute = TRUE; 400d514b0f3Smrg spice_pointer->pInfo = pInfo; 401d514b0f3Smrg 402d514b0f3Smrg pInfo->private = NULL; 403d514b0f3Smrg pInfo->type_name = unknown_type_string; 404d514b0f3Smrg pInfo->device_control = xspice_pointer_proc; 405d514b0f3Smrg pInfo->read_input = NULL; 406d514b0f3Smrg pInfo->switch_mode = NULL; 407d514b0f3Smrg 408d514b0f3Smrg spice_server_add_interface(xspice_get_spice_server(), &spice_pointer->tablet.base); 409d514b0f3Smrg return Success; 410d514b0f3Smrg} 411d514b0f3Smrg 412d514b0f3Smrgstatic void 413d514b0f3SmrgXSpicePointerUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 414d514b0f3Smrg{ 415d514b0f3Smrg} 416d514b0f3Smrg 417d514b0f3Smrgstatic void 418d514b0f3SmrgXSpiceKeyboardUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 419d514b0f3Smrg{ 420d514b0f3Smrg} 421d514b0f3Smrg 422d514b0f3Smrgvoid xspice_add_input_drivers(pointer module) 423d514b0f3Smrg{ 424d514b0f3Smrg xf86AddInputDriver(&XSPICE_POINTER, module, 0); 425d514b0f3Smrg xf86AddInputDriver(&XSPICE_KEYBOARD, module, 0); 426d514b0f3Smrg} 427