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