btkbd.c revision 1.3.4.2 1 1.3.4.2 rpaulo /* $NetBSD: btkbd.c,v 1.3.4.2 2006/09/09 02:49:44 rpaulo Exp $ */
2 1.3.4.2 rpaulo
3 1.3.4.2 rpaulo /*-
4 1.3.4.2 rpaulo * Copyright (c) 2006 Itronix Inc.
5 1.3.4.2 rpaulo * All rights reserved.
6 1.3.4.2 rpaulo *
7 1.3.4.2 rpaulo * Written by Iain Hibbert for Itronix Inc.
8 1.3.4.2 rpaulo *
9 1.3.4.2 rpaulo * Redistribution and use in source and binary forms, with or without
10 1.3.4.2 rpaulo * modification, are permitted provided that the following conditions
11 1.3.4.2 rpaulo * are met:
12 1.3.4.2 rpaulo * 1. Redistributions of source code must retain the above copyright
13 1.3.4.2 rpaulo * notice, this list of conditions and the following disclaimer.
14 1.3.4.2 rpaulo * 2. Redistributions in binary form must reproduce the above copyright
15 1.3.4.2 rpaulo * notice, this list of conditions and the following disclaimer in the
16 1.3.4.2 rpaulo * documentation and/or other materials provided with the distribution.
17 1.3.4.2 rpaulo * 3. The name of Itronix Inc. may not be used to endorse
18 1.3.4.2 rpaulo * or promote products derived from this software without specific
19 1.3.4.2 rpaulo * prior written permission.
20 1.3.4.2 rpaulo *
21 1.3.4.2 rpaulo * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 1.3.4.2 rpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.3.4.2 rpaulo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.3.4.2 rpaulo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 1.3.4.2 rpaulo * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 1.3.4.2 rpaulo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 1.3.4.2 rpaulo * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 1.3.4.2 rpaulo * ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.3.4.2 rpaulo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.3.4.2 rpaulo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.3.4.2 rpaulo * POSSIBILITY OF SUCH DAMAGE.
32 1.3.4.2 rpaulo */
33 1.3.4.2 rpaulo
34 1.3.4.2 rpaulo /*
35 1.3.4.2 rpaulo * based on dev/usb/ukbd.c
36 1.3.4.2 rpaulo */
37 1.3.4.2 rpaulo
38 1.3.4.2 rpaulo #include <sys/cdefs.h>
39 1.3.4.2 rpaulo __KERNEL_RCSID(0, "$NetBSD: btkbd.c,v 1.3.4.2 2006/09/09 02:49:44 rpaulo Exp $");
40 1.3.4.2 rpaulo
41 1.3.4.2 rpaulo #include <sys/param.h>
42 1.3.4.2 rpaulo #include <sys/callout.h>
43 1.3.4.2 rpaulo #include <sys/conf.h>
44 1.3.4.2 rpaulo #include <sys/device.h>
45 1.3.4.2 rpaulo #include <sys/kernel.h>
46 1.3.4.2 rpaulo #include <sys/proc.h>
47 1.3.4.2 rpaulo #include <sys/systm.h>
48 1.3.4.2 rpaulo
49 1.3.4.2 rpaulo #include <netbt/bluetooth.h>
50 1.3.4.2 rpaulo
51 1.3.4.2 rpaulo #include <dev/bluetooth/bthid.h>
52 1.3.4.2 rpaulo #include <dev/bluetooth/bthidev.h>
53 1.3.4.2 rpaulo
54 1.3.4.2 rpaulo #include <dev/usb/hid.h>
55 1.3.4.2 rpaulo #include <dev/usb/usb.h>
56 1.3.4.2 rpaulo #include <dev/usb/usbhid.h>
57 1.3.4.2 rpaulo
58 1.3.4.2 rpaulo #include <dev/wscons/wsconsio.h>
59 1.3.4.2 rpaulo #include <dev/wscons/wskbdvar.h>
60 1.3.4.2 rpaulo #include <dev/wscons/wsksymdef.h>
61 1.3.4.2 rpaulo #include <dev/wscons/wsksymvar.h>
62 1.3.4.2 rpaulo
63 1.3.4.2 rpaulo #include "opt_wsdisplay_compat.h"
64 1.3.4.2 rpaulo #include "opt_btkbd.h"
65 1.3.4.2 rpaulo
66 1.3.4.2 rpaulo #define MAXKEYCODE 6
67 1.3.4.2 rpaulo #define MAXMOD 8 /* max 32 */
68 1.3.4.2 rpaulo #define MAXKEYS (MAXMOD + (2 * MAXKEYCODE))
69 1.3.4.2 rpaulo
70 1.3.4.2 rpaulo struct btkbd_data {
71 1.3.4.2 rpaulo uint32_t modifiers;
72 1.3.4.2 rpaulo uint8_t keycode[MAXKEYCODE];
73 1.3.4.2 rpaulo };
74 1.3.4.2 rpaulo
75 1.3.4.2 rpaulo struct btkbd_mod {
76 1.3.4.2 rpaulo uint32_t mask;
77 1.3.4.2 rpaulo uint8_t key;
78 1.3.4.2 rpaulo };
79 1.3.4.2 rpaulo
80 1.3.4.2 rpaulo struct btkbd_softc {
81 1.3.4.2 rpaulo struct bthidev sc_hidev; /* device+ */
82 1.3.4.2 rpaulo struct device *sc_wskbd; /* child */
83 1.3.4.2 rpaulo int sc_enabled;
84 1.3.4.2 rpaulo
85 1.3.4.2 rpaulo int (*sc_output) /* output method */
86 1.3.4.2 rpaulo (struct bthidev *, uint8_t *, int);
87 1.3.4.2 rpaulo
88 1.3.4.2 rpaulo /* stored data */
89 1.3.4.2 rpaulo struct btkbd_data sc_odata;
90 1.3.4.2 rpaulo struct btkbd_data sc_ndata;
91 1.3.4.2 rpaulo
92 1.3.4.2 rpaulo /* input reports */
93 1.3.4.2 rpaulo int sc_nmod;
94 1.3.4.2 rpaulo struct hid_location sc_modloc[MAXMOD];
95 1.3.4.2 rpaulo struct btkbd_mod sc_mods[MAXMOD];
96 1.3.4.2 rpaulo
97 1.3.4.2 rpaulo int sc_nkeycode;
98 1.3.4.2 rpaulo struct hid_location sc_keycodeloc;
99 1.3.4.2 rpaulo
100 1.3.4.2 rpaulo /* output reports */
101 1.3.4.2 rpaulo struct hid_location sc_numloc;
102 1.3.4.2 rpaulo struct hid_location sc_capsloc;
103 1.3.4.2 rpaulo struct hid_location sc_scroloc;
104 1.3.4.2 rpaulo int sc_leds;
105 1.3.4.2 rpaulo
106 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
107 1.3.4.2 rpaulo int sc_rawkbd;
108 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
109 1.3.4.2 rpaulo struct callout sc_repeat;
110 1.3.4.2 rpaulo int sc_nrep;
111 1.3.4.2 rpaulo char sc_rep[MAXKEYS];
112 1.3.4.2 rpaulo #endif
113 1.3.4.2 rpaulo #endif
114 1.3.4.2 rpaulo };
115 1.3.4.2 rpaulo
116 1.3.4.2 rpaulo /* autoconf(9) methods */
117 1.3.4.2 rpaulo static int btkbd_match(struct device *, struct cfdata *, void *);
118 1.3.4.2 rpaulo static void btkbd_attach(struct device *, struct device *, void *);
119 1.3.4.2 rpaulo static int btkbd_detach(struct device *, int);
120 1.3.4.2 rpaulo
121 1.3.4.2 rpaulo CFATTACH_DECL(btkbd, sizeof(struct btkbd_softc),
122 1.3.4.2 rpaulo btkbd_match, btkbd_attach, btkbd_detach, NULL);
123 1.3.4.2 rpaulo
124 1.3.4.2 rpaulo /* wskbd(4) accessops */
125 1.3.4.2 rpaulo static int btkbd_enable(void *, int);
126 1.3.4.2 rpaulo static void btkbd_set_leds(void *, int);
127 1.3.4.2 rpaulo static int btkbd_ioctl(void *, unsigned long, caddr_t, int, struct lwp *);
128 1.3.4.2 rpaulo
129 1.3.4.2 rpaulo static const struct wskbd_accessops btkbd_accessops = {
130 1.3.4.2 rpaulo btkbd_enable,
131 1.3.4.2 rpaulo btkbd_set_leds,
132 1.3.4.2 rpaulo btkbd_ioctl
133 1.3.4.2 rpaulo };
134 1.3.4.2 rpaulo
135 1.3.4.2 rpaulo /* wskbd(4) keymap data */
136 1.3.4.2 rpaulo extern const struct wscons_keydesc ukbd_keydesctab[];
137 1.3.4.2 rpaulo
138 1.3.4.2 rpaulo const struct wskbd_mapdata btkbd_keymapdata = {
139 1.3.4.2 rpaulo ukbd_keydesctab,
140 1.3.4.2 rpaulo #if defined(BTKBD_LAYOUT)
141 1.3.4.2 rpaulo BTKBD_LAYOUT,
142 1.3.4.2 rpaulo #elif defined(PCKBD_LAYOUT)
143 1.3.4.2 rpaulo PCKBD_LAYOUT,
144 1.3.4.2 rpaulo #else
145 1.3.4.2 rpaulo KB_US,
146 1.3.4.2 rpaulo #endif
147 1.3.4.2 rpaulo };
148 1.3.4.2 rpaulo
149 1.3.4.2 rpaulo /* bthid methods */
150 1.3.4.2 rpaulo static void btkbd_input(struct bthidev *, uint8_t *, int);
151 1.3.4.2 rpaulo
152 1.3.4.2 rpaulo /* internal prototypes */
153 1.3.4.2 rpaulo static const char *btkbd_parse_desc(struct btkbd_softc *, int, const void *, int);
154 1.3.4.2 rpaulo
155 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
156 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
157 1.3.4.2 rpaulo static void btkbd_repeat(void *);
158 1.3.4.2 rpaulo #endif
159 1.3.4.2 rpaulo #endif
160 1.3.4.2 rpaulo
161 1.3.4.2 rpaulo /*****************************************************************************
162 1.3.4.2 rpaulo *
163 1.3.4.2 rpaulo * btkbd autoconf(9) routines
164 1.3.4.2 rpaulo */
165 1.3.4.2 rpaulo
166 1.3.4.2 rpaulo static int
167 1.3.4.2 rpaulo btkbd_match(struct device *self, struct cfdata *cfdata, void *aux)
168 1.3.4.2 rpaulo {
169 1.3.4.2 rpaulo struct bthidev_attach_args *ba = aux;
170 1.3.4.2 rpaulo
171 1.3.4.2 rpaulo if (hid_is_collection(ba->ba_desc, ba->ba_dlen, ba->ba_id,
172 1.3.4.2 rpaulo HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
173 1.3.4.2 rpaulo return 1;
174 1.3.4.2 rpaulo
175 1.3.4.2 rpaulo return 0;
176 1.3.4.2 rpaulo }
177 1.3.4.2 rpaulo
178 1.3.4.2 rpaulo static void
179 1.3.4.2 rpaulo btkbd_attach(struct device *parent, struct device *self, void *aux)
180 1.3.4.2 rpaulo {
181 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
182 1.3.4.2 rpaulo struct bthidev_attach_args *ba = aux;
183 1.3.4.2 rpaulo struct wskbddev_attach_args wska;
184 1.3.4.2 rpaulo const char *parserr;
185 1.3.4.2 rpaulo
186 1.3.4.2 rpaulo sc->sc_output = ba->ba_output;
187 1.3.4.2 rpaulo ba->ba_input = btkbd_input;
188 1.3.4.2 rpaulo
189 1.3.4.2 rpaulo parserr = btkbd_parse_desc(sc, ba->ba_id, ba->ba_desc, ba->ba_dlen);
190 1.3.4.2 rpaulo if (parserr != NULL) {
191 1.3.4.2 rpaulo aprint_error("%s\n", parserr);
192 1.3.4.2 rpaulo return;
193 1.3.4.2 rpaulo }
194 1.3.4.2 rpaulo
195 1.3.4.2 rpaulo aprint_normal("\n");
196 1.3.4.2 rpaulo
197 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
198 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
199 1.3.4.2 rpaulo callout_init(&sc->sc_repeat);
200 1.3.4.2 rpaulo callout_setfunc(&sc->sc_repeat, btkbd_repeat, sc);
201 1.3.4.2 rpaulo #endif
202 1.3.4.2 rpaulo #endif
203 1.3.4.2 rpaulo
204 1.3.4.2 rpaulo wska.console = 0;
205 1.3.4.2 rpaulo wska.keymap = &btkbd_keymapdata;
206 1.3.4.2 rpaulo wska.accessops = &btkbd_accessops;
207 1.3.4.2 rpaulo wska.accesscookie = sc;
208 1.3.4.2 rpaulo
209 1.3.4.2 rpaulo sc->sc_wskbd = config_found((struct device *)sc, &wska, wskbddevprint);
210 1.3.4.2 rpaulo }
211 1.3.4.2 rpaulo
212 1.3.4.2 rpaulo static int
213 1.3.4.2 rpaulo btkbd_detach(struct device *self, int flags)
214 1.3.4.2 rpaulo {
215 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
216 1.3.4.2 rpaulo int err = 0;
217 1.3.4.2 rpaulo
218 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
219 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
220 1.3.4.2 rpaulo callout_stop(&sc->sc_repeat);
221 1.3.4.2 rpaulo KASSERT(!callout_invoking(&sc->sc_repeat));
222 1.3.4.2 rpaulo #endif
223 1.3.4.2 rpaulo #endif
224 1.3.4.2 rpaulo
225 1.3.4.2 rpaulo if (sc->sc_wskbd != NULL) {
226 1.3.4.2 rpaulo err = config_detach(sc->sc_wskbd, flags);
227 1.3.4.2 rpaulo sc->sc_wskbd = NULL;
228 1.3.4.2 rpaulo }
229 1.3.4.2 rpaulo
230 1.3.4.2 rpaulo return err;
231 1.3.4.2 rpaulo }
232 1.3.4.2 rpaulo
233 1.3.4.2 rpaulo static const char *
234 1.3.4.2 rpaulo btkbd_parse_desc(struct btkbd_softc *sc, int id, const void *desc, int dlen)
235 1.3.4.2 rpaulo {
236 1.3.4.2 rpaulo struct hid_data *d;
237 1.3.4.2 rpaulo struct hid_item h;
238 1.3.4.2 rpaulo int imod;
239 1.3.4.2 rpaulo
240 1.3.4.2 rpaulo imod = 0;
241 1.3.4.2 rpaulo sc->sc_nkeycode = 0;
242 1.3.4.2 rpaulo d = hid_start_parse(desc, dlen, hid_input);
243 1.3.4.2 rpaulo while (hid_get_item(d, &h)) {
244 1.3.4.2 rpaulo if (h.kind != hid_input || (h.flags & HIO_CONST) ||
245 1.3.4.2 rpaulo HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
246 1.3.4.2 rpaulo h.report_ID != id)
247 1.3.4.2 rpaulo continue;
248 1.3.4.2 rpaulo
249 1.3.4.2 rpaulo if (h.flags & HIO_VARIABLE) {
250 1.3.4.2 rpaulo if (h.loc.size != 1)
251 1.3.4.2 rpaulo return ("bad modifier size");
252 1.3.4.2 rpaulo
253 1.3.4.2 rpaulo /* Single item */
254 1.3.4.2 rpaulo if (imod < MAXMOD) {
255 1.3.4.2 rpaulo sc->sc_modloc[imod] = h.loc;
256 1.3.4.2 rpaulo sc->sc_mods[imod].mask = 1 << imod;
257 1.3.4.2 rpaulo sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
258 1.3.4.2 rpaulo imod++;
259 1.3.4.2 rpaulo } else
260 1.3.4.2 rpaulo return ("too many modifier keys");
261 1.3.4.2 rpaulo } else {
262 1.3.4.2 rpaulo /* Array */
263 1.3.4.2 rpaulo if (h.loc.size != 8)
264 1.3.4.2 rpaulo return ("key code size != 8");
265 1.3.4.2 rpaulo
266 1.3.4.2 rpaulo if (h.loc.count > MAXKEYCODE)
267 1.3.4.2 rpaulo return ("too many key codes");
268 1.3.4.2 rpaulo
269 1.3.4.2 rpaulo if (h.loc.pos % 8 != 0)
270 1.3.4.2 rpaulo return ("key codes not on byte boundary");
271 1.3.4.2 rpaulo
272 1.3.4.2 rpaulo if (sc->sc_nkeycode != 0)
273 1.3.4.2 rpaulo return ("multiple key code arrays\n");
274 1.3.4.2 rpaulo
275 1.3.4.2 rpaulo sc->sc_keycodeloc = h.loc;
276 1.3.4.2 rpaulo sc->sc_nkeycode = h.loc.count;
277 1.3.4.2 rpaulo }
278 1.3.4.2 rpaulo }
279 1.3.4.2 rpaulo sc->sc_nmod = imod;
280 1.3.4.2 rpaulo hid_end_parse(d);
281 1.3.4.2 rpaulo
282 1.3.4.2 rpaulo hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
283 1.3.4.2 rpaulo id, hid_output, &sc->sc_numloc, NULL);
284 1.3.4.2 rpaulo
285 1.3.4.2 rpaulo hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
286 1.3.4.2 rpaulo id, hid_output, &sc->sc_capsloc, NULL);
287 1.3.4.2 rpaulo
288 1.3.4.2 rpaulo hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
289 1.3.4.2 rpaulo id, hid_output, &sc->sc_scroloc, NULL);
290 1.3.4.2 rpaulo
291 1.3.4.2 rpaulo return (NULL);
292 1.3.4.2 rpaulo }
293 1.3.4.2 rpaulo
294 1.3.4.2 rpaulo /*****************************************************************************
295 1.3.4.2 rpaulo *
296 1.3.4.2 rpaulo * wskbd(9) accessops
297 1.3.4.2 rpaulo */
298 1.3.4.2 rpaulo
299 1.3.4.2 rpaulo static int
300 1.3.4.2 rpaulo btkbd_enable(void *self, int on)
301 1.3.4.2 rpaulo {
302 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
303 1.3.4.2 rpaulo
304 1.3.4.2 rpaulo sc->sc_enabled = on;
305 1.3.4.2 rpaulo return 0;
306 1.3.4.2 rpaulo }
307 1.3.4.2 rpaulo
308 1.3.4.2 rpaulo static void
309 1.3.4.2 rpaulo btkbd_set_leds(void *self, int leds)
310 1.3.4.2 rpaulo {
311 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
312 1.3.4.2 rpaulo uint8_t report;
313 1.3.4.2 rpaulo
314 1.3.4.2 rpaulo if (sc->sc_leds == leds)
315 1.3.4.2 rpaulo return;
316 1.3.4.2 rpaulo
317 1.3.4.2 rpaulo sc->sc_leds = leds;
318 1.3.4.2 rpaulo
319 1.3.4.2 rpaulo /*
320 1.3.4.2 rpaulo * This is not totally correct, since we did not check the
321 1.3.4.2 rpaulo * report size from the descriptor but for keyboards it should
322 1.3.4.2 rpaulo * just be a single byte with the relevant bits set.
323 1.3.4.2 rpaulo */
324 1.3.4.2 rpaulo report = 0;
325 1.3.4.2 rpaulo if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
326 1.3.4.2 rpaulo report |= 1 << sc->sc_scroloc.pos;
327 1.3.4.2 rpaulo
328 1.3.4.2 rpaulo if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
329 1.3.4.2 rpaulo report |= 1 << sc->sc_numloc.pos;
330 1.3.4.2 rpaulo
331 1.3.4.2 rpaulo if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
332 1.3.4.2 rpaulo report |= 1 << sc->sc_capsloc.pos;
333 1.3.4.2 rpaulo
334 1.3.4.2 rpaulo if (sc->sc_output)
335 1.3.4.2 rpaulo (*sc->sc_output)(&sc->sc_hidev, &report, sizeof(report));
336 1.3.4.2 rpaulo }
337 1.3.4.2 rpaulo
338 1.3.4.2 rpaulo static int
339 1.3.4.2 rpaulo btkbd_ioctl(void *self, unsigned long cmd, caddr_t data, int flag, struct lwp *l)
340 1.3.4.2 rpaulo {
341 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
342 1.3.4.2 rpaulo
343 1.3.4.2 rpaulo switch (cmd) {
344 1.3.4.2 rpaulo case WSKBDIO_GTYPE:
345 1.3.4.2 rpaulo *(int *)data = WSKBD_TYPE_BLUETOOTH;
346 1.3.4.2 rpaulo break;
347 1.3.4.2 rpaulo
348 1.3.4.2 rpaulo case WSKBDIO_SETLEDS:
349 1.3.4.2 rpaulo btkbd_set_leds(sc, *(int *)data);
350 1.3.4.2 rpaulo break;
351 1.3.4.2 rpaulo
352 1.3.4.2 rpaulo case WSKBDIO_GETLEDS:
353 1.3.4.2 rpaulo *(int *)data = sc->sc_leds;
354 1.3.4.2 rpaulo break;
355 1.3.4.2 rpaulo
356 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
357 1.3.4.2 rpaulo case WSKBDIO_SETMODE:
358 1.3.4.2 rpaulo sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
359 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
360 1.3.4.2 rpaulo callout_stop(&sc->sc_repeat);
361 1.3.4.2 rpaulo #endif
362 1.3.4.2 rpaulo break;
363 1.3.4.2 rpaulo #endif
364 1.3.4.2 rpaulo
365 1.3.4.2 rpaulo default:
366 1.3.4.2 rpaulo return EPASSTHROUGH;
367 1.3.4.2 rpaulo }
368 1.3.4.2 rpaulo
369 1.3.4.2 rpaulo return 0;
370 1.3.4.2 rpaulo }
371 1.3.4.2 rpaulo
372 1.3.4.2 rpaulo /*****************************************************************************
373 1.3.4.2 rpaulo *
374 1.3.4.2 rpaulo * btkbd input routine, called from our parent
375 1.3.4.2 rpaulo */
376 1.3.4.2 rpaulo
377 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
378 1.3.4.2 rpaulo #define NN 0 /* no translation */
379 1.3.4.2 rpaulo /*
380 1.3.4.2 rpaulo * Translate USB keycodes to US keyboard XT scancodes.
381 1.3.4.2 rpaulo * Scancodes >= 0x80 represent EXTENDED keycodes.
382 1.3.4.2 rpaulo *
383 1.3.4.2 rpaulo * See http://www.microsoft.com/HWDEV/TECH/input/Scancode.asp
384 1.3.4.2 rpaulo */
385 1.3.4.2 rpaulo static const u_int8_t btkbd_trtab[256] = {
386 1.3.4.2 rpaulo NN, NN, NN, NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
387 1.3.4.2 rpaulo 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
388 1.3.4.2 rpaulo 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
389 1.3.4.2 rpaulo 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
390 1.3.4.2 rpaulo 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
391 1.3.4.2 rpaulo 0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
392 1.3.4.2 rpaulo 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
393 1.3.4.2 rpaulo 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
394 1.3.4.2 rpaulo 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
395 1.3.4.2 rpaulo 0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
396 1.3.4.2 rpaulo 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
397 1.3.4.2 rpaulo 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
398 1.3.4.2 rpaulo 0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, NN, 0x59, /* 60 - 67 */
399 1.3.4.2 rpaulo 0x5d, 0x5e, 0x5f, NN, NN, NN, NN, NN, /* 68 - 6f */
400 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */
401 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7f */
402 1.3.4.2 rpaulo NN, NN, NN, NN, NN, 0x7e, NN, 0x73, /* 80 - 87 */
403 1.3.4.2 rpaulo 0x70, 0x7d, 0x79, 0x7b, 0x5c, NN, NN, NN, /* 88 - 8f */
404 1.3.4.2 rpaulo NN, NN, 0x78, 0x77, 0x76, NN, NN, NN, /* 90 - 97 */
405 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9f */
406 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* a0 - a7 */
407 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* a8 - af */
408 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* b0 - b7 */
409 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* b8 - bf */
410 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* c0 - c7 */
411 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* c8 - cf */
412 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* d0 - d7 */
413 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* d8 - df */
414 1.3.4.2 rpaulo 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
415 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* e8 - ef */
416 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* f0 - f7 */
417 1.3.4.2 rpaulo NN, NN, NN, NN, NN, NN, NN, NN, /* f8 - ff */
418 1.3.4.2 rpaulo };
419 1.3.4.2 rpaulo #endif
420 1.3.4.2 rpaulo
421 1.3.4.2 rpaulo #define KEY_ERROR 0x01
422 1.3.4.2 rpaulo #define PRESS 0x000
423 1.3.4.2 rpaulo #define RELEASE 0x100
424 1.3.4.2 rpaulo #define CODEMASK 0x0ff
425 1.3.4.2 rpaulo #define ADDKEY(c) ibuf[nkeys++] = (c)
426 1.3.4.2 rpaulo #define REP_DELAY1 400
427 1.3.4.2 rpaulo #define REP_DELAYN 100
428 1.3.4.2 rpaulo
429 1.3.4.2 rpaulo static void
430 1.3.4.2 rpaulo btkbd_input(struct bthidev *self, uint8_t *data, int len)
431 1.3.4.2 rpaulo {
432 1.3.4.2 rpaulo struct btkbd_softc *sc = (struct btkbd_softc *)self;
433 1.3.4.2 rpaulo struct btkbd_data *ud = &sc->sc_ndata;
434 1.3.4.2 rpaulo uint16_t ibuf[MAXKEYS];
435 1.3.4.2 rpaulo uint32_t mod, omod;
436 1.3.4.2 rpaulo int nkeys, i, j;
437 1.3.4.2 rpaulo int key;
438 1.3.4.2 rpaulo int s;
439 1.3.4.2 rpaulo
440 1.3.4.2 rpaulo if (sc->sc_wskbd == NULL || sc->sc_enabled == 0)
441 1.3.4.2 rpaulo return;
442 1.3.4.2 rpaulo
443 1.3.4.2 rpaulo /* extract key modifiers */
444 1.3.4.2 rpaulo ud->modifiers = 0;
445 1.3.4.2 rpaulo for (i = 0 ; i < sc->sc_nmod ; i++)
446 1.3.4.2 rpaulo if (hid_get_data(data, &sc->sc_modloc[i]))
447 1.3.4.2 rpaulo ud->modifiers |= sc->sc_mods[i].mask;
448 1.3.4.2 rpaulo
449 1.3.4.2 rpaulo /* extract keycodes */
450 1.3.4.2 rpaulo memcpy(ud->keycode, data + (sc->sc_keycodeloc.pos / 8),
451 1.3.4.2 rpaulo sc->sc_nkeycode);
452 1.3.4.2 rpaulo
453 1.3.4.2 rpaulo if (ud->keycode[0] == KEY_ERROR)
454 1.3.4.2 rpaulo return; /* ignore */
455 1.3.4.2 rpaulo
456 1.3.4.2 rpaulo nkeys = 0;
457 1.3.4.2 rpaulo mod = ud->modifiers;
458 1.3.4.2 rpaulo omod = sc->sc_odata.modifiers;
459 1.3.4.2 rpaulo if (mod != omod)
460 1.3.4.2 rpaulo for (i = 0 ; i < sc->sc_nmod ; i++)
461 1.3.4.2 rpaulo if ((mod & sc->sc_mods[i].mask) !=
462 1.3.4.2 rpaulo (omod & sc->sc_mods[i].mask))
463 1.3.4.2 rpaulo ADDKEY(sc->sc_mods[i].key |
464 1.3.4.2 rpaulo (mod & sc->sc_mods[i].mask
465 1.3.4.2 rpaulo ? PRESS : RELEASE));
466 1.3.4.2 rpaulo
467 1.3.4.2 rpaulo if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
468 1.3.4.2 rpaulo /* Check for released keys. */
469 1.3.4.2 rpaulo for (i = 0 ; i < sc->sc_nkeycode ; i++) {
470 1.3.4.2 rpaulo key = sc->sc_odata.keycode[i];
471 1.3.4.2 rpaulo if (key == 0)
472 1.3.4.2 rpaulo continue;
473 1.3.4.2 rpaulo
474 1.3.4.2 rpaulo for (j = 0 ; j < sc->sc_nkeycode ; j++)
475 1.3.4.2 rpaulo if (key == ud->keycode[j])
476 1.3.4.2 rpaulo goto rfound;
477 1.3.4.2 rpaulo
478 1.3.4.2 rpaulo ADDKEY(key | RELEASE);
479 1.3.4.2 rpaulo
480 1.3.4.2 rpaulo rfound:
481 1.3.4.2 rpaulo ;
482 1.3.4.2 rpaulo }
483 1.3.4.2 rpaulo
484 1.3.4.2 rpaulo /* Check for pressed keys. */
485 1.3.4.2 rpaulo for (i = 0 ; i < sc->sc_nkeycode ; i++) {
486 1.3.4.2 rpaulo key = ud->keycode[i];
487 1.3.4.2 rpaulo if (key == 0)
488 1.3.4.2 rpaulo continue;
489 1.3.4.2 rpaulo
490 1.3.4.2 rpaulo for (j = 0; j < sc->sc_nkeycode; j++)
491 1.3.4.2 rpaulo if (key == sc->sc_odata.keycode[j])
492 1.3.4.2 rpaulo goto pfound;
493 1.3.4.2 rpaulo
494 1.3.4.2 rpaulo ADDKEY(key | PRESS);
495 1.3.4.2 rpaulo pfound:
496 1.3.4.2 rpaulo ;
497 1.3.4.2 rpaulo }
498 1.3.4.2 rpaulo }
499 1.3.4.2 rpaulo sc->sc_odata = *ud;
500 1.3.4.2 rpaulo
501 1.3.4.2 rpaulo if (nkeys == 0)
502 1.3.4.2 rpaulo return;
503 1.3.4.2 rpaulo
504 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
505 1.3.4.2 rpaulo if (sc->sc_rawkbd) {
506 1.3.4.2 rpaulo u_char cbuf[MAXKEYS * 2];
507 1.3.4.2 rpaulo int c;
508 1.3.4.2 rpaulo int npress;
509 1.3.4.2 rpaulo
510 1.3.4.2 rpaulo for (npress = i = j = 0 ; i < nkeys ; i++) {
511 1.3.4.2 rpaulo key = ibuf[i];
512 1.3.4.2 rpaulo c = btkbd_trtab[key & CODEMASK];
513 1.3.4.2 rpaulo if (c == NN)
514 1.3.4.2 rpaulo continue;
515 1.3.4.2 rpaulo
516 1.3.4.2 rpaulo if (c & 0x80)
517 1.3.4.2 rpaulo cbuf[j++] = 0xe0;
518 1.3.4.2 rpaulo
519 1.3.4.2 rpaulo cbuf[j] = c & 0x7f;
520 1.3.4.2 rpaulo if (key & RELEASE)
521 1.3.4.2 rpaulo cbuf[j] |= 0x80;
522 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
523 1.3.4.2 rpaulo else {
524 1.3.4.2 rpaulo /* remember pressed keys for autorepeat */
525 1.3.4.2 rpaulo if (c & 0x80)
526 1.3.4.2 rpaulo sc->sc_rep[npress++] = 0xe0;
527 1.3.4.2 rpaulo
528 1.3.4.2 rpaulo sc->sc_rep[npress++] = c & 0x7f;
529 1.3.4.2 rpaulo }
530 1.3.4.2 rpaulo #endif
531 1.3.4.2 rpaulo
532 1.3.4.2 rpaulo j++;
533 1.3.4.2 rpaulo }
534 1.3.4.2 rpaulo
535 1.3.4.2 rpaulo s = spltty();
536 1.3.4.2 rpaulo wskbd_rawinput(sc->sc_wskbd, cbuf, j);
537 1.3.4.2 rpaulo splx(s);
538 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
539 1.3.4.2 rpaulo callout_stop(&sc->sc_repeat);
540 1.3.4.2 rpaulo if (npress != 0) {
541 1.3.4.2 rpaulo sc->sc_nrep = npress;
542 1.3.4.2 rpaulo callout_schedule(&sc->sc_repeat, hz * REP_DELAY1 / 1000);
543 1.3.4.2 rpaulo }
544 1.3.4.2 rpaulo #endif
545 1.3.4.2 rpaulo return;
546 1.3.4.2 rpaulo }
547 1.3.4.2 rpaulo #endif
548 1.3.4.2 rpaulo
549 1.3.4.2 rpaulo s = spltty();
550 1.3.4.2 rpaulo for (i = 0 ; i < nkeys ; i++) {
551 1.3.4.2 rpaulo key = ibuf[i];
552 1.3.4.2 rpaulo wskbd_input(sc->sc_wskbd,
553 1.3.4.2 rpaulo key & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
554 1.3.4.2 rpaulo key & CODEMASK);
555 1.3.4.2 rpaulo }
556 1.3.4.2 rpaulo splx(s);
557 1.3.4.2 rpaulo }
558 1.3.4.2 rpaulo
559 1.3.4.2 rpaulo #ifdef WSDISPLAY_COMPAT_RAWKBD
560 1.3.4.2 rpaulo #ifdef BTKBD_REPEAT
561 1.3.4.2 rpaulo static void
562 1.3.4.2 rpaulo btkbd_repeat(void *arg)
563 1.3.4.2 rpaulo {
564 1.3.4.2 rpaulo struct btkbd_softc *sc = arg;
565 1.3.4.2 rpaulo int s;
566 1.3.4.2 rpaulo
567 1.3.4.2 rpaulo s = spltty();
568 1.3.4.2 rpaulo wskbd_rawinput(sc->sc_wskbd, sc->sc_rep, sc->sc_nrep);
569 1.3.4.2 rpaulo splx(s);
570 1.3.4.2 rpaulo callout_schedule(&sc->sc_repeat, hz * REP_DELAYN / 1000);
571 1.3.4.2 rpaulo }
572 1.3.4.2 rpaulo #endif
573 1.3.4.2 rpaulo #endif
574