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