| 1 | /* Portions of this file were derived from the following files: |
| 2 | * |
| 3 | ********************************************************************** |
| 4 | * |
| 5 | * xfree86/common/xf86KbdLnx.c |
| 6 | * |
| 7 | * Linux version of keymapping setup. The kernel (since 0.99.14) has support |
| 8 | * for fully remapping the keyboard, but there are some differences between |
| 9 | * the Linux map and the SVR4 map (esp. in the extended keycodes). We also |
| 10 | * remove the restriction on what keycodes can be remapped. |
| 11 | * Orest Zborowski. |
| 12 | * |
| 13 | * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. |
| 14 | * |
| 15 | * Permission to use, copy, modify, distribute, and sell this software and its |
| 16 | * documentation for any purpose is hereby granted without fee, provided that |
| 17 | * the above copyright notice appear in all copies and that both that |
| 18 | * copyright notice and this permission notice appear in supporting |
| 19 | * documentation, and that the name of Thomas Roell not be used in |
| 20 | * advertising or publicity pertaining to distribution of the software without |
| 21 | * specific, written prior permission. Thomas Roell makes no representations |
| 22 | * about the suitability of this software for any purpose. It is provided |
| 23 | * "as is" without express or implied warranty. |
| 24 | * |
| 25 | * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 26 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| 27 | * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 28 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
| 29 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 30 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 31 | * PERFORMANCE OF THIS SOFTWARE. |
| 32 | * |
| 33 | */ |
| 34 | |
| 35 | /* |
| 36 | * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. |
| 37 | * |
| 38 | * All Rights Reserved. |
| 39 | * |
| 40 | * Permission is hereby granted, free of charge, to any person obtaining |
| 41 | * a copy of this software and associated documentation files (the |
| 42 | * "Software"), to deal in the Software without restriction, including |
| 43 | * without limitation on the rights to use, copy, modify, merge, |
| 44 | * publish, distribute, sublicense, and/or sell copies of the Software, |
| 45 | * and to permit persons to whom the Software is furnished to do so, |
| 46 | * subject to the following conditions: |
| 47 | * |
| 48 | * The above copyright notice and this permission notice (including the |
| 49 | * next paragraph) shall be included in all copies or substantial |
| 50 | * portions of the Software. |
| 51 | * |
| 52 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 53 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 54 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 55 | * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS |
| 56 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 57 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 58 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 59 | * SOFTWARE. |
| 60 | */ |
| 61 | |
| 62 | /* |
| 63 | * Authors: |
| 64 | * Rickard E. (Rik) Faith <faith@redhat.com> |
| 65 | * |
| 66 | */ |
| 67 | |
| 68 | /** \file |
| 69 | * |
| 70 | * This code implements a low-level device driver for a USB keyboard |
| 71 | * under Linux. The keymap description is derived from code by Thomas |
| 72 | * Roell, Orest Zborowski. */ |
| 73 | |
| 74 | #ifdef HAVE_DMX_CONFIG_H |
| 75 | #include <dmx-config.h> |
| 76 | #endif |
| 77 | |
| 78 | #include "atKeynames.h" |
| 79 | #include "usb-private.h" |
| 80 | |
| 81 | #define USB_KEYBOARD_DEBUG 0 |
| 82 | |
| 83 | /*****************************************************************************/ |
| 84 | /* Define some macros to make it easier to move this file to another |
| 85 | * part of the Xserver tree. All calls to the dmx* layer are #defined |
| 86 | * here for the .c file. The .h file will also have to be edited. */ |
| 87 | #include "usb-keyboard.h" |
| 88 | #include <xkbsrv.h> |
| 89 | |
| 90 | #define GETPRIV myPrivate *priv \ |
| 91 | = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private |
| 92 | |
| 93 | #define LOG0(f) dmxLog(dmxDebug,f) |
| 94 | #define LOG1(f,a) dmxLog(dmxDebug,f,a) |
| 95 | #define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) |
| 96 | #define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) |
| 97 | #define FATAL0(f) dmxLog(dmxFatal,f) |
| 98 | #define FATAL1(f,a) dmxLog(dmxFatal,f,a) |
| 99 | #define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) |
| 100 | #define MOTIONPROC dmxMotionProcPtr |
| 101 | #define ENQUEUEPROC dmxEnqueueProcPtr |
| 102 | #define CHECKPROC dmxCheckSpecialProcPtr |
| 103 | #define BLOCK DMXBlockType |
| 104 | |
| 105 | /* End of interface definitions. */ |
| 106 | /*****************************************************************************/ |
| 107 | |
| 108 | #define GLYPHS_PER_KEY 4 |
| 109 | #define NUM_KEYCODES 248 |
| 110 | #define MIN_KEYCODE 8 |
| 111 | #define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) |
| 112 | |
| 113 | static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { |
| 114 | /* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */ |
| 115 | /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 116 | /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, |
| 117 | /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, |
| 118 | /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, |
| 119 | /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, |
| 120 | /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, |
| 121 | /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, |
| 122 | /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, |
| 123 | /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, |
| 124 | /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, |
| 125 | /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, |
| 126 | /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, |
| 127 | /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, |
| 128 | /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, |
| 129 | /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, |
| 130 | /* 0x0f */ XK_Tab, XK_ISO_Left_Tab, NoSymbol, NoSymbol, |
| 131 | /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, |
| 132 | /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, |
| 133 | /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, |
| 134 | /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, |
| 135 | /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, |
| 136 | /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, |
| 137 | /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, |
| 138 | /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, |
| 139 | /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, |
| 140 | /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, |
| 141 | /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, |
| 142 | /* 0x1b */ XK_bracketright, XK_braceright, NoSymbol, NoSymbol, |
| 143 | /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, |
| 144 | /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, |
| 145 | /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, |
| 146 | /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, |
| 147 | /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, |
| 148 | /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, |
| 149 | /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, |
| 150 | /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, |
| 151 | /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, |
| 152 | /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, |
| 153 | /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, |
| 154 | /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, |
| 155 | /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, |
| 156 | /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, |
| 157 | /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, |
| 158 | /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, |
| 159 | /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, |
| 160 | /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, |
| 161 | /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, |
| 162 | /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, |
| 163 | /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, |
| 164 | /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, |
| 165 | /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, |
| 166 | /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, |
| 167 | /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, |
| 168 | /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, |
| 169 | /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, |
| 170 | /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, |
| 171 | /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, |
| 172 | /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, |
| 173 | /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, |
| 174 | /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, |
| 175 | /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, |
| 176 | /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, |
| 177 | /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, |
| 178 | /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, |
| 179 | /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, |
| 180 | /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, |
| 181 | /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, |
| 182 | /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, |
| 183 | /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, |
| 184 | /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, |
| 185 | /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, |
| 186 | /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, |
| 187 | /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, |
| 188 | /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, |
| 189 | /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, |
| 190 | /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, |
| 191 | /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, |
| 192 | /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, |
| 193 | /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, |
| 194 | /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, |
| 195 | /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, |
| 196 | /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, |
| 197 | /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, |
| 198 | /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, |
| 199 | /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, |
| 200 | /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 201 | /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, |
| 202 | /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, |
| 203 | /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, |
| 204 | /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 205 | /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 206 | /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 207 | /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 208 | /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, |
| 209 | /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 210 | /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 211 | /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, |
| 212 | /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, |
| 213 | /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, |
| 214 | /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, |
| 215 | /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, |
| 216 | /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, |
| 217 | /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, |
| 218 | /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol, |
| 219 | /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, |
| 220 | /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol, |
| 221 | /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol, |
| 222 | /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol, |
| 223 | /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol, |
| 224 | /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol, |
| 225 | /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, |
| 226 | /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, |
| 227 | /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 228 | /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 229 | /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 230 | /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 231 | /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 232 | /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 233 | /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 234 | /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, |
| 235 | /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 236 | /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 237 | /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, |
| 238 | /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 239 | /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, |
| 240 | /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol, |
| 241 | /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol, |
| 242 | /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, |
| 243 | }; |
| 244 | |
| 245 | static int |
| 246 | kbdUSBKeyDown(myPrivate * priv, int keyCode) |
| 247 | { |
| 248 | CARD8 byte = keyCode >> 5; |
| 249 | CARD32 bit = 1 << (keyCode & 0x1f); |
| 250 | |
| 251 | if (byte > NUM_STATE_ENTRIES) |
| 252 | return 0; |
| 253 | return priv->kbdState[byte] & bit; |
| 254 | } |
| 255 | |
| 256 | static void |
| 257 | kbdUSBKeyState(myPrivate * priv, int type, int keyCode) |
| 258 | { |
| 259 | CARD8 byte = keyCode >> 5; |
| 260 | CARD32 bit = 1 << (keyCode & 0x1f); |
| 261 | |
| 262 | if (byte > NUM_STATE_ENTRIES) |
| 263 | return; |
| 264 | if (type == KeyPress) |
| 265 | priv->kbdState[byte] |= bit; |
| 266 | else |
| 267 | priv->kbdState[byte] &= ~bit; |
| 268 | } |
| 269 | |
| 270 | /** Set the LEDs. */ |
| 271 | void |
| 272 | kbdUSBCtrl(DevicePtr pDev, KeybdCtrl * ctrl) |
| 273 | { |
| 274 | GETPRIV; |
| 275 | struct timeval tv; |
| 276 | struct input_event event; |
| 277 | int i, led; |
| 278 | |
| 279 | gettimeofday(&tv, NULL); |
| 280 | for (i = 0; i < 5; i++) { |
| 281 | event.time.tv_sec = tv.tv_sec; |
| 282 | event.time.tv_usec = tv.tv_usec; |
| 283 | event.type = EV_LED; |
| 284 | if (i == 0) |
| 285 | led = 1; /* LED_CAPSL == 0x01 */ |
| 286 | else if (i == 1) |
| 287 | led = 0; /* LED_NUML == 0x00 */ |
| 288 | else |
| 289 | led = i; |
| 290 | event.code = led; |
| 291 | event.value = ! !(ctrl->leds & (1 << led)); |
| 292 | write(priv->fd, &event, sizeof(event)); |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | /** Initialize \a pDev using #usbInit. */ |
| 297 | void |
| 298 | kbdUSBInit(DevicePtr pDev) |
| 299 | { |
| 300 | usbInit(pDev, usbKeyboard); |
| 301 | } |
| 302 | |
| 303 | static void |
| 304 | kbdUSBConvert(DevicePtr pDev, |
| 305 | unsigned int scanCode, |
| 306 | int value, |
| 307 | ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) |
| 308 | { |
| 309 | GETPRIV; |
| 310 | XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; |
| 311 | int type; |
| 312 | int keyCode; |
| 313 | KeySym keySym = NoSymbol; |
| 314 | int switching; |
| 315 | |
| 316 | /* Set up xEvent information */ |
| 317 | type = value ? KeyPress : KeyRelease; |
| 318 | keyCode = (scanCode & 0xff) + MIN_KEYCODE; |
| 319 | |
| 320 | /* Handle repeats */ |
| 321 | |
| 322 | if (keyCode >= xkbi->desc->min_key_code && |
| 323 | keyCode <= xkbi->desc->max_key_code) { |
| 324 | |
| 325 | int effectiveGroup = XkbGetEffectiveGroup(xkbi, |
| 326 | &xkbi->state, |
| 327 | scanCode); |
| 328 | |
| 329 | keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); |
| 330 | #if 0 |
| 331 | switch (keySym) { |
| 332 | case XK_Num_Lock: |
| 333 | case XK_Scroll_Lock: |
| 334 | case XK_Shift_Lock: |
| 335 | case XK_Caps_Lock: |
| 336 | /* Ignore releases and all but first press */ |
| 337 | if (kbdLinuxModIgnore(priv, &xE, keySym)) |
| 338 | return; |
| 339 | if (kbdLinuxKeyDown(priv, &xE)) |
| 340 | xE.u.u.type = KeyRelease; |
| 341 | else |
| 342 | xE.u.u.type = KeyPress; |
| 343 | break; |
| 344 | } |
| 345 | #endif |
| 346 | |
| 347 | /* If key is already down, ignore or autorepeat */ |
| 348 | if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) { |
| 349 | KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed; |
| 350 | |
| 351 | /* No auto-repeat? */ |
| 352 | if ((feed && !feed->ctrl.autoRepeat) |
| 353 | || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode] |
| 354 | || (feed && !(feed->ctrl.autoRepeats[keyCode >> 3] |
| 355 | & (1 << (keyCode & 7))))) |
| 356 | return; /* Ignore */ |
| 357 | |
| 358 | /* Do auto-repeat */ |
| 359 | enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); |
| 360 | type = KeyPress; |
| 361 | } |
| 362 | |
| 363 | /* If key is already up, ignore */ |
| 364 | if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) |
| 365 | return; |
| 366 | } |
| 367 | |
| 368 | switching = 0; |
| 369 | if (checkspecial && type == KeyPress) |
| 370 | switching = checkspecial(pDev, keySym); |
| 371 | if (!switching) { |
| 372 | if (enqueue) |
| 373 | enqueue(pDev, type, keyCode, keySym, NULL, block); |
| 374 | kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */ |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | /** Read an event from the \a pDev device. If the event is a motion |
| 379 | * event, enqueue it with the \a motion function. Otherwise, check for |
| 380 | * special keys with the \a checkspecial function and enqueue the event |
| 381 | * with the \a enqueue function. The \a block type is passed to the |
| 382 | * functions so that they may block SIGIO handling as appropriate to the |
| 383 | * caller of this function. */ |
| 384 | void |
| 385 | kbdUSBRead(DevicePtr pDev, |
| 386 | MOTIONPROC motion, |
| 387 | ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) |
| 388 | { |
| 389 | GETPRIV; |
| 390 | struct input_event raw; |
| 391 | |
| 392 | while (read(priv->fd, &raw, sizeof(raw)) > 0) { |
| 393 | #if USB_KEYBOARD_DEBUG |
| 394 | LOG3("KBD: type = %d, code = 0x%02x, value = %d\n", |
| 395 | raw.type, raw.code, raw.value); |
| 396 | #endif |
| 397 | kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block); |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | /** Turn \a pDev on (i.e., take input from \a pDev). */ |
| 402 | int |
| 403 | kbdUSBOn(DevicePtr pDev) |
| 404 | { |
| 405 | GETPRIV; |
| 406 | |
| 407 | if (priv->fd < 0) |
| 408 | kbdUSBInit(pDev); |
| 409 | return priv->fd; |
| 410 | } |
| 411 | |
| 412 | static void |
| 413 | kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) |
| 414 | { |
| 415 | KeySym *k, *mapCopy; |
| 416 | int i; |
| 417 | |
| 418 | mapCopy = malloc(sizeof(map)); |
| 419 | memcpy(mapCopy, map, sizeof(map)); |
| 420 | |
| 421 | /* compute the modifier map */ |
| 422 | for (i = 0; i < MAP_LENGTH; i++) |
| 423 | pModMap[i] = NoSymbol; /* make sure it is restored */ |
| 424 | |
| 425 | for (k = mapCopy, i = MIN_KEYCODE; |
| 426 | i < NUM_KEYCODES + MIN_KEYCODE; i++, k += 4) { |
| 427 | switch (*k) { |
| 428 | case XK_Shift_L: |
| 429 | case XK_Shift_R: |
| 430 | pModMap[i] = ShiftMask; |
| 431 | break; |
| 432 | case XK_Control_L: |
| 433 | case XK_Control_R: |
| 434 | pModMap[i] = ControlMask; |
| 435 | break; |
| 436 | case XK_Caps_Lock: |
| 437 | pModMap[i] = LockMask; |
| 438 | break; |
| 439 | case XK_Alt_L: |
| 440 | case XK_Alt_R: |
| 441 | pModMap[i] = AltMask; |
| 442 | break; |
| 443 | case XK_Num_Lock: |
| 444 | pModMap[i] = NumLockMask; |
| 445 | break; |
| 446 | case XK_Scroll_Lock: |
| 447 | pModMap[i] = ScrollLockMask; |
| 448 | break; |
| 449 | case XK_Kana_Lock: |
| 450 | case XK_Kana_Shift: |
| 451 | pModMap[i] = KanaMask; |
| 452 | break; |
| 453 | case XK_Mode_switch: |
| 454 | pModMap[i] = AltLangMask; |
| 455 | break; |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | pKeySyms->map = mapCopy; /* Must be XFree'able */ |
| 460 | pKeySyms->mapWidth = GLYPHS_PER_KEY; |
| 461 | pKeySyms->minKeyCode = MIN_KEYCODE; |
| 462 | pKeySyms->maxKeyCode = MAX_KEYCODE; |
| 463 | } |
| 464 | |
| 465 | /** Fill the \a info structure with information needed to initialize \a |
| 466 | * pDev. */ |
| 467 | void |
| 468 | kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) |
| 469 | { |
| 470 | info->keyboard = 1; |
| 471 | info->keyClass = 1; |
| 472 | kbdUSBGetMap(pDev, &info->keySyms, info->modMap); |
| 473 | info->focusClass = 1; |
| 474 | info->kbdFeedbackClass = 1; |
| 475 | info->names.keycodes = strdup("powerpcps2"); |
| 476 | info->force = 1; |
| 477 | } |