ukbd.c revision 1.74 1 1.74 lukem /* $NetBSD: ukbd.c,v 1.74 2001/11/28 05:45:28 lukem 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.63 augustss * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf
42 1.17 augustss */
43 1.72 lukem
44 1.72 lukem #include <sys/cdefs.h>
45 1.74 lukem __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.74 2001/11/28 05:45:28 lukem 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.1 augustss #include <dev/usb/hid.h>
68 1.31 thorpej #include <dev/usb/ukbdvar.h>
69 1.1 augustss
70 1.2 augustss #include <dev/wscons/wsconsio.h>
71 1.2 augustss #include <dev/wscons/wskbdvar.h>
72 1.2 augustss #include <dev/wscons/wsksymdef.h>
73 1.2 augustss #include <dev/wscons/wsksymvar.h>
74 1.2 augustss
75 1.2 augustss #include "opt_wsdisplay_compat.h"
76 1.69 augustss #include "opt_ddb.h"
77 1.21 augustss
78 1.62 augustss #ifdef UKBD_DEBUG
79 1.39 augustss #define DPRINTF(x) if (ukbddebug) logprintf x
80 1.39 augustss #define DPRINTFN(n,x) if (ukbddebug>(n)) logprintf x
81 1.1 augustss int ukbddebug = 0;
82 1.1 augustss #else
83 1.1 augustss #define DPRINTF(x)
84 1.1 augustss #define DPRINTFN(n,x)
85 1.1 augustss #endif
86 1.1 augustss
87 1.1 augustss #define NKEYCODE 6
88 1.1 augustss
89 1.2 augustss #define NUM_LOCK 0x01
90 1.2 augustss #define CAPS_LOCK 0x02
91 1.2 augustss #define SCROLL_LOCK 0x04
92 1.2 augustss
93 1.1 augustss struct ukbd_data {
94 1.1 augustss u_int8_t modifiers;
95 1.1 augustss #define MOD_CONTROL_L 0x01
96 1.1 augustss #define MOD_CONTROL_R 0x10
97 1.1 augustss #define MOD_SHIFT_L 0x02
98 1.1 augustss #define MOD_SHIFT_R 0x20
99 1.1 augustss #define MOD_ALT_L 0x04
100 1.1 augustss #define MOD_ALT_R 0x40
101 1.1 augustss #define MOD_WIN_L 0x08
102 1.1 augustss #define MOD_WIN_R 0x80
103 1.1 augustss u_int8_t reserved;
104 1.1 augustss u_int8_t keycode[NKEYCODE];
105 1.1 augustss };
106 1.1 augustss
107 1.23 augustss #define PRESS 0x000
108 1.23 augustss #define RELEASE 0x100
109 1.23 augustss #define CODEMASK 0x0ff
110 1.1 augustss
111 1.23 augustss /* Translate USB bitmap to USB keycode. */
112 1.27 augustss #define NMOD 8
113 1.65 jdolecek Static const struct {
114 1.1 augustss int mask, key;
115 1.1 augustss } ukbd_mods[NMOD] = {
116 1.23 augustss { MOD_CONTROL_L, 224 },
117 1.23 augustss { MOD_CONTROL_R, 228 },
118 1.23 augustss { MOD_SHIFT_L, 225 },
119 1.23 augustss { MOD_SHIFT_R, 229 },
120 1.23 augustss { MOD_ALT_L, 226 },
121 1.23 augustss { MOD_ALT_R, 230 },
122 1.27 augustss { MOD_WIN_L, 227 },
123 1.27 augustss { MOD_WIN_R, 231 },
124 1.1 augustss };
125 1.1 augustss
126 1.23 augustss #if defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD)
127 1.5 augustss #define NN 0 /* no translation */
128 1.19 augustss /*
129 1.23 augustss * Translate USB keycodes to US keyboard XT scancodes.
130 1.19 augustss * Scancodes >= 128 represent EXTENDED keycodes.
131 1.19 augustss */
132 1.65 jdolecek Static const u_int8_t ukbd_trtab[256] = {
133 1.23 augustss NN, NN, NN, NN, 30, 48, 46, 32, /* 00 - 07 */
134 1.5 augustss 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */
135 1.5 augustss 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */
136 1.5 augustss 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */
137 1.5 augustss 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */
138 1.5 augustss 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */
139 1.61 augustss 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */
140 1.5 augustss 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */
141 1.5 augustss 65, 66, 67, 68, 87, 88, 170, 70, /* 40 - 47 */
142 1.5 augustss 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */
143 1.5 augustss 203, 208, 200, 69, 181, 55, 74, 78, /* 50 - 57 */
144 1.5 augustss 156, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */
145 1.61 augustss 72, 73, 82, 83, 86, 221, NN, NN, /* 60 - 67 */
146 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */
147 1.27 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */
148 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */
149 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 80 - 87 */
150 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 88 - 8F */
151 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */
152 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */
153 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */
154 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */
155 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */
156 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */
157 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */
158 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */
159 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */
160 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */
161 1.26 augustss 29, 42, 56, 219, 157, 54, 184,220, /* E0 - E7 */
162 1.26 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */
163 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */
164 1.5 augustss NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */
165 1.1 augustss };
166 1.23 augustss #endif /* defined(__NetBSD__) && defined(WSDISPLAY_COMPAT_RAWKBD) */
167 1.1 augustss
168 1.1 augustss #define KEY_ERROR 0x01
169 1.1 augustss
170 1.20 augustss #define MAXKEYS (NMOD+2*NKEYCODE)
171 1.20 augustss
172 1.1 augustss struct ukbd_softc {
173 1.43 augustss USBBASEDEVICE sc_dev; /* base device */
174 1.55 augustss usbd_device_handle sc_udev;
175 1.1 augustss usbd_interface_handle sc_iface; /* interface */
176 1.1 augustss usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
177 1.1 augustss int sc_ep_addr;
178 1.1 augustss
179 1.1 augustss struct ukbd_data sc_ndata;
180 1.1 augustss struct ukbd_data sc_odata;
181 1.1 augustss
182 1.9 augustss char sc_enabled;
183 1.1 augustss
184 1.29 thorpej int sc_console_keyboard; /* we are the console keyboard */
185 1.29 thorpej
186 1.62 augustss char sc_debounce; /* for quirk handling */
187 1.70 augustss usb_callout_t sc_delay; /* for quirk handling */
188 1.62 augustss struct ukbd_data sc_data; /* for quirk handling */
189 1.62 augustss
190 1.2 augustss int sc_leds;
191 1.16 augustss #if defined(__NetBSD__)
192 1.70 augustss usb_callout_t sc_rawrepeat_ch;
193 1.57 thorpej
194 1.2 augustss struct device *sc_wskbddev;
195 1.23 augustss #if defined(WSDISPLAY_COMPAT_RAWKBD)
196 1.20 augustss #define REP_DELAY1 400
197 1.20 augustss #define REP_DELAYN 100
198 1.2 augustss int sc_rawkbd;
199 1.20 augustss int sc_nrep;
200 1.20 augustss char sc_rep[MAXKEYS];
201 1.23 augustss #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
202 1.3 augustss
203 1.3 augustss int sc_polling;
204 1.23 augustss int sc_npollchar;
205 1.23 augustss u_int16_t sc_pollchars[MAXKEYS];
206 1.23 augustss #endif /* defined(__NetBSD__) */
207 1.40 augustss
208 1.40 augustss u_char sc_dying;
209 1.1 augustss };
210 1.1 augustss
211 1.62 augustss #ifdef UKBD_DEBUG
212 1.62 augustss #define UKBDTRACESIZE 64
213 1.62 augustss struct ukbdtraceinfo {
214 1.62 augustss int unit;
215 1.62 augustss struct timeval tv;
216 1.62 augustss struct ukbd_data ud;
217 1.62 augustss };
218 1.62 augustss struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
219 1.62 augustss int ukbdtraceindex = 0;
220 1.62 augustss int ukbdtrace = 0;
221 1.62 augustss void ukbdtracedump(void);
222 1.62 augustss void
223 1.62 augustss ukbdtracedump(void)
224 1.62 augustss {
225 1.62 augustss int i;
226 1.62 augustss for (i = 0; i < UKBDTRACESIZE; i++) {
227 1.62 augustss struct ukbdtraceinfo *p =
228 1.62 augustss &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
229 1.62 augustss printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
230 1.62 augustss "key2=0x%02x key3=0x%02x\n",
231 1.62 augustss p->tv.tv_sec, p->tv.tv_usec,
232 1.62 augustss p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
233 1.62 augustss p->ud.keycode[2], p->ud.keycode[3]);
234 1.62 augustss }
235 1.62 augustss }
236 1.62 augustss #endif
237 1.62 augustss
238 1.1 augustss #define UKBDUNIT(dev) (minor(dev))
239 1.1 augustss #define UKBD_CHUNK 128 /* chunk size for read */
240 1.1 augustss #define UKBD_BSIZE 1020 /* buffer size */
241 1.1 augustss
242 1.58 augustss Static int ukbd_is_console;
243 1.31 thorpej
244 1.60 augustss Static void ukbd_cngetc(void *, u_int *, int *);
245 1.60 augustss Static void ukbd_cnpollc(void *, int);
246 1.3 augustss
247 1.16 augustss #if defined(__NetBSD__)
248 1.8 drochner const struct wskbd_consops ukbd_consops = {
249 1.8 drochner ukbd_cngetc,
250 1.8 drochner ukbd_cnpollc,
251 1.8 drochner };
252 1.16 augustss #endif
253 1.8 drochner
254 1.60 augustss Static void ukbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
255 1.62 augustss Static void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
256 1.62 augustss Static void ukbd_delayed_decode(void *addr);
257 1.2 augustss
258 1.60 augustss Static int ukbd_enable(void *, int);
259 1.60 augustss Static void ukbd_set_leds(void *, int);
260 1.23 augustss
261 1.16 augustss #if defined(__NetBSD__)
262 1.60 augustss Static int ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
263 1.48 mjacob #ifdef WSDISPLAY_COMPAT_RAWKBD
264 1.60 augustss Static void ukbd_rawrepeat(void *v);
265 1.48 mjacob #endif
266 1.1 augustss
267 1.8 drochner const struct wskbd_accessops ukbd_accessops = {
268 1.8 drochner ukbd_enable,
269 1.8 drochner ukbd_set_leds,
270 1.8 drochner ukbd_ioctl,
271 1.8 drochner };
272 1.8 drochner
273 1.23 augustss extern const struct wscons_keydesc ukbd_keydesctab[];
274 1.23 augustss
275 1.8 drochner const struct wskbd_mapdata ukbd_keymapdata = {
276 1.23 augustss ukbd_keydesctab,
277 1.66 augustss #ifdef UKBD_LAYOUT
278 1.66 augustss UKBD_LAYOUT,
279 1.66 augustss #else
280 1.8 drochner KB_US,
281 1.66 augustss #endif
282 1.8 drochner };
283 1.16 augustss #endif
284 1.8 drochner
285 1.16 augustss USB_DECLARE_DRIVER(ukbd);
286 1.1 augustss
287 1.16 augustss USB_MATCH(ukbd)
288 1.1 augustss {
289 1.16 augustss USB_MATCH_START(ukbd, uaa);
290 1.1 augustss usb_interface_descriptor_t *id;
291 1.1 augustss
292 1.1 augustss /* Check that this is a keyboard that speaks the boot protocol. */
293 1.47 augustss if (uaa->iface == NULL)
294 1.1 augustss return (UMATCH_NONE);
295 1.1 augustss id = usbd_get_interface_descriptor(uaa->iface);
296 1.47 augustss if (id == NULL ||
297 1.56 augustss id->bInterfaceClass != UICLASS_HID ||
298 1.56 augustss id->bInterfaceSubClass != UISUBCLASS_BOOT ||
299 1.56 augustss id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD)
300 1.1 augustss return (UMATCH_NONE);
301 1.1 augustss return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
302 1.1 augustss }
303 1.1 augustss
304 1.16 augustss USB_ATTACH(ukbd)
305 1.1 augustss {
306 1.16 augustss USB_ATTACH_START(ukbd, sc, uaa);
307 1.1 augustss usbd_interface_handle iface = uaa->iface;
308 1.1 augustss usb_interface_descriptor_t *id;
309 1.1 augustss usb_endpoint_descriptor_t *ed;
310 1.47 augustss usbd_status err;
311 1.62 augustss u_int32_t qflags;
312 1.1 augustss char devinfo[1024];
313 1.16 augustss #if defined(__NetBSD__)
314 1.2 augustss struct wskbddev_attach_args a;
315 1.16 augustss #else
316 1.16 augustss int i;
317 1.16 augustss #endif
318 1.1 augustss
319 1.55 augustss sc->sc_udev = uaa->device;
320 1.1 augustss sc->sc_iface = iface;
321 1.1 augustss id = usbd_get_interface_descriptor(iface);
322 1.1 augustss usbd_devinfo(uaa->device, 0, devinfo);
323 1.16 augustss USB_ATTACH_SETUP;
324 1.16 augustss printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
325 1.12 augustss devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
326 1.16 augustss
327 1.1 augustss ed = usbd_interface2endpoint_descriptor(iface, 0);
328 1.47 augustss if (ed == NULL) {
329 1.1 augustss printf("%s: could not read endpoint descriptor\n",
330 1.16 augustss USBDEVNAME(sc->sc_dev));
331 1.16 augustss USB_ATTACH_ERROR_RETURN;
332 1.1 augustss }
333 1.1 augustss
334 1.15 augustss DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d "
335 1.15 augustss "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
336 1.15 augustss " bInterval=%d\n",
337 1.15 augustss ed->bLength, ed->bDescriptorType,
338 1.15 augustss ed->bEndpointAddress & UE_ADDR,
339 1.42 augustss UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
340 1.15 augustss ed->bmAttributes & UE_XFERTYPE,
341 1.15 augustss UGETW(ed->wMaxPacketSize), ed->bInterval));
342 1.1 augustss
343 1.42 augustss if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
344 1.1 augustss (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
345 1.1 augustss printf("%s: unexpected endpoint\n",
346 1.16 augustss USBDEVNAME(sc->sc_dev));
347 1.16 augustss USB_ATTACH_ERROR_RETURN;
348 1.1 augustss }
349 1.1 augustss
350 1.62 augustss qflags = usbd_get_quirks(uaa->device)->uq_flags;
351 1.62 augustss if ((qflags & UQ_NO_SET_PROTO) == 0) {
352 1.47 augustss err = usbd_set_protocol(iface, 0);
353 1.1 augustss DPRINTFN(5, ("ukbd_attach: protocol set\n"));
354 1.47 augustss if (err) {
355 1.1 augustss printf("%s: set protocol failed\n",
356 1.47 augustss USBDEVNAME(sc->sc_dev));
357 1.16 augustss USB_ATTACH_ERROR_RETURN;
358 1.1 augustss }
359 1.1 augustss }
360 1.62 augustss sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
361 1.20 augustss
362 1.6 augustss /* Ignore if SETIDLE fails since it is not crucial. */
363 1.62 augustss (void)usbd_set_idle(iface, 0, 0);
364 1.1 augustss
365 1.1 augustss sc->sc_ep_addr = ed->bEndpointAddress;
366 1.2 augustss
367 1.29 thorpej /*
368 1.29 thorpej * Remember if we're the console keyboard.
369 1.29 thorpej *
370 1.31 thorpej * XXX This always picks the first keyboard on the
371 1.31 thorpej * first USB bus, but what else can we really do?
372 1.29 thorpej */
373 1.31 thorpej if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
374 1.29 thorpej /* Don't let any other keyboard have it. */
375 1.31 thorpej ukbd_is_console = 0;
376 1.29 thorpej }
377 1.29 thorpej
378 1.31 thorpej if (sc->sc_console_keyboard) {
379 1.32 augustss DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
380 1.31 thorpej wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
381 1.34 wrstuden ukbd_enable(sc, 1);
382 1.31 thorpej }
383 1.29 thorpej
384 1.29 thorpej a.console = sc->sc_console_keyboard;
385 1.8 drochner
386 1.8 drochner a.keymap = &ukbd_keymapdata;
387 1.8 drochner
388 1.8 drochner a.accessops = &ukbd_accessops;
389 1.2 augustss a.accesscookie = sc;
390 1.8 drochner
391 1.70 augustss usb_callout_init(sc->sc_rawrepeat_ch);
392 1.57 thorpej
393 1.70 augustss usb_callout_init(sc->sc_delay);
394 1.62 augustss
395 1.19 augustss /* Flash the leds; no real purpose, just shows we're alive. */
396 1.19 augustss ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
397 1.23 augustss usbd_delay_ms(uaa->device, 400);
398 1.19 augustss ukbd_set_leds(sc, 0);
399 1.19 augustss
400 1.55 augustss usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
401 1.55 augustss USBDEV(sc->sc_dev));
402 1.64 augustss
403 1.64 augustss sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
404 1.55 augustss
405 1.16 augustss USB_ATTACH_SUCCESS_RETURN;
406 1.1 augustss }
407 1.1 augustss
408 1.8 drochner int
409 1.60 augustss ukbd_enable(void *v, int on)
410 1.8 drochner {
411 1.9 augustss struct ukbd_softc *sc = v;
412 1.47 augustss usbd_status err;
413 1.9 augustss
414 1.40 augustss if (on && sc->sc_dying)
415 1.40 augustss return (EIO);
416 1.40 augustss
417 1.38 augustss /* Should only be called to change state */
418 1.38 augustss if (sc->sc_enabled == on) {
419 1.38 augustss #ifdef DIAGNOSTIC
420 1.38 augustss printf("ukbd_enable: %s: bad call on=%d\n",
421 1.38 augustss USBDEVNAME(sc->sc_dev), on);
422 1.38 augustss #endif
423 1.38 augustss return (EBUSY);
424 1.38 augustss }
425 1.38 augustss
426 1.33 augustss DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
427 1.9 augustss if (on) {
428 1.9 augustss /* Set up interrupt pipe. */
429 1.47 augustss err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
430 1.47 augustss USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc,
431 1.54 augustss &sc->sc_ndata, sizeof(sc->sc_ndata), ukbd_intr,
432 1.54 augustss USBD_DEFAULT_INTERVAL);
433 1.47 augustss if (err)
434 1.9 augustss return (EIO);
435 1.9 augustss } else {
436 1.9 augustss /* Disable interrupts. */
437 1.9 augustss usbd_abort_pipe(sc->sc_intrpipe);
438 1.9 augustss usbd_close_pipe(sc->sc_intrpipe);
439 1.68 augustss sc->sc_intrpipe = NULL;
440 1.9 augustss }
441 1.38 augustss sc->sc_enabled = on;
442 1.9 augustss
443 1.8 drochner return (0);
444 1.37 augustss }
445 1.37 augustss
446 1.37 augustss int
447 1.60 augustss ukbd_activate(device_ptr_t self, enum devact act)
448 1.37 augustss {
449 1.40 augustss struct ukbd_softc *sc = (struct ukbd_softc *)self;
450 1.44 augustss int rv = 0;
451 1.40 augustss
452 1.40 augustss switch (act) {
453 1.40 augustss case DVACT_ACTIVATE:
454 1.40 augustss return (EOPNOTSUPP);
455 1.40 augustss break;
456 1.40 augustss
457 1.40 augustss case DVACT_DEACTIVATE:
458 1.47 augustss if (sc->sc_wskbddev != NULL)
459 1.44 augustss rv = config_deactivate(sc->sc_wskbddev);
460 1.40 augustss sc->sc_dying = 1;
461 1.40 augustss break;
462 1.40 augustss }
463 1.44 augustss return (rv);
464 1.37 augustss }
465 1.37 augustss
466 1.46 augustss USB_DETACH(ukbd)
467 1.37 augustss {
468 1.46 augustss USB_DETACH_START(ukbd, sc);
469 1.37 augustss int rv = 0;
470 1.37 augustss
471 1.37 augustss DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
472 1.46 augustss
473 1.37 augustss if (sc->sc_console_keyboard) {
474 1.50 augustss #if 0
475 1.37 augustss /*
476 1.37 augustss * XXX Should probably disconnect our consops,
477 1.37 augustss * XXX and either notify some other keyboard that
478 1.37 augustss * XXX it can now be the console, or if there aren't
479 1.37 augustss * XXX any more USB keyboards, set ukbd_is_console
480 1.37 augustss * XXX back to 1 so that the next USB keyboard attached
481 1.37 augustss * XXX to the system will get it.
482 1.37 augustss */
483 1.37 augustss panic("ukbd_detach: console keyboard");
484 1.50 augustss #else
485 1.51 augustss /*
486 1.51 augustss * Disconnect our consops and set ukbd_is_console
487 1.51 augustss * back to 1 so that the next USB keyboard attached
488 1.51 augustss * to the system will get it.
489 1.51 augustss * XXX Should notify some other keyboard that it can be
490 1.51 augustss * XXX console, if there are any other keyboards.
491 1.51 augustss */
492 1.51 augustss printf("%s: was console keyboard\n", USBDEVNAME(sc->sc_dev));
493 1.50 augustss wskbd_cndetach();
494 1.50 augustss ukbd_is_console = 1;
495 1.50 augustss #endif
496 1.37 augustss }
497 1.45 augustss /* No need to do reference counting of ukbd, wskbd has all the goo. */
498 1.47 augustss if (sc->sc_wskbddev != NULL)
499 1.37 augustss rv = config_detach(sc->sc_wskbddev, flags);
500 1.68 augustss
501 1.68 augustss /* The console keyboard does not get a disable call, so check pipe. */
502 1.68 augustss if (sc->sc_intrpipe != NULL) {
503 1.68 augustss usbd_abort_pipe(sc->sc_intrpipe);
504 1.68 augustss usbd_close_pipe(sc->sc_intrpipe);
505 1.68 augustss sc->sc_intrpipe = NULL;
506 1.68 augustss }
507 1.55 augustss
508 1.55 augustss usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
509 1.55 augustss USBDEV(sc->sc_dev));
510 1.55 augustss
511 1.37 augustss return (rv);
512 1.1 augustss }
513 1.1 augustss
514 1.1 augustss void
515 1.47 augustss ukbd_intr(xfer, addr, status)
516 1.47 augustss usbd_xfer_handle xfer;
517 1.1 augustss usbd_private_handle addr;
518 1.1 augustss usbd_status status;
519 1.1 augustss {
520 1.1 augustss struct ukbd_softc *sc = addr;
521 1.1 augustss struct ukbd_data *ud = &sc->sc_ndata;
522 1.1 augustss
523 1.1 augustss DPRINTFN(5, ("ukbd_intr: status=%d\n", status));
524 1.1 augustss if (status == USBD_CANCELLED)
525 1.1 augustss return;
526 1.1 augustss
527 1.49 augustss if (status) {
528 1.1 augustss DPRINTF(("ukbd_intr: status=%d\n", status));
529 1.67 augustss if (status == USBD_STALLED)
530 1.67 augustss usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
531 1.1 augustss return;
532 1.1 augustss }
533 1.1 augustss
534 1.69 augustss if (sc->sc_debounce && !sc->sc_polling) {
535 1.62 augustss /*
536 1.62 augustss * Some keyboards have a peculiar quirk. They sometimes
537 1.62 augustss * generate a key up followed by a key down for the same
538 1.62 augustss * key after about 10 ms.
539 1.62 augustss * We avoid this bug by holding off decoding for 20 ms.
540 1.62 augustss */
541 1.62 augustss sc->sc_data = *ud;
542 1.70 augustss usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc);
543 1.74 lukem #ifdef DDB
544 1.69 augustss } else if (sc->sc_console_keyboard && !sc->sc_polling) {
545 1.69 augustss /*
546 1.69 augustss * For the console keyboard we can't deliver CTL-ALT-ESC
547 1.69 augustss * from the interrupt routine. Doing so would start
548 1.69 augustss * polling from inside the interrupt routine and that
549 1.69 augustss * loses bigtime.
550 1.69 augustss */
551 1.69 augustss sc->sc_data = *ud;
552 1.70 augustss usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc);
553 1.69 augustss #endif
554 1.62 augustss } else {
555 1.62 augustss ukbd_decode(sc, ud);
556 1.62 augustss }
557 1.62 augustss }
558 1.62 augustss
559 1.62 augustss void
560 1.62 augustss ukbd_delayed_decode(void *addr)
561 1.62 augustss {
562 1.62 augustss struct ukbd_softc *sc = addr;
563 1.62 augustss
564 1.62 augustss ukbd_decode(sc, &sc->sc_data);
565 1.62 augustss }
566 1.62 augustss
567 1.62 augustss void
568 1.62 augustss ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
569 1.62 augustss {
570 1.62 augustss int mod, omod;
571 1.62 augustss u_int16_t ibuf[MAXKEYS]; /* chars events */
572 1.62 augustss int s;
573 1.62 augustss int nkeys, i, j;
574 1.62 augustss int key;
575 1.62 augustss #define ADDKEY(c) ibuf[nkeys++] = (c)
576 1.62 augustss
577 1.62 augustss #ifdef UKBD_DEBUG
578 1.62 augustss /*
579 1.62 augustss * Keep a trace of the last events. Using printf changes the
580 1.62 augustss * timing, so this can be useful sometimes.
581 1.62 augustss */
582 1.62 augustss if (ukbdtrace) {
583 1.62 augustss struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
584 1.62 augustss p->unit = sc->sc_dev.dv_unit;
585 1.62 augustss microtime(&p->tv);
586 1.62 augustss p->ud = *ud;
587 1.62 augustss if (++ukbdtraceindex >= UKBDTRACESIZE)
588 1.62 augustss ukbdtraceindex = 0;
589 1.62 augustss }
590 1.62 augustss if (ukbddebug > 5) {
591 1.62 augustss struct timeval tv;
592 1.62 augustss microtime(&tv);
593 1.62 augustss DPRINTF((" at %lu.%06lu mod=0x%02x key0=0x%02x key1=0x%02x "
594 1.62 augustss "key2=0x%02x key3=0x%02x\n",
595 1.62 augustss tv.tv_sec, tv.tv_usec,
596 1.62 augustss ud->modifiers, ud->keycode[0], ud->keycode[1],
597 1.62 augustss ud->keycode[2], ud->keycode[3]));
598 1.62 augustss }
599 1.62 augustss #endif
600 1.1 augustss
601 1.53 augustss if (ud->keycode[0] == KEY_ERROR) {
602 1.53 augustss DPRINTF(("ukbd_intr: KEY_ERROR\n"));
603 1.1 augustss return; /* ignore */
604 1.53 augustss }
605 1.1 augustss nkeys = 0;
606 1.1 augustss mod = ud->modifiers;
607 1.1 augustss omod = sc->sc_odata.modifiers;
608 1.1 augustss if (mod != omod)
609 1.1 augustss for (i = 0; i < NMOD; i++)
610 1.1 augustss if (( mod & ukbd_mods[i].mask) !=
611 1.1 augustss (omod & ukbd_mods[i].mask))
612 1.1 augustss ADDKEY(ukbd_mods[i].key |
613 1.1 augustss (mod & ukbd_mods[i].mask
614 1.1 augustss ? PRESS : RELEASE));
615 1.1 augustss if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) {
616 1.1 augustss /* Check for released keys. */
617 1.1 augustss for (i = 0; i < NKEYCODE; i++) {
618 1.1 augustss key = sc->sc_odata.keycode[i];
619 1.1 augustss if (key == 0)
620 1.1 augustss continue;
621 1.1 augustss for (j = 0; j < NKEYCODE; j++)
622 1.1 augustss if (key == ud->keycode[j])
623 1.1 augustss goto rfound;
624 1.62 augustss DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
625 1.23 augustss ADDKEY(key | RELEASE);
626 1.1 augustss rfound:
627 1.1 augustss ;
628 1.1 augustss }
629 1.1 augustss
630 1.1 augustss /* Check for pressed keys. */
631 1.1 augustss for (i = 0; i < NKEYCODE; i++) {
632 1.1 augustss key = ud->keycode[i];
633 1.1 augustss if (key == 0)
634 1.1 augustss continue;
635 1.1 augustss for (j = 0; j < NKEYCODE; j++)
636 1.1 augustss if (key == sc->sc_odata.keycode[j])
637 1.1 augustss goto pfound;
638 1.23 augustss DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
639 1.23 augustss ADDKEY(key | PRESS);
640 1.1 augustss pfound:
641 1.1 augustss ;
642 1.1 augustss }
643 1.1 augustss }
644 1.1 augustss sc->sc_odata = *ud;
645 1.1 augustss
646 1.20 augustss if (nkeys == 0)
647 1.20 augustss return;
648 1.20 augustss
649 1.3 augustss if (sc->sc_polling) {
650 1.23 augustss DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
651 1.23 augustss memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
652 1.23 augustss sc->sc_npollchar = nkeys;
653 1.3 augustss return;
654 1.3 augustss }
655 1.20 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
656 1.19 augustss if (sc->sc_rawkbd) {
657 1.19 augustss char cbuf[MAXKEYS * 2];
658 1.24 augustss int c;
659 1.20 augustss int npress;
660 1.20 augustss
661 1.23 augustss for (npress = i = j = 0; i < nkeys; i++) {
662 1.23 augustss key = ibuf[i];
663 1.23 augustss c = ukbd_trtab[key & CODEMASK];
664 1.23 augustss if (c == NN)
665 1.23 augustss continue;
666 1.19 augustss if (c & 0x80)
667 1.19 augustss cbuf[j++] = 0xe0;
668 1.19 augustss cbuf[j] = c & 0x7f;
669 1.23 augustss if (key & RELEASE)
670 1.19 augustss cbuf[j] |= 0x80;
671 1.20 augustss else {
672 1.23 augustss /* remember pressed keys for autorepeat */
673 1.20 augustss if (c & 0x80)
674 1.20 augustss sc->sc_rep[npress++] = 0xe0;
675 1.20 augustss sc->sc_rep[npress++] = c & 0x7f;
676 1.20 augustss }
677 1.27 augustss DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
678 1.27 augustss c & 0x80 ? "0xe0 " : "",
679 1.27 augustss cbuf[j]));
680 1.23 augustss j++;
681 1.19 augustss }
682 1.30 augustss s = spltty();
683 1.19 augustss wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
684 1.30 augustss splx(s);
685 1.70 augustss usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
686 1.20 augustss if (npress != 0) {
687 1.20 augustss sc->sc_nrep = npress;
688 1.70 augustss usb_callout(sc->sc_rawrepeat_ch,
689 1.57 thorpej hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc);
690 1.20 augustss }
691 1.19 augustss return;
692 1.19 augustss }
693 1.19 augustss #endif
694 1.19 augustss
695 1.30 augustss s = spltty();
696 1.2 augustss for (i = 0; i < nkeys; i++) {
697 1.23 augustss key = ibuf[i];
698 1.2 augustss wskbd_input(sc->sc_wskbddev,
699 1.23 augustss key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
700 1.23 augustss key&CODEMASK);
701 1.20 augustss }
702 1.30 augustss splx(s);
703 1.1 augustss }
704 1.1 augustss
705 1.2 augustss void
706 1.60 augustss ukbd_set_leds(void *v, int leds)
707 1.1 augustss {
708 1.2 augustss struct ukbd_softc *sc = v;
709 1.2 augustss u_int8_t res;
710 1.1 augustss
711 1.71 augustss DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
712 1.71 augustss sc, leds, sc->sc_leds));
713 1.40 augustss
714 1.40 augustss if (sc->sc_dying)
715 1.40 augustss return;
716 1.1 augustss
717 1.71 augustss if (sc->sc_leds == leds)
718 1.71 augustss return;
719 1.2 augustss sc->sc_leds = leds;
720 1.2 augustss res = 0;
721 1.2 augustss if (leds & WSKBD_LED_SCROLL)
722 1.2 augustss res |= SCROLL_LOCK;
723 1.2 augustss if (leds & WSKBD_LED_NUM)
724 1.2 augustss res |= NUM_LOCK;
725 1.2 augustss if (leds & WSKBD_LED_CAPS)
726 1.2 augustss res |= CAPS_LOCK;
727 1.34 wrstuden res |= leds & 0xf8;
728 1.4 augustss usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
729 1.1 augustss }
730 1.1 augustss
731 1.20 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
732 1.20 augustss void
733 1.60 augustss ukbd_rawrepeat(void *v)
734 1.20 augustss {
735 1.20 augustss struct ukbd_softc *sc = v;
736 1.30 augustss int s;
737 1.20 augustss
738 1.30 augustss s = spltty();
739 1.20 augustss wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
740 1.30 augustss splx(s);
741 1.70 augustss usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
742 1.57 thorpej ukbd_rawrepeat, sc);
743 1.20 augustss }
744 1.20 augustss #endif
745 1.20 augustss
746 1.1 augustss int
747 1.60 augustss ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
748 1.1 augustss {
749 1.2 augustss struct ukbd_softc *sc = v;
750 1.1 augustss
751 1.2 augustss switch (cmd) {
752 1.2 augustss case WSKBDIO_GTYPE:
753 1.20 augustss *(int *)data = WSKBD_TYPE_USB;
754 1.17 augustss return (0);
755 1.2 augustss case WSKBDIO_SETLEDS:
756 1.2 augustss ukbd_set_leds(v, *(int *)data);
757 1.17 augustss return (0);
758 1.2 augustss case WSKBDIO_GETLEDS:
759 1.2 augustss *(int *)data = sc->sc_leds;
760 1.2 augustss return (0);
761 1.2 augustss #ifdef WSDISPLAY_COMPAT_RAWKBD
762 1.2 augustss case WSKBDIO_SETMODE:
763 1.19 augustss DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
764 1.2 augustss sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
765 1.70 augustss usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
766 1.2 augustss return (0);
767 1.2 augustss #endif
768 1.2 augustss }
769 1.17 augustss return (-1);
770 1.1 augustss }
771 1.7 augustss
772 1.71 augustss /*
773 1.71 augustss * This is a hack to work around some broken ports that don't call
774 1.71 augustss * cnpollc() before cngetc().
775 1.71 augustss */
776 1.71 augustss static int pollenter, warned;
777 1.71 augustss
778 1.7 augustss /* Console interface. */
779 1.3 augustss void
780 1.60 augustss ukbd_cngetc(void *v, u_int *type, int *data)
781 1.3 augustss {
782 1.3 augustss struct ukbd_softc *sc = v;
783 1.35 augustss int s;
784 1.4 augustss int c;
785 1.71 augustss int broken;
786 1.71 augustss
787 1.71 augustss if (pollenter == 0) {
788 1.71 augustss if (!warned) {
789 1.71 augustss printf("\n"
790 1.71 augustss "This port is broken, it does not call cnpollc() before calling cngetc().\n"
791 1.71 augustss "This should be fixed, but it will work anyway (for now).\n");
792 1.71 augustss warned = 1;
793 1.71 augustss }
794 1.71 augustss broken = 1;
795 1.71 augustss ukbd_cnpollc(v, 1);
796 1.71 augustss } else
797 1.71 augustss broken = 0;
798 1.3 augustss
799 1.50 augustss DPRINTFN(0,("ukbd_cngetc: enter\n"));
800 1.35 augustss s = splusb();
801 1.3 augustss sc->sc_polling = 1;
802 1.23 augustss while(sc->sc_npollchar <= 0)
803 1.3 augustss usbd_dopoll(sc->sc_iface);
804 1.3 augustss sc->sc_polling = 0;
805 1.23 augustss c = sc->sc_pollchars[0];
806 1.23 augustss sc->sc_npollchar--;
807 1.23 augustss memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
808 1.23 augustss sc->sc_npollchar * sizeof(u_int16_t));
809 1.6 augustss *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
810 1.23 augustss *data = c & CODEMASK;
811 1.35 augustss splx(s);
812 1.50 augustss DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
813 1.71 augustss if (broken)
814 1.71 augustss ukbd_cnpollc(v, 0);
815 1.3 augustss }
816 1.3 augustss
817 1.3 augustss void
818 1.60 augustss ukbd_cnpollc(void *v, int on)
819 1.3 augustss {
820 1.6 augustss struct ukbd_softc *sc = v;
821 1.52 augustss usbd_device_handle dev;
822 1.6 augustss
823 1.19 augustss DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
824 1.6 augustss
825 1.73 augustss usbd_interface2device_handle(sc->sc_iface,&dev);
826 1.71 augustss if (on) pollenter++; else pollenter--;
827 1.52 augustss usbd_set_polling(dev, on);
828 1.3 augustss }
829 1.18 augustss
830 1.18 augustss int
831 1.60 augustss ukbd_cnattach(void)
832 1.18 augustss {
833 1.18 augustss
834 1.31 thorpej /*
835 1.31 thorpej * XXX USB requires too many parts of the kernel to be running
836 1.31 thorpej * XXX in order to work, so we can't do much for the console
837 1.31 thorpej * XXX keyboard until autconfiguration has run its course.
838 1.31 thorpej */
839 1.31 thorpej ukbd_is_console = 1;
840 1.18 augustss return (0);
841 1.18 augustss }
842