On Tue, Jul 10, 2012 at 02:44:53AM +0600, Alexandr Shadchin wrote:
> On Mon, Jul 09, 2012 at 10:35:55PM +0600, Alexandr Shadchin wrote:
> > Add functional xf86-input-keyboard in xf86-input-ws (no new features)
> > 
> > For test add or rewrite xorg.conf:
> > 
> > Section "InputClass"
> >     Identifier "keyboard defaults"
> >     MatchIsKeyboard "on"
> > 
> >     Driver "ws"
> >     Option "Device" "/dev/wskbd"
> > 
> >     Option "XkbModel" "your setting"
> >     Option "XkbLayout" "your setting"
> >     Option "XkbVariant" "your setting"
> >     Option "XKbOptions" "your setting"
> > EndSection
> > 
> > Welcome any feedback.
> > 
> 
> Fix decode extra keys (ex. multimedia)
> 

Suggestion mpi@: 
allocate memory only for pointer device or keyboard
(but not both together)

-- 
Alexandr Shadchin

Index: man/ws.man
===================================================================
RCS file: /cvs/xenocara/driver/xf86-input-ws/man/ws.man,v
retrieving revision 1.13
diff -u -p -r1.13 ws.man
--- man/ws.man  12 Jun 2012 17:12:50 -0000      1.13
+++ man/ws.man  11 Jul 2012 12:28:19 -0000
@@ -199,6 +199,38 @@ is mapped to the negative W axis motion 
 .I N2
 is mapped to the positive W axis motion.
 Default:\ "6\ 7".
+.TP 4
+.BI "Option \*qXkbRules\*q \*q" rules \*q
+Specifies which XKB rules file to use for interpreting the
+.BR XkbModel ,
+.BR XkbLayout ,
+.BR XkbVariant ,
+and
+.B XkbOptions
+settings.
+Default:\ "base".
+.TP 4
+.BI "Option \*qXkbModel\*q \*q" modelname \*q
+Specifies the XKB keyboard model name.
+Default:\ "pc105".
+.TP 4
+.BI "Option \*qXkbLayout\*q \*q" layoutname \*q
+Specifies the XKB keyboard layout name.
+This is usually the country or language type of the keyboard.
+Default:\ "us".
+.TP 4
+.BI "Option \*qXkbVariant\*q \*q" variants \*q
+Specifies the XKB keyboard variant components.
+These can be used to enhance the keyboard layout details.
+Default:\ not\ set.
+.TP 4
+.BI "Option \*qXkbOptions\*q \*q" options \*q
+Specifies the XKB keyboard option components.
+These can be used to enhance the keyboard behaviour.
+Default:\ not\ set.
+.PP
+For a list of available XKB options, see
+.B xkeyboard-config(__miscmansuffix__).
 .SH "SUPPORTED PROPERTIES"
 The following properties are provided by the
 .B ws
Index: src/emumb.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-input-ws/src/emumb.c,v
retrieving revision 1.13
diff -u -p -r1.13 emumb.c
--- src/emumb.c 8 Jul 2012 14:22:03 -0000       1.13
+++ src/emumb.c 11 Jul 2012 12:28:19 -0000
@@ -54,7 +54,7 @@ enum {
        MBEMU_AUTO
 };
 
-static Atom prop_mbemu;                /* Middle button emulation on/off 
property */
+static Atom prop_mbemu;        /* Middle button emulation on/off property */
 static Atom prop_mbtimeout;    /* Middle button timeout property */
 
 /*
@@ -194,20 +194,21 @@ static signed char stateTab[11][5][3] = 
 int
 wsmbEmuTimer(InputInfoPtr pInfo)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int sigstate;
        int id;
 
        sigstate = xf86BlockSIGIO();
 
-       priv->emulateMB.pending = FALSE;
-       if ((id = stateTab[priv->emulateMB.state][4][0]) != 0) {
+       cursor->emulateMB.pending = FALSE;
+       if ((id = stateTab[cursor->emulateMB.state][4][0]) != 0) {
                xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
-               priv->emulateMB.state = stateTab[priv->emulateMB.state][4][2];
+               cursor->emulateMB.state =
+                   stateTab[cursor->emulateMB.state][4][2];
        } else {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "Got unexpected buttonTimer in state %d\n",
-                   priv->emulateMB.state);
+                   cursor->emulateMB.state);
        }
 
        xf86UnblockSIGIO(sigstate);
@@ -226,17 +227,17 @@ wsmbEmuTimer(InputInfoPtr pInfo)
 BOOL
 wsmbEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int id;
        int *btstate;
        int ret = FALSE;
 
-       if (!priv->emulateMB.enabled)
+       if (!cursor->emulateMB.enabled)
                return ret;
 
        /* Disable emulation when middle button event is detected */
