ukbd.c revision 1.86 1 1.86 augustss /* $NetBSD: ukbd.c,v 1.86 2005/04/29 17:02:06 augustss Exp $ */
2 1.1 augustss
3 1.1 augustss /*
4 1.1 augustss * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.1 augustss * All rights reserved.
6 1.1 augustss *
7 1.11 augustss * This code is derived from software contributed to The NetBSD Foundation
8 1.59 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at
9 1.11 augustss * Carlstedt Research & Technology.
10 1.1 augustss *
11 1.1 augustss * Redistribution and use in source and binary forms, with or without
12 1.1 augustss * modification, are permitted provided that the following conditions
13 1.1 augustss * are met:
14 1.1 augustss * 1. Redistributions of source code must retain the above copyright
15 1.1 augustss * notice, this list of conditions and the following disclaimer.
16 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 augustss * notice, this list of conditions and the following disclaimer in the
18 1.1 augustss * documentation and/or other materials provided with the distribution.
19 1.1 augustss * 3. All advertising materials mentioning features or use of this software
20 1.1 augustss * must display the following acknowledgement:
21 1.1 augustss * This product includes software developed by the NetBSD
22 1.1 augustss * Foundation, Inc. and its contributors.
23 1.1 augustss * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.1 augustss * contributors may be used to endorse or promote products derived
25 1.1 augustss * from this software without specific prior written permission.
26 1.1 augustss *
27 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.1 augustss * POSSIBILITY OF SUCH DAMAGE.
38 1.1 augustss */
39 1.1 augustss
40 1.17 augustss /*
41 1.85 augustss * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
42 1.17 augustss */
43 1.72 lukem
44 1.72 lukem #include <sys/cdefs.h>
45 1.86 augustss __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.86 2005/04/29 17:02:06 augustss Exp $");
46 1.17 augustss
47 1.1 augustss #include <sys/param.h>
48 1.1 augustss #include <sys/systm.h>
49 1.57 thorpej #include <sys/callout.h>
50 1.1 augustss #include <sys/kernel.h>
51 1.1 augustss #include <sys/device.h>
52 1.1 augustss #include <sys/ioctl.h>
53 1.1 augustss #include <sys/tty.h>
54 1.1 augustss #include <sys/file.h>
55 1.1 augustss #include <sys/select.h>
56 1.1 augustss #include <sys/proc.h>
57 1.1 augustss #include <sys/vnode.h>
58 1.1 augustss #include <sys/poll.h>
59 1.1 augustss
60 1.1 augustss #include <dev/usb/usb.h>
61 1.2 augustss #include <dev/usb/usbhid.h>
62 1.37 augustss
63 1.1 augustss #include <dev/usb/usbdi.h>
64 1.1 augustss #include <dev/usb/usbdi_util.h>
65 1.1 augustss #include <dev/usb/usbdevs.h>
66 1.1 augustss #include <dev/usb/usb_quirks.h>
67 1.75 augustss #include <dev/usb/uhidev.h>
68 1.1 augustss #include <dev/usb/hid.h>
69 1.31 thorpej #include <dev/usb/ukbdvar.h>
70 1.1 augustss
71 1.2 augustss #include <dev/wscons/wsconsio.h>
72 1.2 augustss #include <dev/wscons/wskbdvar.h>
73 1.2 augustss #include <dev/wscons/wsksymdef.h>
74 1.2 augustss #include <dev/wscons/wsksymvar.h>
75 1.2 augustss
76 1.2 augustss #include "opt_wsdisplay_compat.h"
77 1.69 augustss #include "opt_ddb.h"
78 1.21 augustss
79 1.62 augustss #ifdef UKBD_DEBUG
80 1.39 augustss #define DPRINTF(x) if (ukbddebug) logprintf x
81 1.39 augustss #define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf x
82 1.1 augustss int ukbddebug = 0;
83 1.1 augustss #else
84 1.1 augustss #define DPRINTF(x)
85 1.1 augustss #define DPRINTFN(n,x)
86 1.1 augustss #endif
87 1.1 augustss
88 1.75 augustss #define MAXKEYCODE 6
89 1.75 augustss #define MAXMOD 8 /* max 32 */
90 1.2 augustss
91 1.1 augustss struct ukbd_data {
92 1.75 augustss u_int32_t modifiers;
93 1.75 augustss u_int8_t keycode[MAXKEYCODE];
94 1.1 augustss };
95 1.1 augustss
96 1.23 augustss #define PRESS 0x000
97 1.23 augustss #define RELEASE 0x100
98 1.23 augustss #define CODEMASK 0x0ff
99 1.1 augustss
100 1.23 augustss #if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD)
101 1.5 augustss #define NN 0 /* no translation */
102 1.82 augustss /*
103 1.23 augustss * Translate USB keycodes to US keyboard XT scancodes.
104 1.76 augustss * Scancodes >= 0x80 represent EXTENDED keycodes.
105 1.76 augustss *
106 1.76 augustss * See http://www.microsoft.com/HWDEV/TECH/input/Scancode.asp
107 1.19 augustss */
108 1.65 jdolecek Static const u_int8_t ukbd_trtab[256] = {
109 1.76 augustss NN, NN, NN, NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
110 1.76 augustss 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
111 1.76 augustss 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
112 1.76 augustss 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
113 1.76 augustss 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
114 1.76 augustss 0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
115 1.76 augustss 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
116 1.76 augustss 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
117 1.76 augustss 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
118 1.76 augustss 0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
119 1.76 augustss 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
120 1.76 augustss 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
121 1.76 augustss 0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, NN, 0x59, /* 60 - 67 */
122 1.76 augustss 0x5d, 0x5e, 0x5f, NN, NN, NN, NN, NN, /* 68 - 6f */
123 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */
124 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7f */
125 1.76 augustss NN, NN, NN, NN, NN, 0x7e, NN, 0x73, /* 80 - 87 */
126 1.76 augustss 0x70, 0x7d, 0x79, 0x7b, 0x5c, NN, NN, NN, /* 88 - 8f */
127 1.76 augustss NN, NN, 0x78, 0x77, 0x76, NN, NN, NN, /* 90 - 97 */
128 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9f */
129 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* a0 - a7 */
130 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* a8 - af */
131 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* b0 - b7 */
132 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* b8 - bf */
133 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* c0 - c7 */
134 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* c8 - cf */
135 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* d0 - d7 */
136 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* d8 - df */
137 1.76 augustss 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
138 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* e8 - ef */
139 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* f0 - f7 */
140 1.76 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* f8 - ff */
141 1.1 augustss };
142 1.23 augustss #endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */
143 1.1 augustss
144 1.1 augustss #define KEY_ERROR 0x01
145 1.1 augustss
146 1.75 augustss #define MAXKEYS (MAXMOD+2*MAXKEYCODE)
147 1.20 augustss
148 1.1 augustss struct ukbd_softc {
149 1.75 augustss struct uhidev sc_hdev;
150 1.1 augustss
151 1.1 augustss struct ukbd_data sc_ndata;
152 1.1 augustss struct ukbd_data sc_odata;
153 1.75 augustss struct hid_location sc_modloc[MAXMOD];
154 1.75 augustss u_int sc_nmod;
155 1.75 augustss struct {
156 1.75 augustss u_int32_t mask;
157 1.75 augustss u_int8_t key;
158 1.75 augustss } sc_mods[MAXMOD];
159 1.75 augustss
160 1.75 augustss struct hid_location sc_keycodeloc;
161 1.75 augustss u_int sc_nkeycode;
162 1.1 augustss
163 1.9 augustss char sc_enabled;
164 1.1 augustss
165 1.29 thorpej int sc_console_keyboard; /* we are the console keyboard */
166 1.29 thorpej
167 1.62 augustss char sc_debounce; /* for quirk handling */
168 1.70 augustss usb_callout_t sc_delay; /* for quirk handling */
169 1.62 augustss struct ukbd_data sc_data; /* for quirk handling */
170 1.62 augustss
171 1.75 augustss struct hid_location sc_numloc;
172 1.75 augustss struct hid_location sc_capsloc;
173 1.75 augustss struct hid_location sc_scroloc;
174 1.2 augustss int sc_leds;
175 1.16 augustss #if defined(__NetBSD__)
176 1.70 augustss usb_callout_t sc_rawrepeat_ch;
177 1.57 thorpej
178 1.2 augustss struct device *sc_wskbddev;
179 1.23 augustss #if defined(WSDISPLAY_COMPAT_RAWKBD)
180 1.20 augustss #define REP_DELAY1 400
181 1.20 augustss #define REP_DELAYN 100
182 1.2 augustss int sc_rawkbd;
183 1.20 augustss int sc_nrep;
184 1.20 augustss char sc_rep[MAXKEYS];
185 1.23 augustss #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
186 1.3 augustss
187 1.84 augustss int sc_spl;
188 1.3 augustss int sc_polling;
189 1.23 augustss int sc_npollchar;
190 1.23 augustss u_int16_t sc_pollchars[MAXKEYS];
191 1.23 augustss #endif /* defined(__NetBSD__) */
192 1.40 augustss
193 1.40 augustss u_char sc_dying;
194 1.1 augustss };
195 1.1 augustss
196 1.62 augustss #ifdef UKBD_DEBUG
197 1.62 augustss #define UKBDTRACESIZE 64
198 1.62 augustss struct ukbdtraceinfo {
199 1.62 augustss int unit;
200 1.62 augustss struct timeval tv;
201 1.62 augustss struct ukbd_data ud;
202 1.62 augustss };
203 1.62 augustss struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
204 1.62 augustss int ukbdtraceindex = 0;
205 1.62 augustss int ukbdtrace = 0;
206 1.62 augustss void ukbdtracedump(void);
207 1.62 augustss void
208 1.62 augustss ukbdtracedump(void)
209 1.62 augustss {
210 1.62 augustss int i;
211 1.62 augustss for (i = 0; i < UKBDTRACESIZE; i++) {
212 1.82 augustss struct ukbdtraceinfo *p =
213 1.62 augustss &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
214 1.62 augustss printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
215 1.62 augustss "key2=0x%02x key3=0x%02x\n",
216 1.62 augustss p->tv.tv_sec, p->tv.tv_usec,
217 1.62 augustss p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
218 1.62 augustss p->ud.keycode[2], p->ud.keycode[3]);
219 1.62 augustss }
220 1.62 augustss }
221 1.62 augustss #endif
222 1.62 augustss
223 1.1 augustss #define UKBDUNIT(dev) (minor(dev))
224 1.1 augustss #define UKBD_CHUNK 128 /* chunk size for read */
225 1.1 augustss #define UKBD_BSIZE 1020 /* buffer size */
226 1.1 augustss
227 1.58 augustss Static int ukbd_is_console;
228 1.31 thorpej
229 1.60 augustss Static void ukbd_cngetc(void *, u_int *, int *);
230 1.60 augustss Static void ukbd_cnpollc(void *, int);
231 1.3 augustss
232 1.16 augustss #if defined(__NetBSD__)
233 1.8 drochner const struct wskbd_consops ukbd_consops = {
234 1.8 drochner ukbd_cngetc,
235 1.8 drochner ukbd_cnpollc,
236 1.8 drochner };
237 1.16 augustss #endif
238 1.8 drochner
239 1.75 augustss Static const char *ukbd_parse_desc(struct ukbd_softc *sc);
240 1.75 augustss
241 1.75 augustss Static void ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
242 1.62 augustss Static void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
243 1.62 augustss Static void ukbd_delayed_decode(void *addr);
244 1.2 augustss
245 1.60 augustss Static int ukbd_enable(void *, int);
246 1.60 augustss Static void ukbd_set_leds(void *, int);
247 1.23 augustss
248 1.16 augustss #if defined(__NetBSD__)
249 1.80 augustss Static int ukbd_ioctl(void *, u_long, caddr_t, int, usb_proc_ptr );
250 1.48 mjacob #ifdef WSDISPLAY_COMPAT_RAWKBD
251 1.60 augustss Static void ukbd_rawrepeat(void *v);
252 1.48 mjacob #endif
253 1.1 augustss
254 1.8 drochner const struct wskbd_accessops ukbd_accessops = {
255 1.8 drochner ukbd_enable,
256 1.8 drochner ukbd_set_leds,
257 1.8 drochner ukbd_ioctl,
258 1.8 drochner };
259 1.8 drochner
260 1.23 augustss extern const struct wscons_keydesc ukbd_keydesctab[];
261 1.23 augustss
262 1.8 drochner const struct wskbd_mapdata ukbd_keymapdata = {
263 1.23 augustss ukbd_keydesctab,
264 1.86 augustss #if defined(UKBD_LAYOUT)
265 1.66 augustss UKBD_LAYOUT,
266 1.86 augustss #elif defined(PCKBD_LAYOUT)
267 1.86 augustss PCKBD_LAYOUT,
268 1.66 augustss #else
269 1.8 drochner KB_US,
270 1.66 augustss #endif
271 1.8 drochner };
272 1.16 augustss #endif
273 1.8 drochner
274 1.16 augustss USB_DECLARE_DRIVER(ukbd);
275 1.1 augustss
276 1.75 augustss int
277 1.75 augustss ukbd_match(struct device *parent, struct cfdata *match, void *aux)
278 1.1 augustss {
279 1.75 augustss struct uhidev_attach_arg *uha = aux;
280 1.75 augustss int size;
281 1.75 augustss void *desc;
282 1.82 augustss
283 1.75 augustss uhidev_get_report_desc(uha->parent, &desc, &size);
284 1.75 augustss if (!hid_is_collection(desc, size, uha->reportid,
285 1.75 augustss HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
286 1.1 augustss return (UMATCH_NONE);
287 1.75 augustss
288 1.75 augustss return (UMATCH_IFACECLASS);
289 1.1 augustss }
290 1.1 augustss
291 1.75 augustss void
292 1.75 augustss ukbd_attach(struct device *parent, struct device *self, void *aux)
293 1.1 augustss {
294 1.75 augustss struct ukbd_softc *sc = (struct ukbd_softc *)self;
295 1.75 augustss struct uhidev_attach_arg *uha = aux;
296 1.62 augustss u_int32_t qflags;
297 1.75 augustss const char *parseerr;
298 1.16 augustss #if defined(__NetBSD__)
299 1.2 augustss struct wskbddev_attach_args a;
300 1.16 augustss #else
301 1.16 augustss int i;
302 1.16 augustss #endif
303 1.82 augustss
304 1.75 augustss sc->sc_hdev.sc_intr = ukbd_intr;
305 1.75 augustss sc->sc_hdev.sc_parent = uha->parent;
306 1.75 augustss sc->sc_hdev.sc_report_id = uha->reportid;
307 1.75 augustss
308 1.75 augustss parseerr = ukbd_parse_desc(sc);
309 1.75 augustss if (parseerr != NULL) {
310 1.75 augustss printf("\n%s: attach failed, %s\n",
311 1.75 augustss sc->sc_hdev.sc_dev.dv_xname, parseerr);
312 1.16 augustss USB_ATTACH_ERROR_RETURN;
313 1.1 augustss }
314 1.82 augustss
315 1.75 augustss #ifdef DIAGNOSTIC
316 1.75 augustss printf(": %d modifier keys, %d key codes", sc->sc_nmod,
317 1.75 augustss sc->sc_nkeycode);
318 1.75 augustss #endif
319 1.75 augustss printf("\n");
320 1.1 augustss
321 1.1 augustss
322 1.75 augustss qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
323 1.62 augustss sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
324 1.20 augustss
325 1.29 thorpej /*
326 1.29 thorpej * Remember if we're the console keyboard.
327 1.29 thorpej *
328 1.31 thorpej * XXX This always picks the first keyboard on the
329 1.31 thorpej * first USB bus, but what else can we really do?
330 1.29 thorpej */
331 1.31 thorpej if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
332 1.29 thorpej /* Don't let any other keyboard have it. */
333 1.31 thorpej ukbd_is_console = 0;
334 1.29 thorpej }
335 1.29 thorpej
336 1.31 thorpej if (sc->sc_console_keyboard) {
337 1.32 augustss DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
338 1.31 thorpej wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
339 1.34 wrstuden ukbd_enable(sc, 1);
340 1.31 thorpej }
341 1.29 thorpej
342 1.29 thorpej a.console = sc->sc_console_keyboard;
343 1.8 drochner
344 1.8 drochner a.keymap = &ukbd_keymapdata;
345 1.8 drochner
346 1.8 drochner a.accessops = &ukbd_accessops;
347 1.2 augustss a.accesscookie = sc;
348 1.8 drochner
349 1.70 augustss usb_callout_init(sc->sc_rawrepeat_ch);
350 1.57 thorpej
351 1.70 augustss usb_callout_init(sc->sc_delay);
352 1.62 augustss
353 1.19 augustss /* Flash the leds; no real purpose, just shows we're alive. */
354 1.19 augustss ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
355 1.75 augustss usbd_delay_ms(uha->parent->sc_udev, 400);
356 1.19 augustss ukbd_set_leds(sc, 0);
357 1.19 augustss
358 1.64 augustss sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
359 1.55 augustss
360 1.16 augustss USB_ATTACH_SUCCESS_RETURN;
361 1.1 augustss }
362 1.1 augustss
363 1.8 drochner int
364 1.60 augustss ukbd_enable(void *v, int on)
365 1.8 drochner {
366 1.9 augustss struct ukbd_softc *sc = v;
367 1.9 augustss
368 1.40 augustss if (on && sc->sc_dying)
369 1.40 augustss return (EIO);
370 1.40 augustss
371 1.38 augustss /* Should only be called to change state */
372 1.38 augustss if (sc->sc_enabled == on) {
373 1.38 augustss #ifdef DIAGNOSTIC
374 1.82 augustss printf("ukbd_enable: %s: bad call on=%d\n",
375 1.75 augustss USBDEVNAME(sc->sc_hdev.sc_dev), on);
376 1.38 augustss #endif
377 1.38 augustss return (EBUSY);
378 1.38 augustss }
379 1.38 augustss
380 1.33 augustss DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
381 1.75 augustss sc->sc_enabled = on;
382 1.9 augustss if (on) {
383 1.75 augustss return (uhidev_open(&sc->sc_hdev));
384 1.9 augustss } else {
385 1.75 augustss uhidev_close(&sc->sc_hdev);
386 1.75 augustss return (0);
387 1.9 augustss }
388 1.37 augustss }
389 1.37 augustss
390 1.37 augustss int
391 1.60 augustss ukbd_activate(device_ptr_t self, enum devact act)
392 1.37 augustss {
393 1.40 augustss struct ukbd_softc *sc = (struct ukbd_softc *)self;
394 1.44 augustss int rv = 0;
395 1.40 augustss
396 1.40 augustss switch (act) {
397 1.40 augustss case DVACT_ACTIVATE:
398 1.40 augustss return (EOPNOTSUPP);
399 1.40 augustss
400 1.40 augustss case DVACT_DEACTIVATE:
401 1.47 augustss if (sc->sc_wskbddev != NULL)
402 1.44 augustss rv = config_deactivate(sc->sc_wskbddev);
403 1.40 augustss sc->sc_dying = 1;
404 1.40 augustss break;
405 1.40 augustss }
406 1.44 augustss return (rv);
407 1.37 augustss }
408 1.37 augustss
409 1.75 augustss int
410 1.75 augustss ukbd_detach(struct device *self, int flags)
411 1.37 augustss {
412 1.75 augustss struct ukbd_softc *sc = (struct ukbd_softc *)self;
413 1.37 augustss int rv = 0;
414 1.37 augustss
415 1.37 augustss DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
416 1.46 augustss
417 1.37 augustss if (sc->sc_console_keyboard) {
418 1.50 augustss #if 0
419 1.37 augustss /*
420 1.37 augustss * XXX Should probably disconnect our consops,
421 1.37 augustss * XXX and either notify some other keyboard that
422 1.37 augustss * XXX it can now be the console, or if there aren't
423 1.37 augustss * XXX any more USB keyboards, set ukbd_is_console
424 1.37 augustss * XXX back to 1 so that the next USB keyboard attached
425 1.37 augustss * XXX to the system will get it.
426 1.37 augustss */
427 1.37 augustss panic("ukbd_detach: console keyboard");
428 1.50 augustss #else
429 1.51 augustss /*
430 1.51 augustss * Disconnect our consops and set ukbd_is_console
431 1.51 augustss * back to 1 so that the next USB keyboard attached
432 1.51 augustss * to the system will get it.
433 1.51 augustss * XXX Should notify some other keyboard that it can be
434 1.51 augustss * XXX console, if there are any other keyboards.
435 1.51 augustss */
436 1.75 augustss printf("%s: was console keyboard\n",
437 1.75 augustss USBDEVNAME(sc->sc_hdev.sc_dev));
438 1.50 augustss wskbd_cndetach();
439 1.50 augustss ukbd_is_console = 1;
440 1.50 augustss #endif
441 1.37 augustss }
442 1.45 augustss /* No need to do reference counting of ukbd, wskbd has all the goo. */
443 1.47 augustss if (sc->sc_wskbddev != NULL)
444 1.37 augustss rv = config_detach(sc->sc_wskbddev, flags);
445 1.68 augustss
446 1.68 augustss /* The console keyboard does not get a disable call, so check pipe. */
447 1.75 augustss if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
448 1.75 augustss uhidev_close(&sc->sc_hdev);
449 1.55 augustss
450 1.37 augustss return (rv);
451 1.1 augustss }
452 1.1 augustss
453 1.1 augustss void
454 1.75 augustss ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
455 1.1 augustss {
456 1.75 augustss struct ukbd_softc *sc = (struct ukbd_softc *)addr;
457 1.1 augustss struct ukbd_data *ud = &sc->sc_ndata;
458 1.75 augustss int i;
459 1.76 augustss
460 1.76 augustss #ifdef UKBD_DEBUG
461 1.76 augustss if (ukbddebug > 5) {
462 1.76 augustss printf("ukbd_intr: data");
463 1.76 augustss for (i = 0; i < len; i++)
464 1.78 augustss printf(" 0x%02x", ((u_char *)ibuf)[i]);
465 1.76 augustss printf("\n");
466 1.76 augustss }
467 1.76 augustss #endif
468 1.76 augustss
469 1.75 augustss ud->modifiers = 0;
470 1.75 augustss for (i = 0; i < sc->sc_nmod; i++)
471 1.75 augustss if (hid_get_data(ibuf, &sc->sc_modloc[i]))
472 1.80 augustss ud->modifiers |= sc->sc_mods[i].mask;
473 1.75 augustss memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8,
474 1.75 augustss sc->sc_nkeycode);
475 1.1 augustss
476 1.69 augustss if (sc->sc_debounce && !sc->sc_polling) {
477 1.62 augustss /*
478 1.62 augustss * Some keyboards have a peculiar quirk. They sometimes
479 1.62 augustss * generate a key up followed by a key down for the same
480 1.62 augustss * key after about 10 ms.
481 1.62 augustss * We avoid this bug by holding off decoding for 20 ms.
482 1.62 augustss */
483 1.62 augustss sc->sc_data = *ud;
484 1.70 augustss usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc);
485 1.74 lukem #ifdef DDB
486 1.69 augustss } else if (sc->sc_console_keyboard && !sc->sc_polling) {
487 1.69 augustss /*
488 1.69 augustss * For the console keyboard we can't deliver CTL-ALT-ESC
489 1.69 augustss * from the interrupt routine. Doing so would start
490 1.69 augustss * polling from inside the interrupt routine and that
491 1.69 augustss * loses bigtime.
492 1.69 augustss */
493 1.69 augustss sc->sc_data = *ud;
494 1.70 augustss usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc);
495 1.69 augustss #endif
496 1.62 augustss } else {
497 1.62 augustss ukbd_decode(sc, ud);
498 1.62 augustss }
499 1.62 augustss }
500 1.62 augustss
501 1.62 augustss void
502 1.62 augustss ukbd_delayed_decode(void *addr)
503 1.62 augustss {
504 1.62 augustss struct ukbd_softc *sc = addr;
505 1.62 augustss
506 1.62 augustss ukbd_decode(sc, &sc->sc_data);
507 1.62 augustss }
508 1.62 augustss
509 1.62 augustss void
510 1.62 augustss ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
511 1.62 augustss {
512 1.62 augustss int mod, omod;
513 1.62 augustss u_int16_t ibuf[MAXKEYS]; /* chars events */
514 1.62 augustss int s;
515 1.62 augustss int nkeys, i, j;
516 1.62 augustss int key;
517 1.62 augustss #define ADDKEY(c) ibuf[nkeys++] = (c)
518 1.62 augustss
519 1.62 augustss #ifdef UKBD_DEBUG
520 1.82 augustss /*
521 1.62 augustss * Keep a trace of the last events. Using printf changes the
522 1.62 augustss * timing, so this can be useful sometimes.
523 1.62 augustss */
524 1.62 augustss if (ukbdtrace) {
525 1.62 augustss struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
526 1.75 augustss p->unit = sc->sc_hdev.sc_dev.dv_unit;
527 1.62 augustss microtime(&p->tv);
528 1.62 augustss p->ud = *ud;
529 1.62 augustss if (++ukbdtraceindex >= UKBDTRACESIZE)
530 1.62 augustss ukbdtraceindex = 0;
531 1.62 augustss }
532 1.62 augustss if (ukbddebug > 5) {
533 1.62 augustss struct timeval tv;
534 1.62 augustss microtime(&tv);
535 1.62 augustss DPRINTF((" at %lu.%06lu mod=0x%02x key0=0x%02x key1=0x%02x "
536 1.62 augustss "key2=0x%02x key3=0x%02x\n",
537 1.62 augustss tv.tv_sec, tv.tv_usec,
538 1.62 augustss ud->modifiers, ud->keycode[0], ud->keycode[1],
539 1.62 augustss ud->keycode[2], ud->keycode[3]));
540 1.62 augustss }
541 1.62 augustss #endif
542 1.1 augustss
543 1.53 augustss if (ud->keycode[0] == KEY_ERROR) {
544 1.53 augustss DPRINTF(("ukbd_intr: KEY_ERROR\n"));
545 1.1 augustss return; /* ignore */
546 1.53 augustss }
547 1.1 augustss nkeys = 0;
548 1.1 augustss mod = ud->modifiers;
549 1.1 augustss omod = sc->sc_odata.modifiers;
550 1.1 augustss if (mod != omod)
551 1.75 augustss for (i = 0; i < sc->sc_nmod; i++)
552 1.82 augustss if (( mod & sc->sc_mods[i].mask) !=
553 1.75 augustss (omod & sc->sc_mods[i].mask))
554 1.82 augustss ADDKEY(sc->sc_mods[i].key |
555 1.82 augustss (mod & sc->sc_mods[i].mask
556 1.1 augustss ? PRESS : RELEASE));
557 1.75 augustss if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
558 1.1 augustss /* Check for released keys. */
559 1.75 augustss for (i = 0; i < sc->sc_nkeycode; i++) {
560 1.1 augustss key = sc->sc_odata.keycode[i];
561 1.1 augustss if (key == 0)
562 1.1 augustss continue;
563 1.75 augustss for (j = 0; j < sc->sc_nkeycode; j++)
564 1.1 augustss if (key == ud->keycode[j])
565 1.1 augustss goto rfound;
566 1.62 augustss DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
567 1.23 augustss ADDKEY(key | RELEASE);
568 1.1 augustss rfound:
569 1.1 augustss ;
570 1.1 augustss }
571 1.82 augustss
572 1.1 augustss /* Check for pressed keys. */
573 1.75 augustss for (i = 0; i < sc->sc_nkeycode; i++) {
574 1.1 augustss key = ud->keycode[i];
575 1.1 augustss if (key == 0)
576 1.1 augustss continue;
577 1.75 augustss for (j = 0; j < sc->sc_nkeycode; j++)
578 1.1 augustss if (key == sc->sc_odata.keycode[j])
579 1.1 augustss goto pfound;
580 1.23 augustss DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
581 1.23 augustss ADDKEY(key | PRESS);
582 1.1 augustss pfound:
583 1.1 augustss ;
584 1.1 augustss }
585 1.1 augustss }
586 1.1 augustss sc->sc_odata = *ud;
587 1.1 augustss
588 1.20 augustss if (nkeys == 0)
589 1.20 augustss return;
590 1.20 augustss
591 1.3 augustss if (sc->sc_polling) {
592 1.23 augustss DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
593 1.23 augustss memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
594 1.23 augustss sc->sc_npollchar = nkeys;
595 1.3 augustss return;
596 1.3 augustss }
597 1.20 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
598 1.19 augustss if (sc->sc_rawkbd) {
599 1.79 augustss u_char cbuf[MAXKEYS * 2];
600 1.24 augustss int c;
601 1.20 augustss int npress;
602 1.20 augustss
603 1.23 augustss for (npress = i = j = 0; i < nkeys; i++) {
604 1.23 augustss key = ibuf[i];
605 1.23 augustss c = ukbd_trtab[key & CODEMASK];
606 1.23 augustss if (c == NN)
607 1.23 augustss continue;
608 1.19 augustss if (c & 0x80)
609 1.19 augustss cbuf[j++] = 0xe0;
610 1.19 augustss cbuf[j] = c & 0x7f;
611 1.23 augustss if (key & RELEASE)
612 1.19 augustss cbuf[j] |= 0x80;
613 1.20 augustss else {
614 1.23 augustss /* remember pressed keys for autorepeat */
615 1.20 augustss if (c & 0x80)
616 1.20 augustss sc->sc_rep[npress++] = 0xe0;
617 1.20 augustss sc->sc_rep[npress++] = c & 0x7f;
618 1.20 augustss }
619 1.82 augustss DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
620 1.27 augustss c & 0x80 ? "0xe0 " : "",
621 1.27 augustss cbuf[j]));
622 1.23 augustss j++;
623 1.19 augustss }
624 1.30 augustss s = spltty();
625 1.19 augustss wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
626 1.30 augustss splx(s);
627 1.70 augustss usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
628 1.20 augustss if (npress != 0) {
629 1.20 augustss sc->sc_nrep = npress;
630 1.70 augustss usb_callout(sc->sc_rawrepeat_ch,
631 1.57 thorpej hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc);
632 1.20 augustss }
633 1.19 augustss return;
634 1.19 augustss }
635 1.19 augustss #endif
636 1.19 augustss
637 1.30 augustss s = spltty();
638 1.2 augustss for (i = 0; i < nkeys; i++) {
639 1.23 augustss key = ibuf[i];
640 1.82 augustss wskbd_input(sc->sc_wskbddev,
641 1.23 augustss key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
642 1.23 augustss key&CODEMASK);
643 1.20 augustss }
644 1.30 augustss splx(s);
645 1.1 augustss }
646 1.1 augustss
647 1.2 augustss void
648 1.60 augustss ukbd_set_leds(void *v, int leds)
649 1.1 augustss {
650 1.2 augustss struct ukbd_softc *sc = v;
651 1.2 augustss u_int8_t res;
652 1.1 augustss
653 1.71 augustss DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
654 1.71 augustss sc, leds, sc->sc_leds));
655 1.40 augustss
656 1.40 augustss if (sc->sc_dying)
657 1.40 augustss return;
658 1.1 augustss
659 1.71 augustss if (sc->sc_leds == leds)
660 1.71 augustss return;
661 1.2 augustss sc->sc_leds = leds;
662 1.2 augustss res = 0;
663 1.75 augustss /* XXX not really right */
664 1.75 augustss if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
665 1.75 augustss res |= 1 << sc->sc_scroloc.pos;
666 1.75 augustss if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
667 1.75 augustss res |= 1 << sc->sc_numloc.pos;
668 1.75 augustss if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
669 1.75 augustss res |= 1 << sc->sc_capsloc.pos;
670 1.75 augustss uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
671 1.1 augustss }
672 1.1 augustss
673 1.20 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
674 1.20 augustss void
675 1.60 augustss ukbd_rawrepeat(void *v)
676 1.20 augustss {
677 1.20 augustss struct ukbd_softc *sc = v;
678 1.30 augustss int s;
679 1.20 augustss
680 1.30 augustss s = spltty();
681 1.20 augustss wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
682 1.30 augustss splx(s);
683 1.70 augustss usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
684 1.57 thorpej ukbd_rawrepeat, sc);
685 1.20 augustss }
686 1.20 augustss #endif
687 1.20 augustss
688 1.1 augustss int
689 1.80 augustss ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
690 1.1 augustss {
691 1.2 augustss struct ukbd_softc *sc = v;
692 1.1 augustss
693 1.2 augustss switch (cmd) {
694 1.2 augustss case WSKBDIO_GTYPE:
695 1.20 augustss *(int *)data = WSKBD_TYPE_USB;
696 1.17 augustss return (0);
697 1.2 augustss case WSKBDIO_SETLEDS:
698 1.2 augustss ukbd_set_leds(v, *(int *)data);
699 1.17 augustss return (0);
700 1.2 augustss case WSKBDIO_GETLEDS:
701 1.2 augustss *(int *)data = sc->sc_leds;
702 1.2 augustss return (0);
703 1.2 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
704 1.2 augustss case WSKBDIO_SETMODE:
705 1.19 augustss DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
706 1.2 augustss sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
707 1.70 augustss usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
708 1.2 augustss return (0);
709 1.2 augustss #endif
710 1.2 augustss }
711 1.81 atatat return (EPASSTHROUGH);
712 1.1 augustss }
713 1.7 augustss
714 1.71 augustss /*
715 1.71 augustss * This is a hack to work around some broken ports that don't call
716 1.71 augustss * cnpollc() before cngetc().
717 1.71 augustss */
718 1.71 augustss static int pollenter, warned;
719 1.71 augustss
720 1.7 augustss /* Console interface. */
721 1.3 augustss void
722 1.60 augustss ukbd_cngetc(void *v, u_int *type, int *data)
723 1.3 augustss {
724 1.3 augustss struct ukbd_softc *sc = v;
725 1.4 augustss int c;
726 1.71 augustss int broken;
727 1.71 augustss
728 1.71 augustss if (pollenter == 0) {
729 1.71 augustss if (!warned) {
730 1.71 augustss printf("\n"
731 1.71 augustss "This port is broken, it does not call cnpollc() before calling cngetc().\n"
732 1.71 augustss "This should be fixed, but it will work anyway (for now).\n");
733 1.71 augustss warned = 1;
734 1.71 augustss }
735 1.71 augustss broken = 1;
736 1.71 augustss ukbd_cnpollc(v, 1);
737 1.71 augustss } else
738 1.71 augustss broken = 0;
739 1.3 augustss
740 1.50 augustss DPRINTFN(0,("ukbd_cngetc: enter\n"));
741 1.3 augustss sc->sc_polling = 1;
742 1.23 augustss while(sc->sc_npollchar <= 0)
743 1.75 augustss usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
744 1.3 augustss sc->sc_polling = 0;
745 1.23 augustss c = sc->sc_pollchars[0];
746 1.23 augustss sc->sc_npollchar--;
747 1.82 augustss memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
748 1.23 augustss sc->sc_npollchar * sizeof(u_int16_t));
749 1.6 augustss *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
750 1.23 augustss *data = c & CODEMASK;
751 1.50 augustss DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
752 1.71 augustss if (broken)
753 1.71 augustss ukbd_cnpollc(v, 0);
754 1.3 augustss }
755 1.3 augustss
756 1.3 augustss void
757 1.60 augustss ukbd_cnpollc(void *v, int on)
758 1.3 augustss {
759 1.6 augustss struct ukbd_softc *sc = v;
760 1.52 augustss usbd_device_handle dev;
761 1.6 augustss
762 1.19 augustss DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
763 1.6 augustss
764 1.75 augustss usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev);
765 1.84 augustss if (on) {
766 1.84 augustss sc->sc_spl = splusb();
767 1.84 augustss pollenter++;
768 1.84 augustss } else {
769 1.84 augustss splx(sc->sc_spl);
770 1.84 augustss pollenter--;
771 1.84 augustss }
772 1.52 augustss usbd_set_polling(dev, on);
773 1.3 augustss }
774 1.18 augustss
775 1.18 augustss int
776 1.60 augustss ukbd_cnattach(void)
777 1.18 augustss {
778 1.18 augustss
779 1.31 thorpej /*
780 1.31 thorpej * XXX USB requires too many parts of the kernel to be running
781 1.31 thorpej * XXX in order to work, so we can't do much for the console
782 1.31 thorpej * XXX keyboard until autconfiguration has run its course.
783 1.31 thorpej */
784 1.31 thorpej ukbd_is_console = 1;
785 1.18 augustss return (0);
786 1.75 augustss }
787 1.75 augustss
788 1.75 augustss const char *
789 1.75 augustss ukbd_parse_desc(struct ukbd_softc *sc)
790 1.75 augustss {
791 1.75 augustss struct hid_data *d;
792 1.75 augustss struct hid_item h;
793 1.75 augustss int size;
794 1.75 augustss void *desc;
795 1.75 augustss int imod;
796 1.75 augustss
797 1.75 augustss uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
798 1.75 augustss imod = 0;
799 1.75 augustss sc->sc_nkeycode = 0;
800 1.75 augustss d = hid_start_parse(desc, size, hid_input);
801 1.75 augustss while (hid_get_item(d, &h)) {
802 1.75 augustss /*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n",
803 1.75 augustss h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
804 1.75 augustss if (h.kind != hid_input || (h.flags & HIO_CONST) ||
805 1.75 augustss HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
806 1.75 augustss h.report_ID != sc->sc_hdev.sc_report_id)
807 1.75 augustss continue;
808 1.79 augustss DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
809 1.79 augustss "cnt=%d\n", imod,
810 1.79 augustss h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
811 1.75 augustss if (h.flags & HIO_VARIABLE) {
812 1.80 augustss if (h.loc.size != 1)
813 1.80 augustss return ("bad modifier size");
814 1.75 augustss /* Single item */
815 1.75 augustss if (imod < MAXMOD) {
816 1.75 augustss sc->sc_modloc[imod] = h.loc;
817 1.75 augustss sc->sc_mods[imod].mask = 1 << imod;
818 1.75 augustss sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
819 1.75 augustss imod++;
820 1.75 augustss } else
821 1.75 augustss return ("too many modifier keys");
822 1.75 augustss } else {
823 1.75 augustss /* Array */
824 1.75 augustss if (h.loc.size != 8)
825 1.75 augustss return ("key code size != 8");
826 1.75 augustss if (h.loc.count > MAXKEYCODE)
827 1.75 augustss return ("too many key codes");
828 1.75 augustss if (h.loc.pos % 8 != 0)
829 1.75 augustss return ("key codes not on byte boundary");
830 1.75 augustss if (sc->sc_nkeycode != 0)
831 1.75 augustss return ("multiple key code arrays\n");
832 1.75 augustss sc->sc_keycodeloc = h.loc;
833 1.75 augustss sc->sc_nkeycode = h.loc.count;
834 1.75 augustss }
835 1.75 augustss }
836 1.75 augustss sc->sc_nmod = imod;
837 1.75 augustss hid_end_parse(d);
838 1.75 augustss
839 1.75 augustss hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
840 1.75 augustss sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
841 1.75 augustss hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
842 1.75 augustss sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
843 1.75 augustss hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
844 1.75 augustss sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);
845 1.75 augustss
846 1.75 augustss return (NULL);
847 1.18 augustss }
848