#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kbio.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <dev/misc/evdev/evdev.h>
#include <dev/misc/evdev/evdev_private.h>
#include <dev/misc/evdev/input.h>
#include <dev/misc/kbd/kbdreg.h>
#define NONE KEY_RESERVED
static uint16_t evdev_usb_scancodes[256] = {
NONE, NONE, NONE, NONE, KEY_A, KEY_B, KEY_C, KEY_D,
KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB,
KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT,
KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10,
KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK,
KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK,
KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS,
KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3,
KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7,
KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL,
KEY_F13, KEY_F14, KEY_F15, KEY_F16,
KEY_F17, KEY_F18, KEY_F19, KEY_F20,
KEY_F21, KEY_F22, KEY_F23, KEY_F24,
KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT,
KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
KEY_VOLUMEUP, KEY_VOLUMEDOWN, NONE, NONE,
NONE, KEY_KPCOMMA, NONE, KEY_RO,
KEY_KATAKANAHIRAGANA, KEY_YEN,KEY_HENKAN, KEY_MUHENKAN,
KEY_KPJPCOMMA, NONE, NONE, NONE,
KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
KEY_ZENKAKUHANKAKU, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA,
KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,KEY_NEXTSONG,
KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP,
KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT,
KEY_SLEEP, KEY_COFFEE, KEY_REFRESH, KEY_CALC,
NONE, NONE, NONE, NONE,
};
static uint16_t evdev_at_set1_scancodes[] = {
NONE, KEY_ESC, KEY_1, KEY_2,
KEY_3, KEY_4, KEY_5, KEY_6,
KEY_7, KEY_8, KEY_9, KEY_0,
KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB,
KEY_Q, KEY_W, KEY_E, KEY_R,
KEY_T, KEY_Y, KEY_U, KEY_I,
KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
KEY_ENTER, KEY_LEFTCTRL, KEY_A, KEY_S,
KEY_D, KEY_F, KEY_G, KEY_H,
KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
KEY_APOSTROPHE, KEY_GRAVE, KEY_LEFTSHIFT, KEY_BACKSLASH,
KEY_Z, KEY_X, KEY_C, KEY_V,
KEY_B, KEY_N, KEY_M, KEY_COMMA,
KEY_DOT, KEY_SLASH, KEY_RIGHTSHIFT, KEY_KPASTERISK,
KEY_LEFTALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
KEY_F2, KEY_F3, KEY_F4, KEY_F5,
KEY_F6, KEY_F7, KEY_F8, KEY_F9,
KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KP7,
KEY_KP8, KEY_KP9, KEY_KPMINUS, KEY_KP4,
KEY_KP5, KEY_KP6, KEY_KPPLUS, KEY_KP1,
KEY_KP2, KEY_KP3, KEY_KP0, KEY_KPDOT,
NONE, NONE, KEY_102ND, KEY_F11,
KEY_F12, NONE, NONE, NONE,
NONE, KEY_F13, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
KEY_KATAKANAHIRAGANA, KEY_HANJA, KEY_HANGEUL, KEY_RO,
NONE, NONE, KEY_ZENKAKUHANKAKU, KEY_HIRAGANA,
KEY_KATAKANA, KEY_HENKAN, NONE, KEY_MUHENKAN,
NONE, KEY_YEN, KEY_KPCOMMA, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
KEY_PREVIOUSSONG, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, KEY_NEXTSONG, NONE, NONE,
KEY_KPENTER, KEY_RIGHTCTRL, NONE, NONE,
KEY_MUTE, KEY_CALC, KEY_PLAYPAUSE, NONE,
KEY_STOPCD, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, KEY_VOLUMEDOWN, NONE,
KEY_VOLUMEUP, NONE, KEY_HOMEPAGE, NONE,
NONE, KEY_KPSLASH, NONE, KEY_SYSRQ,
KEY_RIGHTALT, NONE, NONE, KEY_F13,
KEY_F14, KEY_F15, KEY_F16, KEY_F17,
KEY_F18, KEY_F19, KEY_F20, KEY_F21,
KEY_F22, NONE, KEY_PAUSE, KEY_HOME,
KEY_UP, KEY_PAGEUP, NONE, KEY_LEFT,
NONE, KEY_RIGHT, NONE, KEY_END,
KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE,
NONE, NONE, NONE, KEY_F23,
KEY_F24, NONE, NONE, KEY_LEFTMETA,
KEY_RIGHTMETA, KEY_MENU, KEY_POWER, KEY_SLEEP,
NONE, NONE, NONE, KEY_WAKEUP,
NONE, KEY_SEARCH, KEY_BOOKMARKS, KEY_REFRESH,
KEY_STOP, KEY_FORWARD, KEY_BACK, KEY_COMPUTER,
KEY_MAIL, KEY_MEDIA, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
NONE, NONE, NONE, NONE,
};
static uint16_t evdev_mouse_button_codes[] = {
BTN_LEFT,
BTN_MIDDLE,
BTN_RIGHT,
BTN_SIDE,
BTN_EXTRA,
BTN_FORWARD,
BTN_BACK,
BTN_TASK,
};
static uint16_t evdev_led_codes[] = {
LED_CAPSL,
LED_NUML,
LED_SCROLLL,
};
static uint16_t evdev_nfinger_codes[] = {
BTN_TOOL_FINGER,
BTN_TOOL_DOUBLETAP,
BTN_TOOL_TRIPLETAP,
BTN_TOOL_QUADTAP,
BTN_TOOL_QUINTTAP,
};
uint16_t
evdev_hid2key(int scancode)
{
return evdev_usb_scancodes[scancode];
}
void
evdev_support_all_known_keys(struct evdev_dev *evdev)
{
size_t i;
for (i = KEY_RESERVED; i < nitems(evdev_at_set1_scancodes); i++)
if (evdev_at_set1_scancodes[i] != NONE)
evdev_support_key(evdev, evdev_at_set1_scancodes[i]);
}
uint16_t
evdev_scancode2key(int *state, int scancode)
{
uint16_t keycode;
keycode = evdev_at_set1_scancodes[scancode & 0x7f];
switch (*state) {
case 0x00:
switch(scancode) {
case 0xE0:
case 0xE1:
*state = scancode;
return (NONE);
}
break;
case 0xE0:
*state = 0;
keycode = evdev_at_set1_scancodes[0x80 + (scancode & 0x7f)];
break;
case 0xE1:
*state = 0;
if ((scancode & 0x7f) == 0x1D)
*state = scancode;
return (NONE);
case 0x1D:
case 0x9D:
if ((*state ^ scancode) & 0x80)
return (NONE);
*state = 0;
if ((scancode & 0x7f) != 0x45)
return (NONE);
keycode = KEY_PAUSE;
break;
}
return (keycode);
}
void
evdev_push_mouse_btn(struct evdev_dev *evdev, int buttons)
{
size_t i;
for (i = 0; i < nitems(evdev_mouse_button_codes); i++)
evdev_push_key(evdev, evdev_mouse_button_codes[i],
buttons & (1 << i));
}
void
evdev_push_leds(struct evdev_dev *evdev, int leds)
{
size_t i;
if (evdev == NULL)
return;
for (i = 0; i < nitems(evdev_led_codes); i++)
evdev_push_led(evdev, evdev_led_codes[i], leds & (1 << i));
}
void
evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd)
{
if (evdev == NULL)
return;
evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
}
void
evdev_support_nfingers(struct evdev_dev *evdev, int nfingers)
{
int i;
for (i = 0; i < MIN(nitems(evdev_nfinger_codes), nfingers); i++)
evdev_support_key(evdev, evdev_nfinger_codes[i]);
}
void
evdev_send_nfingers(struct evdev_dev *evdev, int nfingers)
{
int i;
EVDEV_LOCK_ASSERT(evdev);
if (nfingers > nitems(evdev_nfinger_codes))
nfingers = nitems(evdev_nfinger_codes);
for (i = 0; i < nitems(evdev_nfinger_codes); i++)
evdev_send_event(evdev, EV_KEY, evdev_nfinger_codes[i],
nfingers == i + 1);
}
void
evdev_push_nfingers(struct evdev_dev *evdev, int nfingers)
{
EVDEV_ENTER(evdev);
evdev_send_nfingers(evdev, nfingers);
EVDEV_EXIT(evdev);
}
void
evdev_ev_kbd_event(struct evdev_dev *evdev, uint16_t type,
uint16_t code, int32_t value)
{
keyboard_t *kbd = (keyboard_t *)evdev_get_softc(evdev);
int delay[2], leds, oleds;
size_t i;
if (type == EV_LED) {
leds = oleds = KBD_LED_VAL(kbd);
for (i = 0; i < nitems(evdev_led_codes); i++) {
if (evdev_led_codes[i] == code) {
if (value)
leds |= 1 << i;
else
leds &= ~(1 << i);
if (leds != oleds)
kbd_ioctl(kbd, KDSETLED,
(caddr_t)&leds);
break;
}
}
} else if (type == EV_REP && code == REP_DELAY) {
delay[0] = value;
delay[1] = kbd->kb_delay2;
kbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
} else if (type == EV_REP && code == REP_PERIOD) {
delay[0] = kbd->kb_delay1;
delay[1] = value;
kbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
}
}