-       if (button == 2 && priv->emulateMB.enabled == MBEMU_AUTO) {
-               priv->emulateMB.enabled = FALSE;
+       if (button == 2 && cursor->emulateMB.enabled == MBEMU_AUTO) {
+               cursor->emulateMB.enabled = FALSE;
                return ret;
        }
 
@@ -244,30 +245,31 @@ wsmbEmuFilterEvent(InputInfoPtr pInfo, i
        if (button != 1 && button != 3)
                return ret;
 
-       btstate = &priv->emulateMB.buttonstate;
+       btstate = &cursor->emulateMB.buttonstate;
        if (press)
                *btstate |= (button == 1) ? 0x1 : 0x2;
        else
                *btstate &= (button == 1) ? ~0x1 : ~0x2;
 
-       if ((id = stateTab[priv->emulateMB.state][*btstate][0]) != 0) {
+       if ((id = stateTab[cursor->emulateMB.state][*btstate][0]) != 0) {
                xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
                ret = TRUE;
        }
-       if ((id = stateTab[priv->emulateMB.state][*btstate][1]) != 0) {
+       if ((id = stateTab[cursor->emulateMB.state][*btstate][1]) != 0) {
                xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
                ret = TRUE;
        }
 
-       priv->emulateMB.state = stateTab[priv->emulateMB.state][*btstate][2];
+       cursor->emulateMB.state =
+           stateTab[cursor->emulateMB.state][*btstate][2];
 
-       if (stateTab[priv->emulateMB.state][4][0] != 0) {
-               priv->emulateMB.expires = GetTimeInMillis()
-                   + priv->emulateMB.timeout;
-               priv->emulateMB.pending = TRUE;
+       if (stateTab[cursor->emulateMB.state][4][0] != 0) {
+               cursor->emulateMB.expires = GetTimeInMillis()
+                   + cursor->emulateMB.timeout;
+               cursor->emulateMB.pending = TRUE;
                ret = TRUE;
        } else {
-               priv->emulateMB.pending = FALSE;
+               cursor->emulateMB.pending = FALSE;
        }
        return ret;
 }
@@ -276,11 +278,11 @@ void
 wsmbEmuWakeupHandler(pointer data, int i, pointer LastSelectMask)
 {
        InputInfoPtr pInfo = (InputInfoPtr)data;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int ms;
 
-       if (priv->emulateMB.pending) {
-               ms = priv->emulateMB.expires - GetTimeInMillis();
+       if (cursor->emulateMB.pending) {
+               ms = cursor->emulateMB.expires - GetTimeInMillis();
                if (ms <= 0)
                        wsmbEmuTimer(pInfo);
        }
@@ -291,11 +293,11 @@ wsmbEmuBlockHandler(pointer data, struct
     pointer LastSelectMask)
 {
        InputInfoPtr pInfo = (InputInfoPtr)data;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int ms;
 
-       if (priv->emulateMB.pending) {
-               ms = priv->emulateMB.expires - GetTimeInMillis();
+       if (cursor->emulateMB.pending) {
+               ms = cursor->emulateMB.expires - GetTimeInMillis();
                if (ms <= 0)
                        ms = 0;
                AdjustWaitForDelay(waitTime, ms);
@@ -305,19 +307,19 @@ wsmbEmuBlockHandler(pointer data, struct
 void
 wsmbEmuPreInit(InputInfoPtr pInfo)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int timeout;
 
        DBG(1, ErrorF("wsmbEmuPreInit\n"));
 
-       priv->emulateMB.enabled = MBEMU_AUTO;
+       cursor->emulateMB.enabled = MBEMU_AUTO;
        if (xf86FindOption(pInfo->options, "Emulate3Buttons")) {
-               priv->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
+               cursor->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
                    "Emulate3Buttons",
                    MBEMU_ENABLED);
                xf86IDrvMsg(pInfo, X_INFO, "Forcing middle mouse button "
                    "emulation %s.\n",
-                   (priv->emulateMB.enabled) ? "on" : "off");
+                   (cursor->emulateMB.enabled) ? "on" : "off");
        }
 
        timeout = xf86SetIntOption(pInfo->options, "Emulate3Timeout", 50);
@@ -327,7 +329,7 @@ wsmbEmuPreInit(InputInfoPtr pInfo)
                xf86IDrvMsg(pInfo, X_WARNING, "Using built-in timeout value\n");
                timeout = 50;
        }
-       priv->emulateMB.timeout = timeout;
+       cursor->emulateMB.timeout = timeout;
 }
 
 void
@@ -349,7 +351,7 @@ wsmbEmuSetProperty(DeviceIntPtr dev, Ato
     BOOL checkonly)
 {
        InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
 
        DBG(1, ErrorF("wsmbEmuSetProperty %s\n", NameForAtom(atom)));
 
@@ -359,7 +361,7 @@ wsmbEmuSetProperty(DeviceIntPtr dev, Ato
                        return BadMatch;
 
                if (!checkonly)
-                       priv->emulateMB.enabled = *((BOOL*)val->data);
+                       cursor->emulateMB.enabled = *((BOOL*)val->data);
        } else if (atom == prop_mbtimeout) {
                int timeout;
 
@@ -373,7 +375,7 @@ wsmbEmuSetProperty(DeviceIntPtr dev, Ato
                        return BadValue;
 
                if (!checkonly)
-                       priv->emulateMB.timeout = timeout;
+                       cursor->emulateMB.timeout = timeout;
        }
 
        return Success;
@@ -386,7 +388,7 @@ void
 wsmbEmuInitProperty(DeviceIntPtr dev)
 {
        InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int rc;
 
        DBG(1, ErrorF("wsmbEmuInitProperty\n"));
@@ -394,7 +396,7 @@ wsmbEmuInitProperty(DeviceIntPtr dev)
        prop_mbemu = MakeAtom(WS_PROP_MIDBUTTON,
            strlen(WS_PROP_MIDBUTTON), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_mbemu, XA_INTEGER, 8,
-           PropModeReplace, 1, &priv->emulateMB.enabled, FALSE);
+           PropModeReplace, 1, &cursor->emulateMB.enabled, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -406,7 +408,7 @@ wsmbEmuInitProperty(DeviceIntPtr dev)
        prop_mbtimeout = MakeAtom(WS_PROP_MIDBUTTON_TIMEOUT,
            strlen(WS_PROP_MIDBUTTON_TIMEOUT), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_mbtimeout, XA_INTEGER, 32,
-           PropModeReplace, 1, &priv->emulateMB.timeout, FALSE);
+           PropModeReplace, 1, &cursor->emulateMB.timeout, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
Index: src/emuwheel.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-input-ws/src/emuwheel.c,v
retrieving revision 1.2
diff -u -p -r1.2 emuwheel.c
--- src/emuwheel.c      8 Jul 2012 13:51:11 -0000       1.2
+++ src/emuwheel.c      11 Jul 2012 12:28:19 -0000
@@ -61,20 +61,20 @@ static int wsWheelEmuSetProperty(DeviceI
 BOOL
 wsWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int press)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int ms;
 
-       if (!priv->emulateWheel.enabled)
+       if (!cursor->emulateWheel.enabled)
                return FALSE;
 
-       if (priv->emulateWheel.button == button) {
-               priv->emulateWheel.button_state = press;
+       if (cursor->emulateWheel.button == button) {
+               cursor->emulateWheel.button_state = press;
 
                if (press) {
-                       priv->emulateWheel.expires = GetTimeInMillis() +
-                           priv->emulateWheel.timeout;
+                       cursor->emulateWheel.expires = GetTimeInMillis() +
+                           cursor->emulateWheel.timeout;
                } else {
-                       ms = priv->emulateWheel.expires - GetTimeInMillis();
+                       ms = cursor->emulateWheel.expires - GetTimeInMillis();
 
                        if (ms > 0) {
                                /*
@@ -94,40 +94,42 @@ wsWheelEmuFilterButton(InputInfoPtr pInf
 BOOL
 wsWheelEmuFilterMotion(InputInfoPtr pInfo, int dx, int dy)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        WheelAxisPtr pAxis = NULL, pOtherAxis = NULL;
        int value;
 
-       if (!priv->emulateWheel.enabled)
+       if (!cursor->emulateWheel.enabled)
                return FALSE;
 
        /*
         * Handle our motion events if the emuWheel button is pressed.
         * Wheel button of 0 means always emulate wheel.
         */
-       if (priv->emulateWheel.button_state || priv->emulateWheel.button == 0) {
-               if (priv->emulateWheel.button) {
-                       int ms = priv->emulateWheel.expires - GetTimeInMillis();
+       if (cursor->emulateWheel.button_state ||
+           cursor->emulateWheel.button == 0) {
+               if (cursor->emulateWheel.button) {
+                       int ms =
+                           cursor->emulateWheel.expires - GetTimeInMillis();
 
                        if (ms > 0)
                                return TRUE;
                }
 
                if (dx) {
-                       pAxis = &(priv->emulateWheel.X);
-                       pOtherAxis = &(priv->emulateWheel.Y);
+                       pAxis = &(cursor->emulateWheel.X);
+                       pOtherAxis = &(cursor->emulateWheel.Y);
                        value = dx;
                } else if (dy) {
-                       pAxis = &(priv->emulateWheel.Y);
-                       pOtherAxis = &(priv->emulateWheel.X);
+                       pAxis = &(cursor->emulateWheel.Y);
+                       pOtherAxis = &(cursor->emulateWheel.X);
                        value = dy;
                } else
                        return FALSE;
 
                /*
                 * Reset the inertia of the other axis when a scroll event
-                * was sent to avoid the buildup of erroneous scroll events if 
the
-                * user doesn't move in a perfectly straight line.
+                * was sent to avoid the buildup of erroneous scroll events if
+                * the user doesn't move in a perfectly straight line.
                 */
                if (pAxis) {
                        if (wsWheelEmuInertia(pInfo, pAxis, value))
@@ -143,7 +145,7 @@ wsWheelEmuFilterMotion(InputInfoPtr pInf
 static int
 wsWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int button, inertia;
        int rc = 0;
 
@@ -154,13 +156,13 @@ wsWheelEmuInertia(InputInfoPtr pInfo, Wh
 
        if (axis->traveled_distance < 0) {
                button = axis->negative;
-               inertia = -priv->emulateWheel.inertia;
+               inertia = -cursor->emulateWheel.inertia;
        } else {
                button = axis->positive;
-               inertia = priv->emulateWheel.inertia;
+               inertia = cursor->emulateWheel.inertia;
        }
 
-       while (abs(axis->traveled_distance) > priv->emulateWheel.inertia) {
+       while (abs(axis->traveled_distance) > cursor->emulateWheel.inertia) {
                axis->traveled_distance -= inertia;
                wsButtonClicks(pInfo, button, 1);
                rc++;
@@ -172,21 +174,21 @@ wsWheelEmuInertia(InputInfoPtr pInfo, Wh
 void
 wsWheelEmuPreInit(InputInfoPtr pInfo)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int button, inertia, timeout;
 
-       priv->emulateWheel.enabled = xf86SetBoolOption(pInfo->options,
+       cursor->emulateWheel.enabled = xf86SetBoolOption(pInfo->options,
            "EmulateWheel", FALSE);
 
        button = xf86SetIntOption(pInfo->options, "EmulateWheelButton", 4);
-       if (button < 0 || button > NBUTTONS) {
+       if (button < 0 || button > MAXBUTTONS) {
                xf86IDrvMsg(pInfo, X_WARNING,
                    "Invalid EmulateWheelButton value: %d\n", button);
                xf86IDrvMsg(pInfo, X_WARNING, "Wheel emulation disabled\n");
-               priv->emulateWheel.enabled = FALSE;
+               cursor->emulateWheel.enabled = FALSE;
                button = 4;
        }
-       priv->emulateWheel.button = button;
+       cursor->emulateWheel.button = button;
 
        inertia = xf86SetIntOption(pInfo->options, "EmulateWheelInertia", 10);
        if (inertia <= 0) {
@@ -195,7 +197,7 @@ wsWheelEmuPreInit(InputInfoPtr pInfo)
                xf86IDrvMsg(pInfo, X_WARNING, "Using built-in inertia value\n");
                inertia = 10;
        }
-       priv->emulateWheel.inertia = inertia;
+       cursor->emulateWheel.inertia = inertia;
 
        timeout = xf86SetIntOption(pInfo->options, "EmulateWheelTimeout", 200);
        if (timeout < 0) {
@@ -204,11 +206,11 @@ wsWheelEmuPreInit(InputInfoPtr pInfo)
                xf86IDrvMsg(pInfo, X_WARNING, "Using built-in timeout value\n");
                timeout = 200;
        }
-       priv->emulateWheel.timeout = timeout;
+       cursor->emulateWheel.timeout = timeout;
 
-       wsWheelHandleButtonMap(pInfo, &(priv->emulateWheel.Y),
+       wsWheelHandleButtonMap(pInfo, &(cursor->emulateWheel.Y),
            "YAxisMapping", "4 5");
-       wsWheelHandleButtonMap(pInfo, &(priv->emulateWheel.X),
+       wsWheelHandleButtonMap(pInfo, &(cursor->emulateWheel.X),
            "XAxisMapping", NULL);
 }
 
@@ -217,7 +219,7 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
     BOOL checkonly)
 {
        InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
 
        if (atom == prop_wheel_emu) {
                if (val->format != 8 || val->size != 1 ||
@@ -225,7 +227,7 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
                        return BadMatch;
 
                if (!checkonly)
-                       priv->emulateWheel.enabled = *((BOOL*)val->data);
+                       cursor->emulateWheel.enabled = *((BOOL*)val->data);
        } else if (atom == prop_wheel_button) {
                int button;
 
@@ -235,11 +237,11 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
 
                button = *((CARD8*)val->data);
 
-               if (button < 0 || button > NBUTTONS)
+               if (button < 0 || button > MAXBUTTONS)
                        return BadValue;
 
                if (!checkonly)
-                       priv->emulateWheel.button = button;
+                       cursor->emulateWheel.button = button;
        } else if (atom == prop_wheel_axismap) {
                int x_negative, x_positive;
                int y_negative, y_positive;
@@ -253,10 +255,10 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
                y_negative = *(((CARD8*)val->data) + 2);
                y_positive = *(((CARD8*)val->data) + 3);
 
-               if (x_negative < 0 || x_negative > NBUTTONS ||
-                   x_positive < 0 || x_positive > NBUTTONS ||
-                   y_negative < 0 || y_negative > NBUTTONS ||
-                   y_positive < 0 || y_positive > NBUTTONS)
+               if (x_negative < 0 || x_negative > MAXBUTTONS ||
+                   x_positive < 0 || x_positive > MAXBUTTONS ||
+                   y_negative < 0 || y_negative > MAXBUTTONS ||
+                   y_positive < 0 || y_positive > MAXBUTTONS)
                        return BadValue;
 
                if ((x_negative == WS_NOMAP && x_positive != WS_NOMAP) ||
@@ -266,10 +268,10 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
                        return BadValue;
 
                if (!checkonly) {
-                       priv->emulateWheel.X.negative = x_negative;
-                       priv->emulateWheel.X.positive = x_positive;
-                       priv->emulateWheel.Y.negative = y_negative;
-                       priv->emulateWheel.Y.positive = y_positive;
+                       cursor->emulateWheel.X.negative = x_negative;
+                       cursor->emulateWheel.X.positive = x_positive;
+                       cursor->emulateWheel.Y.negative = y_negative;
+                       cursor->emulateWheel.Y.positive = y_positive;
                }
        } else if (atom == prop_wheel_inertia) {
                int inertia;
@@ -284,7 +286,7 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
                        return BadValue;
 
                if (!checkonly)
-                       priv->emulateWheel.inertia = inertia;
+                       cursor->emulateWheel.inertia = inertia;
        } else if (atom == prop_wheel_timeout) {
                int timeout;
 
@@ -298,7 +300,7 @@ wsWheelEmuSetProperty(DeviceIntPtr dev, 
                        return BadValue;
 
                if (!checkonly)
-                       priv->emulateWheel.timeout = timeout;
+                       cursor->emulateWheel.timeout = timeout;
        }
 
        return Success;
@@ -308,13 +310,13 @@ void
 wsWheelEmuInitProperty(DeviceIntPtr dev)
 {
        InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        char vals[4];
        int rc;
 
        prop_wheel_emu = MakeAtom(WS_PROP_WHEEL, strlen(WS_PROP_WHEEL), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_wheel_emu, XA_INTEGER, 8,
-           PropModeReplace, 1, &priv->emulateWheel.enabled, FALSE);
+           PropModeReplace, 1, &cursor->emulateWheel.enabled, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -323,10 +325,10 @@ wsWheelEmuInitProperty(DeviceIntPtr dev)
        }
        XISetDevicePropertyDeletable(dev, prop_wheel_emu, FALSE);
 
-       vals[0] = priv->emulateWheel.X.negative;
-       vals[1] = priv->emulateWheel.X.positive;
-       vals[2] = priv->emulateWheel.Y.negative;
-       vals[3] = priv->emulateWheel.Y.positive;
+       vals[0] = cursor->emulateWheel.X.negative;
+       vals[1] = cursor->emulateWheel.X.positive;
+       vals[2] = cursor->emulateWheel.Y.negative;
+       vals[3] = cursor->emulateWheel.Y.positive;
 
        prop_wheel_axismap = MakeAtom(WS_PROP_WHEEL_AXES,
            strlen(WS_PROP_WHEEL_AXES), TRUE);
@@ -343,7 +345,7 @@ wsWheelEmuInitProperty(DeviceIntPtr dev)
        prop_wheel_inertia = MakeAtom(WS_PROP_WHEEL_INERTIA,
            strlen(WS_PROP_WHEEL_INERTIA), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER, 16,
-           PropModeReplace, 1, &priv->emulateWheel.inertia, FALSE);
+           PropModeReplace, 1, &cursor->emulateWheel.inertia, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -355,7 +357,7 @@ wsWheelEmuInitProperty(DeviceIntPtr dev)
        prop_wheel_timeout = MakeAtom(WS_PROP_WHEEL_TIMEOUT,
            strlen(WS_PROP_WHEEL_TIMEOUT), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 32,
-           PropModeReplace, 1, &priv->emulateWheel.timeout, FALSE);
+           PropModeReplace, 1, &cursor->emulateWheel.timeout, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -367,7 +369,7 @@ wsWheelEmuInitProperty(DeviceIntPtr dev)
        prop_wheel_button = MakeAtom(WS_PROP_WHEEL_BUTTON,
            strlen(WS_PROP_WHEEL_BUTTON), TRUE);
        rc = XIChangeDeviceProperty(dev, prop_wheel_button, XA_INTEGER, 8,
-           PropModeReplace, 1, &priv->emulateWheel.button, FALSE);
+           PropModeReplace, 1, &cursor->emulateWheel.button, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
Index: src/ws.c
===================================================================
RCS file: /cvs/xenocara/driver/xf86-input-ws/src/ws.c,v
retrieving revision 1.57
diff -u -p -r1.57 ws.c
--- src/ws.c    8 Jul 2012 14:22:03 -0000       1.57
+++ src/ws.c    11 Jul 2012 12:28:19 -0000
@@ -23,10 +23,10 @@
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
-#include <dev/wscons/wsconsio.h>
 
 #include <xorg-server.h>
 #include <xf86.h>
+#include <xf86Priv.h>
 #include <xf86_OSproc.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
@@ -35,6 +35,7 @@
 #include <xisb.h>
 #include <mipointer.h>
 #include <extinit.h>
+#include <xkbsrv.h>
 
 #include "ws.h"
 
@@ -42,25 +43,45 @@
 #include "ws-properties.h"
 #include <xserver-properties.h>
 
+#define CAPSFLAG       (1 << 0)
+#define NUMFLAG                (1 << 1)
+#define SCROLLFLAG     (1 << 2)
+#define COMPOSEFLAG    (1 << 4)
+
 static MODULESETUPPROTO(SetupProc);
 static MODULETEARDOWNPROTO(TearDownProc);
 
 static int wsPreInit(InputDriverPtr, InputInfoPtr, int);
+static int wsPreInitPointer(InputDriverPtr, InputInfoPtr, int);
+static int wsPreInitKeyboard(InputDriverPtr, InputInfoPtr, int);
 static void wsUnInit(InputDriverPtr, InputInfoPtr, int);
 static int wsProc(DeviceIntPtr, int);
 static int wsDeviceInit(DeviceIntPtr);
+static int wsDeviceInitPointer(DeviceIntPtr);
+static int wsDeviceInitKeyboard(DeviceIntPtr);
 static int wsDeviceOn(DeviceIntPtr);
+static int wsDeviceOnPointer(DeviceIntPtr);
+static int wsDeviceOnKeyboard(DeviceIntPtr);
 static void wsDeviceOff(DeviceIntPtr);
+static void wsDeviceOffPointer(DeviceIntPtr);
+static void wsDeviceOffKeyboard(DeviceIntPtr);
 static void wsReadInput(InputInfoPtr);
+static void ConsoleReadInput(InputInfoPtr);
 static void wsSendButtons(InputInfoPtr, int);
 static int wsSwitchMode(ClientPtr, DeviceIntPtr, int);
-static Bool wsOpen(InputInfoPtr);
-static void wsClose(InputInfoPtr);
+static int wsOpenPointer(InputInfoPtr);
+static int wsOpenKeyboard(InputInfoPtr);
+static void wsClosePointer(InputInfoPtr);
+static void wsCloseKeyboard(InputInfoPtr);
 static void wsControlProc(DeviceIntPtr , PtrCtrl *);
+static void wsKeyboardBell(int, DeviceIntPtr, pointer, int);
+static void wsKeyboardCtrl(DeviceIntPtr, KeybdCtrl *);
 
 static void wsInitCalibProperty(DeviceIntPtr);
 static int wsSetCalibProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
 
+static Bool translate_XT_to_X(InputInfoPtr, int *);
+
 static Atom prop_calibration;
 static Atom prop_swap;
 
@@ -121,16 +142,10 @@ static int
 wsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
 {
        WSDevicePtr priv;
-       MessageType buttons_from = X_CONFIG;
-       char *s;
-       int i, phy_btn = 1, rc = BadValue;
 
-       priv = (WSDevicePtr)calloc(1, sizeof(WSDeviceRec));
-       if (priv == NULL) {
-               rc = BadAlloc;
-               goto fail;
-       }
-       pInfo->private = priv;
+       pInfo->private = priv = (WSDevicePtr)calloc(1, sizeof(WSDeviceRec));
+       if (priv == NULL)
+               return BadAlloc;
 
 #ifdef DEBUG
        ws_debug_level = xf86SetIntOption(pInfo->options, "DebugLevel",
@@ -142,10 +157,76 @@ wsPreInit(InputDriverPtr drv, InputInfoP
                xf86IDrvMsg(pInfo, X_ERROR, "No Device specified.\n");
                goto fail;
        }
-       priv->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
-       if (priv->buttons == 0) {
-               priv->buttons = DFLTBUTTONS;
-               buttons_from = X_DEFAULT;
+
+       if (strstr(priv->devName, "/dev/wsmouse") != NULL) {
+               priv->PreInit = wsPreInitPointer;
+               priv->DeviceInit = wsDeviceInitPointer;
+               priv->DeviceOn = wsDeviceOnPointer;
+               priv->DeviceOff = wsDeviceOffPointer;
+               priv->Open = wsOpenPointer;
+               priv->Close = wsClosePointer;
+
+               priv->cursor = (WSPointerPtr)calloc(1, sizeof(WSPointerRec));
+               if (priv->cursor == NULL)
+                       goto fail;
+
+               pInfo->read_input = wsReadInput;
+       } else if (strstr(priv->devName, "/dev/wskbd") != NULL) {
+               priv->PreInit = wsPreInitKeyboard;
+               priv->DeviceInit = wsDeviceInitKeyboard;
+               priv->DeviceOn = wsDeviceOnKeyboard;
+               priv->DeviceOff = wsDeviceOffKeyboard;
+               priv->Open = wsOpenKeyboard;
+               priv->Close = wsCloseKeyboard;
+
+               priv->keyboard =
+                   (WSKeyboardPtr)calloc(1, sizeof(WSKeyboardRec));
+               if (priv->keyboard == NULL)
+                       goto fail;
+
+               pInfo->read_input = ConsoleReadInput;
+       } else {
+               xf86IDrvMsg(pInfo, X_ERROR, "wrong device\n");
+               goto fail;
+       }
+
+       pInfo->device_control = wsProc;
+       pInfo->switch_mode = wsSwitchMode;
+
+       if (priv->Open(pInfo) != Success)
+               goto fail;
+
+       if (priv->PreInit(drv, pInfo, flags) != Success)
+               goto fail;
+
+       priv->Close(pInfo);
+
+       return Success;
+
+fail:
+       if (pInfo->fd >= 0)
+               priv->Close(pInfo);
+       if (priv != NULL) {
+               free(priv);
+               pInfo->private = NULL;
+       }
+       return BadValue;
+}
+
+static int
+wsPreInitPointer(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
+       char *s;
+       int i, phy_btn = 1;
+
+       cursor->buttons = xf86SetIntOption(pInfo->options,
+           "Buttons", MINBUTTONS);
+       if (cursor->buttons < MINBUTTONS || cursor->buttons > MAXBUTTONS) {
+               xf86IDrvMsg(pInfo, X_WARNING,
+                   "Invalid Buttons value: %d\n", cursor->buttons);
+               xf86IDrvMsg(pInfo, X_WARNING, "Using built-in minimal value\n");
+               cursor->buttons = MINBUTTONS;
        }
 
        /* Check for user-defined button mapping */
@@ -157,51 +238,51 @@ wsPreInit(InputDriverPtr drv, InputInfoP
                do {
                        btn = strtol(map, &end, 10);
 
-                       if (end == map || btn < 0 || btn > NBUTTONS) {
+                       if (end == map || btn < 0 || btn > MAXBUTTONS) {
                                xf86IDrvMsg(pInfo, X_ERROR,
                                    "Invalid button mapping. Using defaults\n");
                                phy_btn = 1; /* ensure defaults start at 1 */
                                break;
                        }
 
-                       priv->btnmap[phy_btn++] = btn;
+                       cursor->btnmap[phy_btn++] = btn;
                        map = end;
-               } while (end && *end != '\0' && phy_btn <= NBUTTONS);
+               } while (end && *end != '\0' && phy_btn <= MAXBUTTONS);
                free(s);
        }
 
-       for (i = phy_btn; i <= NBUTTONS; i++)
-               priv->btnmap[i] = i;
+       for (i = phy_btn; i <= MAXBUTTONS; i++)
+               cursor->btnmap[i] = i;
 
-       wsWheelHandleButtonMap(pInfo, &(priv->Z), "ZAxisMapping", "4 5");
-       wsWheelHandleButtonMap(pInfo, &(priv->W), "WAxisMapping", "6 7");
+       wsWheelHandleButtonMap(pInfo, &(cursor->Z), "ZAxisMapping", "4 5");
+       wsWheelHandleButtonMap(pInfo, &(cursor->W), "WAxisMapping", "6 7");
 
-       priv->screen_no = xf86SetIntOption(pInfo->options, "ScreenNo", 0);
+       cursor->screen_no = xf86SetIntOption(pInfo->options, "ScreenNo", 0);
        xf86IDrvMsg(pInfo, X_CONFIG, "associated screen: %d\n",
-           priv->screen_no);
-       if (priv->screen_no < 0 || priv->screen_no >= screenInfo.numScreens)
-               priv->screen_no = 0;
+           cursor->screen_no);
+       if (cursor->screen_no < 0 || cursor->screen_no >= screenInfo.numScreens)
+               cursor->screen_no = 0;
 
-       priv->swap_axes = xf86SetBoolOption(pInfo->options, "SwapXY", 0);
-       if (priv->swap_axes) {
+       cursor->swap_axes = xf86SetBoolOption(pInfo->options, "SwapXY", 0);
+       if (cursor->swap_axes) {
                xf86IDrvMsg(pInfo, X_CONFIG,
                    "device will work with X and Y axes swapped\n");
        }
-       priv->inv_x = 0;
-       priv->inv_y = 0;
+       cursor->inv_x = 0;
+       cursor->inv_y = 0;
        s = xf86SetStrOption(pInfo->options, "Rotate", NULL);
        if (s) {
                if (xf86NameCmp(s, "CW") == 0) {
-                       priv->inv_x = 1;
-                       priv->inv_y = 0;
-                       priv->swap_axes = 1;
+                       cursor->inv_x = 1;
+                       cursor->inv_y = 0;
+                       cursor->swap_axes = 1;
                } else if (xf86NameCmp(s, "CCW") == 0) {
-                       priv->inv_x = 0;
-                       priv->inv_y = 1;
-                       priv->swap_axes = 1;
+                       cursor->inv_x = 0;
+                       cursor->inv_y = 1;
+                       cursor->swap_axes = 1;
                } else if (xf86NameCmp(s, "UD") == 0) {
-                       priv->inv_x = 1;
-                       priv->inv_y = 1;
+                       cursor->inv_x = 1;
+                       cursor->inv_y = 1;
                } else {
                        xf86IDrvMsg(pInfo, X_ERROR, "\"%s\" is not a valid "
                            "value for Option \"Rotate\"\n", s);
@@ -210,72 +291,81 @@ wsPreInit(InputDriverPtr drv, InputInfoP
                }
                free(s);
        }
-       if (wsOpen(pInfo) != Success)
-               goto fail;
-       if (ioctl(pInfo->fd, WSMOUSEIO_GTYPE, &priv->type) != 0)
-               goto fail;
-       if (priv->type == WSMOUSE_TYPE_TPANEL) {
+
+       if (ioctl(pInfo->fd, WSMOUSEIO_GTYPE, &cursor->type) != 0)
+               return !Success;
+
+       if (cursor->type == WSMOUSE_TYPE_TPANEL) {
                pInfo->type_name = XI_TOUCHSCREEN;
-               priv->raw = xf86SetBoolOption(pInfo->options, "Raw", 1);
-               if (priv->raw) {
+               cursor->raw = xf86SetBoolOption(pInfo->options, "Raw", 1);
+               if (cursor->raw) {
                        xf86IDrvMsg(pInfo, X_CONFIG,
                            "device will work in raw mode\n");
                }
        } else {
                pInfo->type_name = XI_MOUSE;
-               priv->raw = 0;
+               cursor->raw = 0;
        }
 
-       if (priv->type == WSMOUSE_TYPE_TPANEL && priv->raw) {
+       if (cursor->type == WSMOUSE_TYPE_TPANEL && cursor->raw) {
                if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS,
-                   &priv->coords) != 0) {
+                   &cursor->coords) != 0) {
                        xf86IDrvMsg(pInfo, X_ERROR,
                            "GCALIBCOORS failed %s\n", strerror(errno));
-                       goto fail;
+                       return !Success;
                }
 
                /* get default coordinate space from kernel */
-               priv->min_x = priv->coords.minx;
-               priv->max_x = priv->coords.maxx;
-               priv->min_y = priv->coords.miny;
-               priv->max_y = priv->coords.maxy;
+               cursor->min_x = cursor->coords.minx;
+               cursor->max_x = cursor->coords.maxx;
+               cursor->min_y = cursor->coords.miny;
+               cursor->max_y = cursor->coords.maxy;
        } else {
                /* in calibrated mode, coordinate space, is screen coords */
-               priv->min_x = 0;
-               priv->max_x = screenInfo.screens[priv->screen_no]->width - 1;
-               priv->min_y = 0;
-               priv->max_y = screenInfo.screens[priv->screen_no]->height - 1;
+               cursor->min_x = cursor->min_y = 0;
+               cursor->max_x =
+                   screenInfo.screens[cursor->screen_no]->width - 1;
+               cursor->max_y =
+                   screenInfo.screens[cursor->screen_no]->height - 1;
        }
-       /* Allow options to override this */
-       priv->min_x = xf86SetIntOption(pInfo->options, "MinX", priv->min_x);
-       xf86IDrvMsg(pInfo, X_INFO, "minimum x position: %d\n", priv->min_x);
-       priv->max_x = xf86SetIntOption(pInfo->options, "MaxX", priv->max_x);
-       xf86IDrvMsg(pInfo, X_INFO, "maximum x position: %d\n", priv->max_x);
-       priv->min_y = xf86SetIntOption(pInfo->options, "MinY", priv->min_y);
-       xf86IDrvMsg(pInfo, X_INFO, "minimum y position: %d\n", priv->min_y);
-       priv->max_y = xf86SetIntOption(pInfo->options, "MaxY", priv->max_y);
-       xf86IDrvMsg(pInfo, X_INFO, "maximum y position: %d\n", priv->max_y);
-
-       pInfo->device_control = wsProc;
-       pInfo->read_input = wsReadInput;
-       pInfo->switch_mode = wsSwitchMode;
 
-       xf86IDrvMsg(pInfo, buttons_from, "Buttons: %d\n", priv->buttons);
+       /* Allow options to override this */
+       cursor->min_x = xf86SetIntOption(pInfo->options, "MinX", cursor->min_x);
+       xf86IDrvMsg(pInfo, X_INFO, "minimum x position: %d\n", cursor->min_x);
+       cursor->max_x = xf86SetIntOption(pInfo->options, "MaxX", cursor->max_x);
+       xf86IDrvMsg(pInfo, X_INFO, "maximum x position: %d\n", cursor->max_x);
+       cursor->min_y = xf86SetIntOption(pInfo->options, "MinY", cursor->min_y);
+       xf86IDrvMsg(pInfo, X_INFO, "minimum y position: %d\n", cursor->min_y);
+       cursor->max_y = xf86SetIntOption(pInfo->options, "MaxY", cursor->max_y);
+       xf86IDrvMsg(pInfo, X_INFO, "maximum y position: %d\n", cursor->max_y);
 
-       wsClose(pInfo);
+       xf86IDrvMsg(pInfo, X_INFO, "Buttons: %d\n", cursor->buttons);
 
        wsmbEmuPreInit(pInfo);
        wsWheelEmuPreInit(pInfo);
+
        return Success;
+}
 
-fail:
-       if (pInfo->fd >= 0)
-               wsClose(pInfo);
-       if (priv != NULL) {
-               free(priv);
-               pInfo->private = NULL;
-       }
-       return rc;
+static int
+wsPreInitKeyboard(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+       WSKeyboardPtr keyboard = ((WSDevicePtr)pInfo->private)->keyboard;
+
+       pInfo->type_name = XI_KEYBOARD;
+
+       keyboard->rmlvo.rules = xf86SetStrOption(pInfo->options,
+           "XkbRules", "base");
+       keyboard->rmlvo.model = xf86SetStrOption(pInfo->options,
+           "XkbModel", "pc105");
+       keyboard->rmlvo.layout = xf86SetStrOption(pInfo->options,
+           "XkbLayout", "us");
+       keyboard->rmlvo.variant = xf86SetStrOption(pInfo->options,
+           "XkbVariant", NULL);
+       keyboard->rmlvo.options = xf86SetStrOption(pInfo->options,
+           "XkbOptions", NULL);
+
+       return Success;
 }
 
 static void
@@ -284,6 +374,8 @@ wsUnInit(InputDriverPtr drv, InputInfoPt
        WSDevicePtr priv = (WSDevicePtr)pInfo->private;
 
        if (priv) {
+               if (priv->keyboard)
+                       XkbFreeRMLVOSet(&priv->keyboard->rmlvo, FALSE);
                free(priv->devName);
                priv->devName = NULL;
        }
@@ -294,6 +386,7 @@ static int
 wsProc(DeviceIntPtr pWS, int what)
 {
        InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
 
        switch (what) {
        case DEVICE_INIT:
@@ -308,7 +401,8 @@ wsProc(DeviceIntPtr pWS, int what)
 
        case DEVICE_CLOSE:
                DBG(1, ErrorF("WS DEVICE_CLOSE\n"));
-               wsClose(pInfo);
+               if (pInfo->fd >= 0)
+                       priv->Close(pInfo);
                break;
 
        default:
@@ -323,24 +417,41 @@ wsDeviceInit(DeviceIntPtr pWS)
 {
        InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
        WSDevicePtr priv = (WSDevicePtr)pInfo->private;
-       int xmin, xmax, ymin, ymax;
-       Atom btn_labels[NBUTTONS] = {0};
-       Atom axes_labels[NAXES] = {0};
 
        DBG(1, ErrorF("WS DEVICE_INIT\n"));
 
+       pWS->public.on = FALSE;
+       if (priv->Open(pInfo) != Success)
+               return !Success;
+
+       if (priv->DeviceInit(pWS) != Success)
+               return !Success;
+
+       return Success;
+}
+
+static int
+wsDeviceInitPointer(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
+       unsigned char map[MAXBUTTONS + 1];
+       int i, xmin, xmax, ymin, ymax;
+       Atom btn_labels[MAXBUTTONS] = {0};
+       Atom axes_labels[NAXES] = {0};
+
        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
-       if (!InitButtonClassDeviceStruct(pWS, min(priv->buttons, NBUTTONS),
-           btn_labels, priv->btnmap))
+       if (!InitButtonClassDeviceStruct(pWS, cursor->buttons,
+           btn_labels, cursor->btnmap))
                return !Success;
 
-       if (priv->type == WSMOUSE_TYPE_TPANEL) {
-               xmin = priv->min_x;
-               xmax = priv->max_x;
-               ymin = priv->min_y;
-               ymax = priv->max_y;
+       if (cursor->type == WSMOUSE_TYPE_TPANEL) {
+               xmin = cursor->min_x;
+               xmax = cursor->max_x;
+               ymin = cursor->min_y;
+               ymax = cursor->max_y;
        } else {
                xmin = -1;
                xmax = -1;
@@ -348,7 +459,7 @@ wsDeviceInit(DeviceIntPtr pWS)
                ymax = -1;
        }
 
-       if (priv->swap_axes) {
+       if (cursor->swap_axes) {
                int tmp;
                tmp = xmin;
                xmin = ymin;
@@ -357,7 +468,7 @@ wsDeviceInit(DeviceIntPtr pWS)
                xmax = ymax;
                ymax = tmp;
        }
-       if (priv->type == WSMOUSE_TYPE_TPANEL) {
+       if (cursor->type == WSMOUSE_TYPE_TPANEL) {
                axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
                axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
        } else {
@@ -366,7 +477,7 @@ wsDeviceInit(DeviceIntPtr pWS)
        }
        if (!InitValuatorClassDeviceStruct(pWS,
            NAXES, axes_labels, GetMotionHistorySize(),
-           priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative))
+           cursor->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative))
                return !Success;
        if (!InitPtrFeedbackClassDeviceStruct(pWS, wsControlProc))
                return !Success;
@@ -374,24 +485,39 @@ wsDeviceInit(DeviceIntPtr pWS)
        xf86InitValuatorAxisStruct(pWS, 0,
            axes_labels[0],
            xmin, xmax, 1, 0, 1,
-           priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative);
+           cursor->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative);
        xf86InitValuatorDefaults(pWS, 0);
 
        xf86InitValuatorAxisStruct(pWS, 1,
            axes_labels[1],
            ymin, ymax, 1, 0, 1,
-           priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative);
+           cursor->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative);
        xf86InitValuatorDefaults(pWS, 1);
 
-       pWS->public.on = FALSE;
-       if (wsOpen(pInfo) != Success) {
-               return !Success;
-       }
-
-       if (priv->type == WSMOUSE_TYPE_TPANEL)
+       if (cursor->type == WSMOUSE_TYPE_TPANEL)
                wsInitCalibProperty(pWS);
        wsmbEmuInitProperty(pWS);
        wsWheelEmuInitProperty(pWS);
+
+       return Success;
+}
+
+static int
+wsDeviceInitKeyboard(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSKeyboardPtr keyboard = ((WSDevicePtr)pInfo->private)->keyboard;
+
+       tcgetattr(pInfo->fd, &(keyboard->kbdtty));
+
+       if (!InitKeyboardDeviceStruct(pWS, &keyboard->rmlvo,
+           wsKeyboardBell, wsKeyboardCtrl)) {
+               xf86IDrvMsg(pInfo, X_ERROR, "Keyboard initialization failed. "
+                   "This could be a missing or incorrect setup of "
+                   "xkeyboard-config.\n");
+               return !Success;
+       }
+
        return Success;
 }
 
@@ -400,26 +526,53 @@ wsDeviceOn(DeviceIntPtr pWS)
 {
        InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
        WSDevicePtr priv = (WSDevicePtr)pInfo->private;
-       struct wsmouse_calibcoords coords;
 
        DBG(1, ErrorF("WS DEVICE ON\n"));
-       if ((pInfo->fd < 0) && (wsOpen(pInfo) != Success)) {
+
+       if ((pInfo->fd < 0) && (priv->Open(pInfo) != Success)) {
                xf86IDrvMsg(pInfo, X_ERROR, "wsOpen failed %s\n",
                    strerror(errno));
                return !Success;
        }
 
-       if (priv->type == WSMOUSE_TYPE_TPANEL) {
+       if (priv->DeviceOn(pWS) != Success)
+               return !Success;
+
+       if (priv->cursor) {
+               priv->cursor->buffer = XisbNew(pInfo->fd,
+                   sizeof(struct wscons_event) * NUMEVENTS);
+               if (priv->cursor->buffer == NULL) {
+                       xf86IDrvMsg(pInfo, X_ERROR,
+                           "cannot alloc xisb buffer\n");
+                       priv->Close(pInfo);
+                       return !Success;
+               }
+       }
+
+       xf86AddEnabledDevice(pInfo);
+       pWS->public.on = TRUE;
+
+       return Success;
+}
+
+static int
+wsDeviceOnPointer(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
+       struct wsmouse_calibcoords coords;
+
+       if (cursor->type == WSMOUSE_TYPE_TPANEL) {
                /* get calibration values */
                if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS, &coords) != 0) {
                        xf86IDrvMsg(pInfo, X_ERROR, "GCALIBCOORS failed %s\n",
                            strerror(errno));
                        return !Success;
                }
-               memcpy(&priv->coords, &coords, sizeof coords);
+               memcpy(&cursor->coords, &coords, sizeof coords);
                /* set raw mode */
-               if (coords.samplelen != priv->raw) {
-                       coords.samplelen = priv->raw;
+               if (coords.samplelen != cursor->raw) {
+                       coords.samplelen = cursor->raw;
                        if (ioctl(pInfo->fd, WSMOUSEIO_SCALIBCOORDS,
                            &coords) != 0) {
                                xf86IDrvMsg(pInfo, X_ERROR,
@@ -428,16 +581,31 @@ wsDeviceOn(DeviceIntPtr pWS)
                        }
                }
        }
-       priv->buffer = XisbNew(pInfo->fd,
-           sizeof(struct wscons_event) * NUMEVENTS);
-       if (priv->buffer == NULL) {
-               xf86IDrvMsg(pInfo, X_ERROR, "cannot alloc xisb buffer\n");
-               wsClose(pInfo);
-               return !Success;
-       }
-       xf86AddEnabledDevice(pInfo);
+
        wsmbEmuOn(pInfo);
-       pWS->public.on = TRUE;
+
+       return Success;
+}
+
+static int
+wsDeviceOnKeyboard(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSKeyboardPtr keyboard = ((WSDevicePtr)pInfo->private)->keyboard;
+       int mode = WSKBD_RAW;
+
+       keyboard->kbdtty.c_iflag = IGNPAR | IGNBRK;
+       keyboard->kbdtty.c_oflag = 0;
+       keyboard->kbdtty.c_cflag = CREAD | CS8;
+       keyboard->kbdtty.c_lflag = 0;
+       keyboard->kbdtty.c_cc[VTIME] = 0;
+       keyboard->kbdtty.c_cc[VMIN] = 1;
+       cfsetispeed(&(keyboard->kbdtty), 9600);
+       cfsetospeed(&(keyboard->kbdtty), 9600);
+       if (tcsetattr(pInfo->fd, TCSANOW, &(keyboard->kbdtty)) < 0)
+               xf86IDrvMsg(pInfo, X_ERROR, "tcsetattr: %s\n", strerror(errno));
+       ioctl(pInfo->fd, WSKBDIO_SETMODE, &mode);
+
        return Success;
 }
 
@@ -446,42 +614,63 @@ wsDeviceOff(DeviceIntPtr pWS)
 {
        InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
        WSDevicePtr priv = (WSDevicePtr)pInfo->private;
-       struct wsmouse_calibcoords coords;
 
        DBG(1, ErrorF("WS DEVICE OFF\n"));
+
+       priv->DeviceOff(pWS);
+       if (pInfo->fd >= 0) {
+               xf86RemoveEnabledDevice(pInfo);
+               priv->Close(pInfo);
+       }
+       if (priv->cursor && priv->cursor->buffer) {
+               XisbFree(priv->cursor->buffer);
+               priv->cursor->buffer = NULL;
+       }
+       pWS->public.on = FALSE;
+}
+
+static void
+wsDeviceOffPointer(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
+       struct wsmouse_calibcoords coords;
+
        wsmbEmuFinalize(pInfo);
-       if (priv->type == WSMOUSE_TYPE_TPANEL) {
+       if (cursor->type == WSMOUSE_TYPE_TPANEL) {
                /* Restore calibration data */
-               memcpy(&coords, &priv->coords, sizeof coords);
+               memcpy(&coords, &cursor->coords, sizeof coords);
                if (ioctl(pInfo->fd, WSMOUSEIO_SCALIBCOORDS, &coords) != 0) {
                        xf86IDrvMsg(pInfo, X_ERROR, "SCALIBCOORS failed %s\n",
                            strerror(errno));
                }
        }
-       if (pInfo->fd >= 0) {
-               xf86RemoveEnabledDevice(pInfo);
-               wsClose(pInfo);
-       }
-       if (priv->buffer) {
-               XisbFree(priv->buffer);
-               priv->buffer = NULL;
-       }
-       pWS->public.on = FALSE;
+}
+
+static void
+wsDeviceOffKeyboard(DeviceIntPtr pWS)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
+       WSKeyboardPtr keyboard = ((WSDevicePtr)pInfo->private)->keyboard;
+       int mode = WSKBD_TRANSLATED;
+
+       ioctl(pInfo->fd, WSKBDIO_SETMODE, &mode);
+       tcsetattr(pInfo->fd, TCSANOW, &(keyboard->kbdtty));
 }
 
 static void
 wsReadInput(InputInfoPtr pInfo)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        static struct wscons_event eventList[NUMEVENTS];
        int n, c;
        struct wscons_event *event = eventList;
        unsigned char *pBuf;
 
-       XisbBlockDuration(priv->buffer, -1);
+       XisbBlockDuration(cursor->buffer, -1);
        pBuf = (unsigned char *)eventList;
        n = 0;
-       while (n < sizeof(eventList) && (c = XisbRead(priv->buffer)) >= 0) {
+       while (n < sizeof(eventList) && (c = XisbRead(cursor->buffer)) >= 0) {
                pBuf[n++] = (unsigned char)c;
        }
 
@@ -490,7 +679,7 @@ wsReadInput(InputInfoPtr pInfo)
 
        n /= sizeof(struct wscons_event);
        while (n--) {
-               int buttons = priv->lastButtons;
+               int buttons = cursor->lastButtons;
                int dx = 0, dy = 0, dz = 0, dw = 0, ax = 0, ay = 0;
                int zbutton = 0, wbutton = 0;
 
@@ -515,27 +704,20 @@ wsReadInput(InputInfoPtr pInfo)
                        break;
                case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
                        DBG(4, ErrorF("Absolute X %d\n", event->value));
-                       if (event->value == 4095)
-                               break;
                        ax = event->value;
-                       if (priv->inv_x)
-                               ax = priv->max_x - ax + priv->min_x;
+                       if (cursor->inv_x)
+                               ax = cursor->max_x - ax + cursor->min_x;
                        break;
                case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
                        DBG(4, ErrorF("Absolute Y %d\n", event->value));
                        ay = event->value;
-                       if (priv->inv_y)
-                               ay = priv->max_y - ay + priv->min_y;
+                       if (cursor->inv_y)
+                               ay = cursor->max_y - ay + cursor->min_y;
                        break;
                case WSCONS_EVENT_MOUSE_DELTA_Z:
                        DBG(4, ErrorF("Relative Z %d\n", event->value));
                        dz = event->value;
                        break;
-               case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
-                       /* ignore those */
-                       ++event;
-                       continue;
-                       break;
                case WSCONS_EVENT_MOUSE_DELTA_W:
                        DBG(4, ErrorF("Relative W %d\n", event->value));
                        dw = event->value;
@@ -543,6 +725,10 @@ wsReadInput(InputInfoPtr pInfo)
                default:
                        xf86IDrvMsg(pInfo, X_WARNING,
                            "bad wsmouse event type=%d\n", event->type);
+                       /* FALLTHROUGH */
+               case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
+               case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
+                       /* ignore those */
                        ++event;
                        continue;
                }
@@ -557,25 +743,23 @@ wsReadInput(InputInfoPtr pInfo)
                            dx, dy));
                        xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
                }
-               if (dz && priv->Z.negative != WS_NOMAP
-                   && priv->Z.positive != WS_NOMAP) {
-                       zbutton = (dz < 0) ? priv->Z.negative :
-                           priv->Z.positive;
+               if (dz && cursor->Z.negative != WS_NOMAP
+                   && cursor->Z.positive != WS_NOMAP) {
+                       zbutton = (dz < 0) ? cursor->Z.negative :
+                           cursor->Z.positive;
                        DBG(4, ErrorF("Z -> button %d\n", zbutton));
                        wsButtonClicks(pInfo, zbutton, abs(dz));
                }
-               if (dw && priv->W.negative != WS_NOMAP
-                   && priv->W.positive != WS_NOMAP) {
-                       wbutton = (dw < 0) ? priv->W.negative :
-                           priv->W.positive;
+               if (dw && cursor->W.negative != WS_NOMAP
+                   && cursor->W.positive != WS_NOMAP) {
+                       wbutton = (dw < 0) ? cursor->W.negative :
+                           cursor->W.positive;
                        DBG(4, ErrorF("W -> button %d\n", wbutton));
                        wsButtonClicks(pInfo, wbutton, abs(dw));
                }
-               if (priv->lastButtons != buttons) {
-                       /* button event */
+               if (cursor->lastButtons != buttons)
                        wsSendButtons(pInfo, buttons);
-               }
-               if (priv->swap_axes) {
+               if (cursor->swap_axes) {
                        int tmp;
 
                        tmp = ax;
@@ -583,8 +767,8 @@ wsReadInput(InputInfoPtr pInfo)
                        ay = tmp;
                }
                if (ax) {
-                       dx = ax - priv->old_ax;
-                       priv->old_ax = ax;
+                       dx = ax - cursor->old_ax;
+                       cursor->old_ax = ax;
                        if (wsWheelEmuFilterMotion(pInfo, dx, 0))
                                continue;
 
@@ -593,8 +777,8 @@ wsReadInput(InputInfoPtr pInfo)
                        xf86PostMotionEvent(pInfo->dev, 1, 0, 1, ax);
                }
                if (ay) {
-                       dy = ay - priv->old_ay;
-                       priv->old_ay = ay;
+                       dy = ay - cursor->old_ay;
+                       cursor->old_ay = ay;
                        if (wsWheelEmuFilterMotion(pInfo, 0, dy))
                                continue;
 
@@ -603,16 +787,34 @@ wsReadInput(InputInfoPtr pInfo)
                        xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
                }
        }
-       return;
+}
+
+static void
+ConsoleReadInput(InputInfoPtr pInfo)
+{
+       unsigned char buf[64];
+       int scancode, n, i;
+
+       if ((n = read(pInfo->fd, buf, sizeof(buf))) > 0) {
+               for (i = 0; i < n; i++) {
+                       scancode = buf[i] & 0x7f;
+
+                       if (!translate_XT_to_X(pInfo, &scancode))
+                               continue;
+
+                       xf86PostKeyboardEvent(pInfo->dev,
+                           scancode, buf[i] & 0x80 ? FALSE : TRUE);
+               }
+       }
 }
 
 static void
 wsSendButtons(InputInfoPtr pInfo, int buttons)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int change, button, press;
 
-       change = buttons ^ priv->lastButtons;
+       change = buttons ^ cursor->lastButtons;
        while (change) {
                button = ffs(change);
                press = buttons & (1 << (button - 1));
@@ -627,7 +829,7 @@ wsSendButtons(InputInfoPtr pInfo, int bu
                xf86PostButtonEvent(pInfo->dev, TRUE, button, press, 0, 0);
                DBG(3, ErrorF("post button event %d %d\n", button, press));
        }
-       priv->lastButtons = buttons;
+       cursor->lastButtons = buttons;
 }
 
 static int
@@ -636,8 +838,8 @@ wsSwitchMode(ClientPtr client, DeviceInt
        return BadMatch;
 }
 
-static Bool
-wsOpen(InputInfoPtr pInfo)
+static int
+wsOpenPointer(InputInfoPtr pInfo)
 {
        WSDevicePtr priv = (WSDevicePtr)pInfo->private;
 #ifdef __NetBSD__
@@ -660,14 +862,28 @@ wsOpen(InputInfoPtr pInfo)
        return Success;
 }
 
+static int
+wsOpenKeyboard(InputInfoPtr pInfo)
+{
+       pInfo->fd = xf86Info.consoleFd;
+
+       return Success;
+}
+
 static void
-wsClose(InputInfoPtr pInfo)
+wsClosePointer(InputInfoPtr pInfo)
 {
        xf86CloseSerial(pInfo->fd);
        pInfo->fd = -1;
 }
 
 static void
+wsCloseKeyboard(InputInfoPtr pInfo)
+{
+       pInfo->fd = -1;
+}
+
+static void
 wsControlProc(DeviceIntPtr device, PtrCtrl *ctrl)
 {
        /* Nothing to do, dix handles all settings */
@@ -675,10 +891,41 @@ wsControlProc(DeviceIntPtr device, PtrCt
 }
 
 static void
+wsKeyboardBell(int percent, DeviceIntPtr device, pointer ctrl, int unused)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)device->public.devicePrivate;
+       struct wskbd_bell_data wsb;
+
+       wsb.which = WSKBD_BELL_DOALL;
+       wsb.pitch = ((KeybdCtrl *)ctrl)->bell_pitch;
+       wsb.period = ((KeybdCtrl *)ctrl)->bell_duration;
+       wsb.volume = percent;
+       ioctl(pInfo->fd, WSKBDIO_COMPLEXBELL, &wsb);
+}
+
+static void
+wsKeyboardCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)device->public.devicePrivate;
+       unsigned long leds = 0;
+
+       if (ctrl->leds & CAPSFLAG)
+               leds |= WSKBD_LED_CAPS;
+       if (ctrl->leds & NUMFLAG)
+               leds |= WSKBD_LED_NUM;
+       if (ctrl->leds & SCROLLFLAG)
+               leds |= WSKBD_LED_SCROLL;
+       if (ctrl->leds & COMPOSEFLAG)
+               leds |= WSKBD_LED_COMPOSE;
+
+       ioctl(pInfo->fd, WSKBDIO_SETLEDS, &leds);
+}
+
+static void
 wsInitCalibProperty(DeviceIntPtr device)
 {
        InputInfoPtr pInfo = (InputInfoPtr)device->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        int rc;
 
        DBG(1, ErrorF("wsInitCalibProperty\n"));
@@ -686,7 +933,7 @@ wsInitCalibProperty(DeviceIntPtr device)
        prop_calibration = MakeAtom(WS_PROP_CALIBRATION,
            strlen(WS_PROP_CALIBRATION), TRUE);
        rc = XIChangeDeviceProperty(device, prop_calibration, XA_INTEGER, 32,
-           PropModeReplace, 4, &priv->min_x, FALSE);
+           PropModeReplace, 4, &cursor->min_x, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -698,7 +945,7 @@ wsInitCalibProperty(DeviceIntPtr device)
        prop_swap = MakeAtom(WS_PROP_SWAP_AXES,
            strlen(WS_PROP_SWAP_AXES), TRUE);
        rc = XIChangeDeviceProperty(device, prop_swap, XA_INTEGER, 8,
-           PropModeReplace, 1, &priv->swap_axes, FALSE);
+           PropModeReplace, 1, &cursor->swap_axes, FALSE);
        if (rc != Success) {
                xf86IDrvMsg(pInfo, X_ERROR,
                    "cannot create device property %s: %d\n",
@@ -717,7 +964,7 @@ wsSetCalibProperty(DeviceIntPtr device, 
     BOOL checkonly)
 {
        InputInfoPtr pInfo = (InputInfoPtr)device->public.devicePrivate;
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        struct wsmouse_calibcoords coords;
        int need_update = 0;
        AxisInfoPtr ax = device->valuator->axes,
@@ -733,31 +980,31 @@ wsSetCalibProperty(DeviceIntPtr device, 
                if (!checkonly) {
                        if (val->size == 0) {
                                DBG(1, ErrorF(" uncalibrate\n"));
-                               priv->min_x = 0;
-                               priv->max_x = -1;
-                               priv->min_y = 0;
-                               priv->max_y = -1;
+                               cursor->min_x = 0;
+                               cursor->max_x = -1;
+                               cursor->min_y = 0;
+                               cursor->max_y = -1;
                        } else {
-                               priv->min_x = ((int *)(val->data))[0];
-                               priv->max_x = ((int *)(val->data))[1];
-                               priv->min_y = ((int *)(val->data))[2];
-                               priv->max_y = ((int *)(val->data))[3];
+                               cursor->min_x = ((int *)(val->data))[0];
+                               cursor->max_x = ((int *)(val->data))[1];
+                               cursor->min_y = ((int *)(val->data))[2];
+                               cursor->max_y = ((int *)(val->data))[3];
                                DBG(1, ErrorF(" calibrate %d %d %d %d\n",
-                                       priv->min_x, priv->max_x,
-                                       priv->min_y, priv->max_y));
+                                       cursor->min_x, cursor->max_x,
+                                       cursor->min_y, cursor->max_y));
                                need_update++;
                        }
                        /* Update axes descriptors */
-                       if (!priv->swap_axes) {
-                               ax->min_value = priv->min_x;
-                               ax->max_value = priv->max_x;
-                               ay->min_value = priv->min_y;
-                               ay->max_value = priv->max_y;
+                       if (!cursor->swap_axes) {
+                               ax->min_value = cursor->min_x;
+                               ax->max_value = cursor->max_x;
+                               ay->min_value = cursor->min_y;
+                               ay->max_value = cursor->max_y;
                        } else {
-                               ax->min_value = priv->min_y;
-                               ax->max_value = priv->max_y;
-                               ay->min_value = priv->min_x;
-                               ay->max_value = priv->max_x;
+                               ax->min_value = cursor->min_y;
+                               ax->max_value = cursor->max_y;
+                               ay->min_value = cursor->min_x;
+                               ay->max_value = cursor->max_x;
                        }
                }
        } else if (atom == prop_swap) {
@@ -765,28 +1012,28 @@ wsSetCalibProperty(DeviceIntPtr device, 
                    val->size != 1)
                        return BadMatch;
                if (!checkonly) {
-                       priv->swap_axes = *((BOOL *)val->data);
-                       DBG(1, ErrorF("swap_axes %d\n", priv->swap_axes));
+                       cursor->swap_axes = *((BOOL *)val->data);
+                       DBG(1, ErrorF("swap_axes %d\n", cursor->swap_axes));
                        need_update++;
                }
        }
        if (need_update) {
                /* Update the saved values to be restored on device off */
-               priv->coords.minx = priv->min_x;
-               priv->coords.maxx = priv->max_x;
-               priv->coords.miny = priv->min_y;
-               priv->coords.maxy = priv->max_y;
-               priv->coords.swapxy = priv->swap_axes;
+               cursor->coords.minx = cursor->min_x;
+               cursor->coords.maxx = cursor->max_x;
+               cursor->coords.miny = cursor->min_y;
+               cursor->coords.maxy = cursor->max_y;
+               cursor->coords.swapxy = cursor->swap_axes;
 
                /* Update the kernel calibration table */
-               coords.minx = priv->min_x;
-               coords.maxx = priv->max_x;
-               coords.miny = priv->min_y;
-               coords.maxy = priv->max_y;
-               coords.swapxy = priv->swap_axes;
-               coords.samplelen = priv->raw;
-               coords.resx = priv->coords.resx;
-               coords.resy = priv->coords.resy;
+               coords.minx = cursor->min_x;
+               coords.maxx = cursor->max_x;
+               coords.miny = cursor->min_y;
+               coords.maxy = cursor->max_y;
+               coords.swapxy = cursor->swap_axes;
+               coords.samplelen = cursor->raw;
+               coords.resx = cursor->coords.resx;
+               coords.resy = cursor->coords.resy;
                if (ioctl(pInfo->fd, WSMOUSEIO_SCALIBCOORDS, &coords) != 0) {
                        xf86IDrvMsg(pInfo, X_ERROR, "SCALIBCOORDS failed %s\n",
                            strerror(errno));
@@ -799,7 +1046,7 @@ void
 wsWheelHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis,
     const char* axis_name, const char* default_value)
 {
-       WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+       WSPointerPtr cursor = ((WSDevicePtr)pInfo->private)->cursor;
        char *option_string;
        int b1, b2;
 
@@ -810,16 +1057,16 @@ wsWheelHandleButtonMap(InputInfoPtr pInf
            default_value);
        if (option_string) {
                if (sscanf(option_string, "%d %d", &b1, &b2) == 2 &&
-                   b1 > 0 && b1 <= NBUTTONS &&
-                   b2 > 0 && b2 <= NBUTTONS) {
+                   b1 > 0 && b1 <= MAXBUTTONS &&
+                   b2 > 0 && b2 <= MAXBUTTONS) {
                        xf86IDrvMsg(pInfo, X_CONFIG, "%s: buttons %d and %d\n",
                            axis_name, b1, b2);
 
                        pAxis->negative = b1;
                        pAxis->positive = b2;
 
-                       if (max(b1, b2) > priv->buttons)
-                               priv->buttons = max(b1, b2);
+                       if (max(b1, b2) > cursor->buttons)
+                               cursor->buttons = max(b1, b2);
                } else {
                        xf86IDrvMsg(pInfo, X_WARNING,
                            "Invalid %s value: \"%s\"\n",
@@ -838,4 +1085,63 @@ wsButtonClicks(InputInfoPtr pInfo, int b
                xf86PostButtonEvent(pInfo->dev, TRUE, button, 1, 0, 0);
                xf86PostButtonEvent(pInfo->dev, TRUE, button, 0, 0, 0);
        }
+}
+
+static Bool
+translate_XT_to_X(InputInfoPtr pInfo, int *scancode)
+{
+       WSKeyboardPtr keyboard = ((WSDevicePtr)pInfo->private)->keyboard;
+
+       switch (keyboard->scanprefix) {
+       case 0x00:
+               switch (*scancode) {
+               case 0x60:
+               case 0x61:
+                       keyboard->scanprefix = *scancode;
+                       return FALSE;
+               case 0x72:      *scancode = 0x6d;       break;  /* Compose */
+               case 0x73:      *scancode = 0x6b;       break;  /* LMeta */
+               case 0x74:      *scancode = 0x6c;       break;  /* RMeta */
+               }
+               break;
+       case 0x60:
+               keyboard->scanprefix = 0;
+               switch (*scancode) {
+               case 0x38:      *scancode = 0x69;       break;  /* RAlt */
+               case 0x1d:      *scancode = 0x65;       break;  /* RCtrl */
+               case 0x52:      *scancode = 0x62;       break;  /* Insert */
+               case 0x53:      *scancode = 0x63;       break;  /* Delete */
+               case 0x47:      *scancode = 0x59;       break;  /* Home */
+               case 0x4f:      *scancode = 0x5f;       break;  /* End */
+               case 0x49:      *scancode = 0x5b;       break;  /* PgUp */
+               case 0x51:      *scancode = 0x61;       break;  /* PgDn */
+               case 0x4b:      *scancode = 0x5c;       break;  /* Left */
+               case 0x48:      *scancode = 0x5a;       break;  /* Up */
+               case 0x50:      *scancode = 0x60;       break;  /* Down */
+               case 0x4d:      *scancode = 0x5e;       break;  /* Right */
+               case 0x35:      *scancode = 0x68;       break;  /* KP Div */
+               case 0x1c:      *scancode = 0x64;       break;  /* KP Enter */
+               case 0x37:      *scancode = 0x67;       break;  /* PrtSrc */
+               case 0x46:      *scancode = 0x6a;       break;  /* Break */
+               case 0x5b:      *scancode = 0x6b;       break;  /* LMeta */
+               case 0x5c:      *scancode = 0x6c;       break;  /* RMeta */
+               case 0x5d:      *scancode = 0x6d;       break;  /* Menu */
+               case 0x5e:      *scancode = 0x84;       break;  /* Power */
+               case 0x2a:      return FALSE;                   /* XXX PrtSrc */
+               default:
+                       *scancode += 0x78;
+               }
+               break;
+       case 0x61:
+               keyboard->scanprefix = (*scancode == 0x1d) ? 0x1d : 0;
+               return FALSE;
+       case 0x1d:
+               keyboard->scanprefix = 0;
+               if (*scancode != 0x45)
+                       return FALSE;
+               *scancode = 0x66;                               /* Pause */
+       }
+
+       *scancode += MIN_KEYCODE;
+       return TRUE;
 }
Index: src/ws.h
===================================================================
RCS file: /cvs/xenocara/driver/xf86-input-ws/src/ws.h,v
retrieving revision 1.12
diff -u -p -r1.12 ws.h
--- src/ws.h    12 Jun 2012 17:44:56 -0000      1.12
+++ src/ws.h    11 Jul 2012 12:28:19 -0000
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <termios.h>
 #include <dev/wscons/wsconsio.h>
 
 /* #undef DEBUG */
@@ -27,12 +28,15 @@ extern int ws_debug_level;
 #endif
 
 #define NAXES          2       /* X and Y axes only */
-#define NBUTTONS       32      /* max theoretical buttons */
-#define DFLTBUTTONS    3       /* default number of buttons */
 #define NUMEVENTS      16      /* max # of ws events to read at once */
 
+#define MINBUTTONS     3       /* min buttons */
+#define MAXBUTTONS     32      /* max theoretical buttons */
+
 #define WS_NOMAP       0
 
+#define MIN_KEYCODE    8
+
 /* axis specific data for wheel */
 typedef struct {
        int negative;
@@ -40,8 +44,7 @@ typedef struct {
        int traveled_distance;
 } WheelAxis, *WheelAxisPtr;
 
-typedef struct WSDevice {
-       char *devName;                  /* device name */
+typedef struct {
        int type;                       /* ws device type */
        unsigned int lastButtons;       /* last state of buttons */
        int old_ax, old_ay;
@@ -57,7 +60,7 @@ typedef struct WSDevice {
 
        /* # of buttons and config-file specified button mapping */
        unsigned int buttons;
-       unsigned char btnmap[NBUTTONS + 1];
+       unsigned char btnmap[MAXBUTTONS + 1];
 
        /* Middle mouse button emulation */
        struct {
@@ -80,6 +83,26 @@ typedef struct WSDevice {
                Time expires;           /* time of expiry */
                Time timeout;
        } emulateWheel;
+} WSPointerRec, *WSPointerPtr;
+
+typedef struct {
+       XkbRMLVOSet rmlvo;
+       struct termios kbdtty;
+       int scanprefix;
+} WSKeyboardRec, *WSKeyboardPtr;
+
+typedef struct {
+       char *devName;                  /* device name */
+
+       int (*PreInit)(InputDriverPtr, InputInfoPtr, int);
+       int (*DeviceInit)(DeviceIntPtr);
+       int (*DeviceOn)(DeviceIntPtr);
+       void (*DeviceOff)(DeviceIntPtr);
+       int (*Open)(InputInfoPtr);
+       void (*Close)(InputInfoPtr);
+
+       WSPointerPtr cursor;
+       WSKeyboardPtr keyboard;
 } WSDeviceRec, *WSDevicePtr;
 
 /* Middle mouse button emulation */

Reply via email to