xref: /dflybsd-src/sys/dev/misc/evdev/evdev_utils.c (revision a162a738eca94f99d45d88429e86cfd0fbfbe95d)
1d3d1dd3eSPeeter Must /*-
2d3d1dd3eSPeeter Must  * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
3d3d1dd3eSPeeter Must  * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
4d3d1dd3eSPeeter Must  * All rights reserved.
5d3d1dd3eSPeeter Must  *
6d3d1dd3eSPeeter Must  * Redistribution and use in source and binary forms, with or without
7d3d1dd3eSPeeter Must  * modification, are permitted provided that the following conditions
8d3d1dd3eSPeeter Must  * are met:
9d3d1dd3eSPeeter Must  * 1. Redistributions of source code must retain the above copyright
10d3d1dd3eSPeeter Must  *    notice, this list of conditions and the following disclaimer.
11d3d1dd3eSPeeter Must  * 2. Redistributions in binary form must reproduce the above copyright
12d3d1dd3eSPeeter Must  *    notice, this list of conditions and the following disclaimer in the
13d3d1dd3eSPeeter Must  *    documentation and/or other materials provided with the distribution.
14d3d1dd3eSPeeter Must  *
15d3d1dd3eSPeeter Must  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16d3d1dd3eSPeeter Must  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17d3d1dd3eSPeeter Must  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18d3d1dd3eSPeeter Must  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19d3d1dd3eSPeeter Must  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20d3d1dd3eSPeeter Must  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21d3d1dd3eSPeeter Must  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22d3d1dd3eSPeeter Must  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23d3d1dd3eSPeeter Must  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24d3d1dd3eSPeeter Must  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25d3d1dd3eSPeeter Must  * SUCH DAMAGE.
26d3d1dd3eSPeeter Must  *
27d3d1dd3eSPeeter Must  * $FreeBSD$
28d3d1dd3eSPeeter Must  */
29d3d1dd3eSPeeter Must 
30d3d1dd3eSPeeter Must #include <sys/param.h>
31d3d1dd3eSPeeter Must #include <sys/bus.h>
32d3d1dd3eSPeeter Must #include <sys/conf.h>
33d3d1dd3eSPeeter Must #include <sys/kbio.h>
34d3d1dd3eSPeeter Must #include <sys/kernel.h>
35d3d1dd3eSPeeter Must #include <sys/malloc.h>
36d3d1dd3eSPeeter Must #include <sys/systm.h>
37d3d1dd3eSPeeter Must 
38d3d1dd3eSPeeter Must #include <dev/misc/evdev/evdev.h>
39*a162a738SMichael Neumann #include <dev/misc/evdev/evdev_private.h>
40d3d1dd3eSPeeter Must #include <dev/misc/evdev/input.h>
41d3d1dd3eSPeeter Must #include <dev/misc/kbd/kbdreg.h>
42d3d1dd3eSPeeter Must 
43d3d1dd3eSPeeter Must #define	NONE	KEY_RESERVED
44d3d1dd3eSPeeter Must 
45d3d1dd3eSPeeter Must static uint16_t evdev_usb_scancodes[256] = {
46d3d1dd3eSPeeter Must 	/* 0x00 - 0x27 */
47d3d1dd3eSPeeter Must 	NONE,	NONE,	NONE,	NONE,	KEY_A,	KEY_B,	KEY_C,	KEY_D,
48d3d1dd3eSPeeter Must 	KEY_E,	KEY_F,	KEY_G,	KEY_H,	KEY_I,	KEY_J,	KEY_K,	KEY_L,
49d3d1dd3eSPeeter Must 	KEY_M,	KEY_N,	KEY_O,	KEY_P,	KEY_Q,	KEY_R,	KEY_S,	KEY_T,
50d3d1dd3eSPeeter Must 	KEY_U,	KEY_V,	KEY_W,	KEY_X,	KEY_Y,	KEY_Z,	KEY_1,	KEY_2,
51d3d1dd3eSPeeter Must 	KEY_3,	KEY_4,	KEY_5,	KEY_6,	KEY_7,	KEY_8,	KEY_9,	KEY_0,
52d3d1dd3eSPeeter Must 	/* 0x28 - 0x3f */
53d3d1dd3eSPeeter Must 	KEY_ENTER,	KEY_ESC,	KEY_BACKSPACE,	KEY_TAB,
54d3d1dd3eSPeeter Must 	KEY_SPACE,	KEY_MINUS,	KEY_EQUAL,	KEY_LEFTBRACE,
55d3d1dd3eSPeeter Must 	KEY_RIGHTBRACE,	KEY_BACKSLASH,	KEY_BACKSLASH,	KEY_SEMICOLON,
56d3d1dd3eSPeeter Must 	KEY_APOSTROPHE,	KEY_GRAVE,	KEY_COMMA,	KEY_DOT,
57d3d1dd3eSPeeter Must 	KEY_SLASH,	KEY_CAPSLOCK,	KEY_F1,		KEY_F2,
58d3d1dd3eSPeeter Must 	KEY_F3,		KEY_F4,		KEY_F5,		KEY_F6,
59d3d1dd3eSPeeter Must 	/* 0x40 - 0x5f */
60d3d1dd3eSPeeter Must 	KEY_F7,		KEY_F8,		KEY_F9,		KEY_F10,
61d3d1dd3eSPeeter Must 	KEY_F11,	KEY_F12,	KEY_SYSRQ,	KEY_SCROLLLOCK,
62d3d1dd3eSPeeter Must 	KEY_PAUSE,	KEY_INSERT,	KEY_HOME,	KEY_PAGEUP,
63d3d1dd3eSPeeter Must 	KEY_DELETE,	KEY_END,	KEY_PAGEDOWN,	KEY_RIGHT,
64d3d1dd3eSPeeter Must 	KEY_LEFT,	KEY_DOWN,	KEY_UP,		KEY_NUMLOCK,
6566b940daSPeeter Must 	KEY_KPSLASH,	KEY_KPASTERISK,	KEY_KPMINUS,	KEY_KPPLUS,
66d3d1dd3eSPeeter Must 	KEY_KPENTER,	KEY_KP1,	KEY_KP2,	KEY_KP3,
67d3d1dd3eSPeeter Must 	KEY_KP4,	KEY_KP5,	KEY_KP6,	KEY_KP7,
68d3d1dd3eSPeeter Must 	/* 0x60 - 0x7f */
69d3d1dd3eSPeeter Must 	KEY_KP8,	KEY_KP9,	KEY_KP0,	KEY_KPDOT,
70d3d1dd3eSPeeter Must 	KEY_102ND,	KEY_COMPOSE,	KEY_POWER,	KEY_KPEQUAL,
71d3d1dd3eSPeeter Must 	KEY_F13,	KEY_F14,	KEY_F15,	KEY_F16,
72d3d1dd3eSPeeter Must 	KEY_F17,	KEY_F18,	KEY_F19,	KEY_F20,
73d3d1dd3eSPeeter Must 	KEY_F21,	KEY_F22,	KEY_F23,	KEY_F24,
74d3d1dd3eSPeeter Must 	KEY_OPEN,	KEY_HELP,	KEY_PROPS,	KEY_FRONT,
75d3d1dd3eSPeeter Must 	KEY_STOP,	KEY_AGAIN,	KEY_UNDO,	KEY_CUT,
76d3d1dd3eSPeeter Must 	KEY_COPY,	KEY_PASTE,	KEY_FIND,	KEY_MUTE,
77d3d1dd3eSPeeter Must 	/* 0x80 - 0x9f */
78d3d1dd3eSPeeter Must 	KEY_VOLUMEUP,	KEY_VOLUMEDOWN,	NONE,		NONE,
79d3d1dd3eSPeeter Must 	NONE,		KEY_KPCOMMA,	NONE,		KEY_RO,
80d3d1dd3eSPeeter Must 	KEY_KATAKANAHIRAGANA,	KEY_YEN,KEY_HENKAN,	KEY_MUHENKAN,
81d3d1dd3eSPeeter Must 	KEY_KPJPCOMMA,	NONE,		NONE,		NONE,
82d3d1dd3eSPeeter Must 	KEY_HANGEUL,	KEY_HANJA,	KEY_KATAKANA,	KEY_HIRAGANA,
83d3d1dd3eSPeeter Must 	KEY_ZENKAKUHANKAKU,	NONE,	NONE,		NONE,
84d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
85d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
86d3d1dd3eSPeeter Must 	/* 0xa0 - 0xbf */
87d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
88d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
89d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
90d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
91d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
92d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
93d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
94d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
95d3d1dd3eSPeeter Must 	/* 0xc0 - 0xdf */
96d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
97d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
98d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
99d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
100d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
101d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
102d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
103d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
104d3d1dd3eSPeeter Must 	/* 0xe0 - 0xff */
105d3d1dd3eSPeeter Must 	KEY_LEFTCTRL,	KEY_LEFTSHIFT,	KEY_LEFTALT,	KEY_LEFTMETA,
106d3d1dd3eSPeeter Must 	KEY_RIGHTCTRL,	KEY_RIGHTSHIFT,	KEY_RIGHTALT,	KEY_RIGHTMETA,
107d3d1dd3eSPeeter Must 	KEY_PLAYPAUSE,	KEY_STOPCD,	KEY_PREVIOUSSONG,KEY_NEXTSONG,
108d3d1dd3eSPeeter Must 	KEY_EJECTCD,	KEY_VOLUMEUP,	KEY_VOLUMEDOWN,	KEY_MUTE,
109d3d1dd3eSPeeter Must 	KEY_WWW,	KEY_BACK,	KEY_FORWARD,	KEY_STOP,
110d3d1dd3eSPeeter Must 	KEY_FIND,	KEY_SCROLLUP,	KEY_SCROLLDOWN,	KEY_EDIT,
111d3d1dd3eSPeeter Must 	KEY_SLEEP,	KEY_COFFEE,	KEY_REFRESH,	KEY_CALC,
112d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
113d3d1dd3eSPeeter Must 
114d3d1dd3eSPeeter Must };
115d3d1dd3eSPeeter Must 
116d3d1dd3eSPeeter Must static uint16_t evdev_at_set1_scancodes[] = {
117d3d1dd3eSPeeter Must 	/* 0x00 - 0x1f */
118d3d1dd3eSPeeter Must 	NONE,		KEY_ESC,	KEY_1,		KEY_2,
119d3d1dd3eSPeeter Must 	KEY_3,		KEY_4,		KEY_5,		KEY_6,
120d3d1dd3eSPeeter Must 	KEY_7,		KEY_8,		KEY_9,		KEY_0,
121d3d1dd3eSPeeter Must 	KEY_MINUS,	KEY_EQUAL,	KEY_BACKSPACE,	KEY_TAB,
122d3d1dd3eSPeeter Must 	KEY_Q,		KEY_W,		KEY_E,		KEY_R,
123d3d1dd3eSPeeter Must 	KEY_T,		KEY_Y,		KEY_U,		KEY_I,
124d3d1dd3eSPeeter Must 	KEY_O,		KEY_P,		KEY_LEFTBRACE,	KEY_RIGHTBRACE,
125d3d1dd3eSPeeter Must 	KEY_ENTER,	KEY_LEFTCTRL,	KEY_A,		KEY_S,
126d3d1dd3eSPeeter Must 	/* 0x20 - 0x3f */
127d3d1dd3eSPeeter Must 	KEY_D,		KEY_F,		KEY_G,		KEY_H,
128d3d1dd3eSPeeter Must 	KEY_J,		KEY_K,		KEY_L,		KEY_SEMICOLON,
129d3d1dd3eSPeeter Must 	KEY_APOSTROPHE,	KEY_GRAVE,	KEY_LEFTSHIFT,	KEY_BACKSLASH,
130d3d1dd3eSPeeter Must 	KEY_Z,		KEY_X,		KEY_C,		KEY_V,
131d3d1dd3eSPeeter Must 	KEY_B,		KEY_N,		KEY_M,		KEY_COMMA,
132*a162a738SMichael Neumann 	KEY_DOT,	KEY_SLASH,	KEY_RIGHTSHIFT,	KEY_KPASTERISK,
133d3d1dd3eSPeeter Must 	KEY_LEFTALT,	KEY_SPACE,	KEY_CAPSLOCK,	KEY_F1,
134d3d1dd3eSPeeter Must 	KEY_F2,		KEY_F3,		KEY_F4,		KEY_F5,
135d3d1dd3eSPeeter Must 	/* 0x40 - 0x5f */
136d3d1dd3eSPeeter Must 	KEY_F6,		KEY_F7,		KEY_F8,		KEY_F9,
137d3d1dd3eSPeeter Must 	KEY_F10,	KEY_NUMLOCK,	KEY_SCROLLLOCK,	KEY_KP7,
138d3d1dd3eSPeeter Must 	KEY_KP8,	KEY_KP9,	KEY_KPMINUS,	KEY_KP4,
139d3d1dd3eSPeeter Must 	KEY_KP5,	KEY_KP6,	KEY_KPPLUS,	KEY_KP1,
140d3d1dd3eSPeeter Must 	KEY_KP2,	KEY_KP3,	KEY_KP0,	KEY_KPDOT,
141f4a114dbSAaron LI 	NONE,		NONE,		KEY_102ND,	KEY_F11,
142d3d1dd3eSPeeter Must 	KEY_F12,	NONE,		NONE,		NONE,
143*a162a738SMichael Neumann 	NONE,		KEY_F13,	NONE,		NONE,
144d3d1dd3eSPeeter Must 	/* 0x60 - 0x7f */
145d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
146d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
147d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
148d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
149*a162a738SMichael Neumann 	KEY_KATAKANAHIRAGANA,	KEY_HANJA,	KEY_HANGEUL,	KEY_RO,
150d3d1dd3eSPeeter Must 	NONE,		NONE,	KEY_ZENKAKUHANKAKU,	KEY_HIRAGANA,
151d3d1dd3eSPeeter Must 	KEY_KATAKANA,	KEY_HENKAN,	NONE,		KEY_MUHENKAN,
152d3d1dd3eSPeeter Must 	NONE,		KEY_YEN,	KEY_KPCOMMA,	NONE,
153d3d1dd3eSPeeter Must 	/* 0x00 - 0x1f. 0xE0 prefixed */
154d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
155d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
156d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
157d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
158d3d1dd3eSPeeter Must 	KEY_PREVIOUSSONG,	NONE,	NONE,		NONE,
159d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
160d3d1dd3eSPeeter Must 	NONE,		KEY_NEXTSONG,	NONE,		NONE,
161d3d1dd3eSPeeter Must 	KEY_KPENTER,	KEY_RIGHTCTRL,	NONE,		NONE,
162d3d1dd3eSPeeter Must 	/* 0x20 - 0x3f. 0xE0 prefixed */
163d3d1dd3eSPeeter Must 	KEY_MUTE,	KEY_CALC,	KEY_PLAYPAUSE,	NONE,
164d3d1dd3eSPeeter Must 	KEY_STOPCD,	NONE,		NONE,		NONE,
165d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
166d3d1dd3eSPeeter Must 	NONE,		NONE,		KEY_VOLUMEDOWN,	NONE,
167d3d1dd3eSPeeter Must 	KEY_VOLUMEUP,	NONE,		KEY_HOMEPAGE,	NONE,
168*a162a738SMichael Neumann 	NONE,		KEY_KPSLASH,	NONE,		KEY_SYSRQ,
169*a162a738SMichael Neumann 	KEY_RIGHTALT,	NONE,		NONE,		KEY_F13,
170*a162a738SMichael Neumann 	KEY_F14,	KEY_F15,	KEY_F16,	KEY_F17,
171d3d1dd3eSPeeter Must 	/* 0x40 - 0x5f. 0xE0 prefixed */
172*a162a738SMichael Neumann 	KEY_F18,	KEY_F19,	KEY_F20,	KEY_F21,
173*a162a738SMichael Neumann 	KEY_F22,	NONE,		KEY_PAUSE,	KEY_HOME,
174d3d1dd3eSPeeter Must 	KEY_UP,		KEY_PAGEUP,	NONE,		KEY_LEFT,
175d3d1dd3eSPeeter Must 	NONE,		KEY_RIGHT,	NONE,		KEY_END,
176d3d1dd3eSPeeter Must 	KEY_DOWN,	KEY_PAGEDOWN,	KEY_INSERT,	KEY_DELETE,
177*a162a738SMichael Neumann 	NONE,		NONE,		NONE,		KEY_F23,
178*a162a738SMichael Neumann 	KEY_F24,	NONE,		NONE,		KEY_LEFTMETA,
179d3d1dd3eSPeeter Must 	KEY_RIGHTMETA,	KEY_MENU,	KEY_POWER,	KEY_SLEEP,
180d3d1dd3eSPeeter Must 	/* 0x60 - 0x7f. 0xE0 prefixed */
181d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		KEY_WAKEUP,
182d3d1dd3eSPeeter Must 	NONE,		KEY_SEARCH,	KEY_BOOKMARKS,	KEY_REFRESH,
183d3d1dd3eSPeeter Must 	KEY_STOP,	KEY_FORWARD,	KEY_BACK,	KEY_COMPUTER,
184d3d1dd3eSPeeter Must 	KEY_MAIL,	KEY_MEDIA,	NONE,		NONE,
185d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
186d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
187d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
188d3d1dd3eSPeeter Must 	NONE,		NONE,		NONE,		NONE,
189d3d1dd3eSPeeter Must };
190d3d1dd3eSPeeter Must 
191d3d1dd3eSPeeter Must static uint16_t evdev_mouse_button_codes[] = {
192d3d1dd3eSPeeter Must 	BTN_LEFT,
193d3d1dd3eSPeeter Must 	BTN_MIDDLE,
194d3d1dd3eSPeeter Must 	BTN_RIGHT,
195d3d1dd3eSPeeter Must 	BTN_SIDE,
196d3d1dd3eSPeeter Must 	BTN_EXTRA,
197d3d1dd3eSPeeter Must 	BTN_FORWARD,
198d3d1dd3eSPeeter Must 	BTN_BACK,
199d3d1dd3eSPeeter Must 	BTN_TASK,
200d3d1dd3eSPeeter Must };
201d3d1dd3eSPeeter Must 
202d3d1dd3eSPeeter Must static uint16_t evdev_led_codes[] = {
203d3d1dd3eSPeeter Must 	LED_CAPSL,	/* CLKED */
204d3d1dd3eSPeeter Must 	LED_NUML,	/* NLKED */
205d3d1dd3eSPeeter Must 	LED_SCROLLL,	/* SLKED */
206d3d1dd3eSPeeter Must };
207d3d1dd3eSPeeter Must 
208*a162a738SMichael Neumann static uint16_t evdev_nfinger_codes[] = {
209*a162a738SMichael Neumann 	BTN_TOOL_FINGER,
210*a162a738SMichael Neumann 	BTN_TOOL_DOUBLETAP,
211*a162a738SMichael Neumann 	BTN_TOOL_TRIPLETAP,
212*a162a738SMichael Neumann 	BTN_TOOL_QUADTAP,
213*a162a738SMichael Neumann 	BTN_TOOL_QUINTTAP,
214*a162a738SMichael Neumann };
215*a162a738SMichael Neumann 
216d3d1dd3eSPeeter Must uint16_t
evdev_hid2key(int scancode)217d3d1dd3eSPeeter Must evdev_hid2key(int scancode)
218d3d1dd3eSPeeter Must {
219d3d1dd3eSPeeter Must 	return evdev_usb_scancodes[scancode];
220d3d1dd3eSPeeter Must }
221d3d1dd3eSPeeter Must 
222d3d1dd3eSPeeter Must void
evdev_support_all_known_keys(struct evdev_dev * evdev)223d3d1dd3eSPeeter Must evdev_support_all_known_keys(struct evdev_dev *evdev)
224d3d1dd3eSPeeter Must {
225d3d1dd3eSPeeter Must 	size_t i;
226d3d1dd3eSPeeter Must 
227d3d1dd3eSPeeter Must 	for (i = KEY_RESERVED; i < nitems(evdev_at_set1_scancodes); i++)
228d3d1dd3eSPeeter Must 		if (evdev_at_set1_scancodes[i] != NONE)
229d3d1dd3eSPeeter Must 			evdev_support_key(evdev, evdev_at_set1_scancodes[i]);
230d3d1dd3eSPeeter Must }
231d3d1dd3eSPeeter Must 
232d3d1dd3eSPeeter Must uint16_t
evdev_scancode2key(int * state,int scancode)233d3d1dd3eSPeeter Must evdev_scancode2key(int *state, int scancode)
234d3d1dd3eSPeeter Must {
235d3d1dd3eSPeeter Must 	uint16_t keycode;
236d3d1dd3eSPeeter Must 
237d3d1dd3eSPeeter Must 	/* translate the scan code into a keycode */
238d3d1dd3eSPeeter Must 	keycode = evdev_at_set1_scancodes[scancode & 0x7f];
239d3d1dd3eSPeeter Must 	switch (*state) {
240d3d1dd3eSPeeter Must 	case 0x00:	/* normal scancode */
241d3d1dd3eSPeeter Must 		switch(scancode) {
242d3d1dd3eSPeeter Must 		case 0xE0:
243d3d1dd3eSPeeter Must 		case 0xE1:
244d3d1dd3eSPeeter Must 			*state = scancode;
245d3d1dd3eSPeeter Must 			return (NONE);
246d3d1dd3eSPeeter Must 		}
247d3d1dd3eSPeeter Must 		break;
248d3d1dd3eSPeeter Must 	case 0xE0:		/* 0xE0 prefix */
249d3d1dd3eSPeeter Must 		*state = 0;
250d3d1dd3eSPeeter Must 		keycode = evdev_at_set1_scancodes[0x80 + (scancode & 0x7f)];
251d3d1dd3eSPeeter Must 		break;
252d3d1dd3eSPeeter Must 	case 0xE1:	/* 0xE1 prefix */
253d3d1dd3eSPeeter Must 		/*
254d3d1dd3eSPeeter Must 		 * The pause/break key on the 101 keyboard produces:
255d3d1dd3eSPeeter Must 		 * E1-1D-45 E1-9D-C5
256d3d1dd3eSPeeter Must 		 * Ctrl-pause/break produces:
257d3d1dd3eSPeeter Must 		 * E0-46 E0-C6 (See above.)
258d3d1dd3eSPeeter Must 		 */
259d3d1dd3eSPeeter Must 		*state = 0;
260d3d1dd3eSPeeter Must 		if ((scancode & 0x7f) == 0x1D)
261*a162a738SMichael Neumann 			*state = scancode;
262d3d1dd3eSPeeter Must 		return (NONE);
263d3d1dd3eSPeeter Must 		/* NOT REACHED */
264d3d1dd3eSPeeter Must 	case 0x1D:	/* pause / break */
265*a162a738SMichael Neumann 	case 0x9D:
266*a162a738SMichael Neumann 		if ((*state ^ scancode) & 0x80)
267*a162a738SMichael Neumann 			return (NONE);
268d3d1dd3eSPeeter Must 		*state = 0;
269*a162a738SMichael Neumann 		if ((scancode & 0x7f) != 0x45)
270d3d1dd3eSPeeter Must 			return (NONE);
271d3d1dd3eSPeeter Must 		keycode = KEY_PAUSE;
272d3d1dd3eSPeeter Must 		break;
273d3d1dd3eSPeeter Must 	}
274d3d1dd3eSPeeter Must 
275d3d1dd3eSPeeter Must 	return (keycode);
276d3d1dd3eSPeeter Must }
277d3d1dd3eSPeeter Must 
278d3d1dd3eSPeeter Must void
evdev_push_mouse_btn(struct evdev_dev * evdev,int buttons)279d3d1dd3eSPeeter Must evdev_push_mouse_btn(struct evdev_dev *evdev, int buttons)
280d3d1dd3eSPeeter Must {
281d3d1dd3eSPeeter Must 	size_t i;
282d3d1dd3eSPeeter Must 
283d3d1dd3eSPeeter Must 	for (i = 0; i < nitems(evdev_mouse_button_codes); i++)
284d3d1dd3eSPeeter Must 		evdev_push_key(evdev, evdev_mouse_button_codes[i],
285d3d1dd3eSPeeter Must 		    buttons & (1 << i));
286d3d1dd3eSPeeter Must }
287d3d1dd3eSPeeter Must 
288d3d1dd3eSPeeter Must void
evdev_push_leds(struct evdev_dev * evdev,int leds)289d3d1dd3eSPeeter Must evdev_push_leds(struct evdev_dev *evdev, int leds)
290d3d1dd3eSPeeter Must {
291d3d1dd3eSPeeter Must 	size_t i;
292d3d1dd3eSPeeter Must 
293d3d1dd3eSPeeter Must 	/* Some drivers initialize leds before evdev */
294d3d1dd3eSPeeter Must 	if (evdev == NULL)
295d3d1dd3eSPeeter Must 		return;
296d3d1dd3eSPeeter Must 
297d3d1dd3eSPeeter Must 	for (i = 0; i < nitems(evdev_led_codes); i++)
298d3d1dd3eSPeeter Must 		evdev_push_led(evdev, evdev_led_codes[i], leds & (1 << i));
299d3d1dd3eSPeeter Must }
300d3d1dd3eSPeeter Must 
301d3d1dd3eSPeeter Must void
evdev_push_repeats(struct evdev_dev * evdev,keyboard_t * kbd)302d3d1dd3eSPeeter Must evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd)
303d3d1dd3eSPeeter Must {
304d3d1dd3eSPeeter Must 	/* Some drivers initialize typematics before evdev */
305d3d1dd3eSPeeter Must 	if (evdev == NULL)
306d3d1dd3eSPeeter Must 		return;
307d3d1dd3eSPeeter Must 
308d3d1dd3eSPeeter Must 	evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
309d3d1dd3eSPeeter Must 	evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
310d3d1dd3eSPeeter Must }
311d3d1dd3eSPeeter Must 
312d3d1dd3eSPeeter Must void
evdev_support_nfingers(struct evdev_dev * evdev,int nfingers)313*a162a738SMichael Neumann evdev_support_nfingers(struct evdev_dev *evdev, int nfingers)
314*a162a738SMichael Neumann {
315*a162a738SMichael Neumann 	int i;
316*a162a738SMichael Neumann 
317*a162a738SMichael Neumann 	for (i = 0; i < MIN(nitems(evdev_nfinger_codes), nfingers); i++)
318*a162a738SMichael Neumann 		evdev_support_key(evdev, evdev_nfinger_codes[i]);
319*a162a738SMichael Neumann }
320*a162a738SMichael Neumann 
321*a162a738SMichael Neumann void
evdev_send_nfingers(struct evdev_dev * evdev,int nfingers)322*a162a738SMichael Neumann evdev_send_nfingers(struct evdev_dev *evdev, int nfingers)
323*a162a738SMichael Neumann {
324*a162a738SMichael Neumann 	int i;
325*a162a738SMichael Neumann 
326*a162a738SMichael Neumann 	EVDEV_LOCK_ASSERT(evdev);
327*a162a738SMichael Neumann 
328*a162a738SMichael Neumann 	if (nfingers > nitems(evdev_nfinger_codes))
329*a162a738SMichael Neumann 		nfingers = nitems(evdev_nfinger_codes);
330*a162a738SMichael Neumann 
331*a162a738SMichael Neumann 	for (i = 0; i < nitems(evdev_nfinger_codes); i++)
332*a162a738SMichael Neumann 		evdev_send_event(evdev, EV_KEY, evdev_nfinger_codes[i],
333*a162a738SMichael Neumann 			nfingers == i + 1);
334*a162a738SMichael Neumann }
335*a162a738SMichael Neumann 
336*a162a738SMichael Neumann void
evdev_push_nfingers(struct evdev_dev * evdev,int nfingers)337*a162a738SMichael Neumann evdev_push_nfingers(struct evdev_dev *evdev, int nfingers)
338*a162a738SMichael Neumann {
339*a162a738SMichael Neumann 	EVDEV_ENTER(evdev);
340*a162a738SMichael Neumann 	evdev_send_nfingers(evdev, nfingers);
341*a162a738SMichael Neumann 	EVDEV_EXIT(evdev);
342*a162a738SMichael Neumann }
343*a162a738SMichael Neumann 
344*a162a738SMichael Neumann void
evdev_ev_kbd_event(struct evdev_dev * evdev,uint16_t type,uint16_t code,int32_t value)345*a162a738SMichael Neumann evdev_ev_kbd_event(struct evdev_dev *evdev, uint16_t type,
346d3d1dd3eSPeeter Must     uint16_t code, int32_t value)
347d3d1dd3eSPeeter Must {
348*a162a738SMichael Neumann 	keyboard_t *kbd = (keyboard_t *)evdev_get_softc(evdev);
349d3d1dd3eSPeeter Must 	int delay[2], leds, oleds;
350d3d1dd3eSPeeter Must 	size_t i;
351d3d1dd3eSPeeter Must 
352d3d1dd3eSPeeter Must 	if (type == EV_LED) {
353d3d1dd3eSPeeter Must 		leds = oleds = KBD_LED_VAL(kbd);
354d3d1dd3eSPeeter Must 		for (i = 0; i < nitems(evdev_led_codes); i++) {
355d3d1dd3eSPeeter Must 			if (evdev_led_codes[i] == code) {
356d3d1dd3eSPeeter Must 				if (value)
357d3d1dd3eSPeeter Must 					leds |= 1 << i;
358d3d1dd3eSPeeter Must 				else
359d3d1dd3eSPeeter Must 					leds &= ~(1 << i);
360d3d1dd3eSPeeter Must 				if (leds != oleds)
361d3d1dd3eSPeeter Must 					kbd_ioctl(kbd, KDSETLED,
362d3d1dd3eSPeeter Must 					    (caddr_t)&leds);
363d3d1dd3eSPeeter Must 				break;
364d3d1dd3eSPeeter Must 			}
365d3d1dd3eSPeeter Must 		}
366d3d1dd3eSPeeter Must 	} else if (type == EV_REP && code == REP_DELAY) {
367d3d1dd3eSPeeter Must 		delay[0] = value;
368d3d1dd3eSPeeter Must 		delay[1] = kbd->kb_delay2;
369d3d1dd3eSPeeter Must 		kbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
370d3d1dd3eSPeeter Must 	} else if (type == EV_REP && code == REP_PERIOD) {
371d3d1dd3eSPeeter Must 		delay[0] = kbd->kb_delay1;
372d3d1dd3eSPeeter Must 		delay[1] = value;
373d3d1dd3eSPeeter Must 		kbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
374d3d1dd3eSPeeter Must 	}
375d3d1dd3eSPeeter Must }
376