#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "atKeynames.h"
#include "usb-private.h"
#define USB_KEYBOARD_DEBUG 0
#include "usb-keyboard.h"
#define GETPRIV myPrivate *priv \
= ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
#define LOG0(f) dmxLog(dmxDebug,f)
#define LOG1(f,a) dmxLog(dmxDebug,f,a)
#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
#define FATAL0(f) dmxLog(dmxFatal,f)
#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
#define MOTIONPROC dmxMotionProcPtr
#define ENQUEUEPROC dmxEnqueueProcPtr
#define CHECKPROC dmxCheckSpecialProcPtr
#define BLOCK DMXBlockType
#define GLYPHS_PER_KEY 4
#define NUM_KEYCODES 248
#define MIN_KEYCODE 8
#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = {
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_Escape, NoSymbol, NoSymbol, NoSymbol,
XK_1, XK_exclam, NoSymbol, NoSymbol,
XK_2, XK_at, NoSymbol, NoSymbol,
XK_3, XK_numbersign, NoSymbol, NoSymbol,
XK_4, XK_dollar, NoSymbol, NoSymbol,
XK_5, XK_percent, NoSymbol, NoSymbol,
XK_6, XK_asciicircum, NoSymbol, NoSymbol,
XK_7, XK_ampersand, NoSymbol, NoSymbol,
XK_8, XK_asterisk, NoSymbol, NoSymbol,
XK_9, XK_parenleft, NoSymbol, NoSymbol,
XK_0, XK_parenright, NoSymbol, NoSymbol,
XK_minus, XK_underscore, NoSymbol, NoSymbol,
XK_equal, XK_plus, NoSymbol, NoSymbol,
XK_BackSpace, NoSymbol, NoSymbol, NoSymbol,
XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol,
XK_Q, NoSymbol, NoSymbol, NoSymbol,
XK_W, NoSymbol, NoSymbol, NoSymbol,
XK_E, NoSymbol, NoSymbol, NoSymbol,
XK_R, NoSymbol, NoSymbol, NoSymbol,
XK_T, NoSymbol, NoSymbol, NoSymbol,
XK_Y, NoSymbol, NoSymbol, NoSymbol,
XK_U, NoSymbol, NoSymbol, NoSymbol,
XK_I, NoSymbol, NoSymbol, NoSymbol,
XK_O, NoSymbol, NoSymbol, NoSymbol,
XK_P, NoSymbol, NoSymbol, NoSymbol,
XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol,
XK_bracketright,XK_braceright, NoSymbol, NoSymbol,
XK_Return, NoSymbol, NoSymbol, NoSymbol,
XK_Control_L, NoSymbol, NoSymbol, NoSymbol,
XK_A, NoSymbol, NoSymbol, NoSymbol,
XK_S, NoSymbol, NoSymbol, NoSymbol,
XK_D, NoSymbol, NoSymbol, NoSymbol,
XK_F, NoSymbol, NoSymbol, NoSymbol,
XK_G, NoSymbol, NoSymbol, NoSymbol,
XK_H, NoSymbol, NoSymbol, NoSymbol,
XK_J, NoSymbol, NoSymbol, NoSymbol,
XK_K, NoSymbol, NoSymbol, NoSymbol,
XK_L, NoSymbol, NoSymbol, NoSymbol,
XK_semicolon, XK_colon, NoSymbol, NoSymbol,
XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol,
XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol,
XK_Shift_L, NoSymbol, NoSymbol, NoSymbol,
XK_backslash, XK_bar, NoSymbol, NoSymbol,
XK_Z, NoSymbol, NoSymbol, NoSymbol,
XK_X, NoSymbol, NoSymbol, NoSymbol,
XK_C, NoSymbol, NoSymbol, NoSymbol,
XK_V, NoSymbol, NoSymbol, NoSymbol,
XK_B, NoSymbol, NoSymbol, NoSymbol,
XK_N, NoSymbol, NoSymbol, NoSymbol,
XK_M, NoSymbol, NoSymbol, NoSymbol,
XK_comma, XK_less, NoSymbol, NoSymbol,
XK_period, XK_greater, NoSymbol, NoSymbol,
XK_slash, XK_question, NoSymbol, NoSymbol,
XK_Shift_R, NoSymbol, NoSymbol, NoSymbol,
XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol,
XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol,
XK_space, NoSymbol, NoSymbol, NoSymbol,
XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol,
XK_F1, NoSymbol, NoSymbol, NoSymbol,
XK_F2, NoSymbol, NoSymbol, NoSymbol,
XK_F3, NoSymbol, NoSymbol, NoSymbol,
XK_F4, NoSymbol, NoSymbol, NoSymbol,
XK_F5, NoSymbol, NoSymbol, NoSymbol,
XK_F6, NoSymbol, NoSymbol, NoSymbol,
XK_F7, NoSymbol, NoSymbol, NoSymbol,
XK_F8, NoSymbol, NoSymbol, NoSymbol,
XK_F9, NoSymbol, NoSymbol, NoSymbol,
XK_F10, NoSymbol, NoSymbol, NoSymbol,
XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol,
XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol,
XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol,
XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol,
XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol,
XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol,
XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol,
XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol,
XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol,
XK_KP_Add, NoSymbol, NoSymbol, NoSymbol,
XK_KP_End, XK_KP_1, NoSymbol, NoSymbol,
XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol,
XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol,
XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol,
XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol,
XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_less, XK_greater, NoSymbol, NoSymbol,
XK_F11, NoSymbol, NoSymbol, NoSymbol,
XK_F12, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_Begin, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol,
XK_Control_R, NoSymbol, NoSymbol, NoSymbol,
XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol,
XK_Print, NoSymbol, NoSymbol, NoSymbol,
XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol,
XK_Break, NoSymbol, NoSymbol, NoSymbol,
XK_Home, NoSymbol, NoSymbol, NoSymbol,
XK_Up, NoSymbol, NoSymbol, NoSymbol,
XK_Prior, NoSymbol, NoSymbol, NoSymbol,
XK_Left, NoSymbol, NoSymbol, NoSymbol,
XK_Right, NoSymbol, NoSymbol, NoSymbol,
XK_End, NoSymbol, NoSymbol, NoSymbol,
XK_Down, NoSymbol, NoSymbol, NoSymbol,
XK_Next, NoSymbol, NoSymbol, NoSymbol,
XK_Insert, NoSymbol, NoSymbol, NoSymbol,
XK_Delete, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_Pause, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_Menu, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
NoSymbol, NoSymbol, NoSymbol, NoSymbol,
XK_Super_L, NoSymbol, NoSymbol, NoSymbol,
XK_Super_R, NoSymbol, NoSymbol, NoSymbol,
XK_Menu, NoSymbol, NoSymbol, NoSymbol,
};
static int kbdUSBKeyDown(myPrivate *priv, int keyCode)
{
CARD8 byte = keyCode >> 5;
CARD32 bit = 1 << (keyCode & 0x1f);
if (byte > NUM_STATE_ENTRIES) return 0;
return priv->kbdState[byte] & bit;
}
static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode)
{
CARD8 byte = keyCode >> 5;
CARD32 bit = 1 << (keyCode & 0x1f);
if (byte > NUM_STATE_ENTRIES) return;
if (type == KeyPress) priv->kbdState[byte] |= bit;
else priv->kbdState[byte] &= ~bit;
}
void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
{
GETPRIV;
struct timeval tv;
struct input_event event;
int i, led;
gettimeofday(&tv, NULL);
for (i = 0; i < 5; i++) {
event.time.tv_sec = tv.tv_sec;
event.time.tv_usec = tv.tv_usec;
event.type = EV_LED;
if (i == 0) led = 1;
else if (i == 1) led = 0;
else led = i;
event.code = led;
event.value = !!(ctrl->leds & (1 << led));
write(priv->fd, &event, sizeof(event));
}
}
void kbdUSBInit(DevicePtr pDev)
{
usbInit(pDev, usbKeyboard);
}
static void kbdUSBConvert(DevicePtr pDev,
unsigned int scanCode,
int value,
ENQUEUEPROC enqueue,
CHECKPROC checkspecial,
BLOCK block)
{
GETPRIV;
KeySymsPtr pKeySyms = &priv->pDevice->key->curKeySyms;
int type;
int keyCode;
KeySym keySym = NoSymbol;
int switching;
type = value ? KeyPress : KeyRelease;
keyCode = (scanCode & 0xff) + MIN_KEYCODE;
if (keyCode >= pKeySyms->minKeyCode && keyCode <= pKeySyms->maxKeyCode) {
keySym = pKeySyms->map[(keyCode - pKeySyms->minKeyCode)
* pKeySyms->mapWidth];
#if 0
switch (keySym) {
case XK_Num_Lock:
case XK_Scroll_Lock:
case XK_Shift_Lock:
case XK_Caps_Lock:
if (kbdLinuxModIgnore(priv, &xE, keySym)) return;
if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease;
else xE.u.u.type = KeyPress;
break;
}
#endif
if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) {
KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed;
if ((feed && !feed->ctrl.autoRepeat)
|| priv->pDevice->key->modifierMap[keyCode]
|| (feed
&& !(feed->ctrl.autoRepeats[keyCode >> 3]
& (1 << (keyCode & 7))))) return;
enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block);
type = KeyPress;
}
if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return;
}
switching = 0;
if (checkspecial && type == KeyPress)
switching = checkspecial(pDev, keySym);
if (!switching) {
if (enqueue)
enqueue(pDev, type, keyCode, keySym, NULL, block);
kbdUSBKeyState(priv, type, keyCode);
}
}
void kbdUSBRead(DevicePtr pDev,
MOTIONPROC motion,
ENQUEUEPROC enqueue,
CHECKPROC checkspecial,
BLOCK block)
{
GETPRIV;
struct input_event raw;
while (read(priv->fd, &raw, sizeof(raw)) > 0) {
#if USB_KEYBOARD_DEBUG
LOG3("KBD: type = %d, code = 0x%02x, value = %d\n",
raw.type, raw.code, raw.value);
#endif
kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block);
}
}
int kbdUSBOn(DevicePtr pDev)
{
GETPRIV;
if (priv->fd < 0) kbdUSBInit(pDev);
return priv->fd;
}
static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
{
KeySym *k, *mapCopy;
int i;
mapCopy = xalloc(sizeof(map));
memcpy(mapCopy, map, sizeof(map));
for (i = 0; i < MAP_LENGTH; i++)
pModMap[i] = NoSymbol;
for (k = mapCopy, i = MIN_KEYCODE;
i < NUM_KEYCODES + MIN_KEYCODE;
i++, k += 4) {
switch(*k) {
case XK_Shift_L:
case XK_Shift_R: pModMap[i] = ShiftMask; break;
case XK_Control_L:
case XK_Control_R: pModMap[i] = ControlMask; break;
case XK_Caps_Lock: pModMap[i] = LockMask; break;
case XK_Alt_L:
case XK_Alt_R: pModMap[i] = AltMask; break;
case XK_Num_Lock: pModMap[i] = NumLockMask; break;
case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break;
case XK_Kana_Lock:
case XK_Kana_Shift: pModMap[i] = KanaMask; break;
case XK_Mode_switch: pModMap[i] = AltLangMask; break;
}
}
pKeySyms->map = mapCopy;
pKeySyms->mapWidth = GLYPHS_PER_KEY;
pKeySyms->minKeyCode = MIN_KEYCODE;
pKeySyms->maxKeyCode = MAX_KEYCODE;
}
void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
{
info->keyboard = 1;
info->keyClass = 1;
kbdUSBGetMap(pDev, &info->keySyms, info->modMap);
info->focusClass = 1;
info->kbdFeedbackClass = 1;
#ifdef XKB
info->names.keycodes = xstrdup("powerpcps2");
info->force = 1;
#endif
}