This source file includes following definitions.
- ukbdtracedump
- ukbd_match
- ukbd_attach
- ukbd_enable
- ukbd_activate
- ukbd_detach
- ukbd_intr
- ukbd_delayed_decode
- ukbd_decode
- ukbd_set_leds
- ukbd_rawrepeat
- ukbd_ioctl
- ukbd_cngetc
- ukbd_cnpollc
- ukbd_cnattach
- ukbd_parse_desc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/timeout.h>
48 #include <sys/kernel.h>
49 #include <sys/device.h>
50 #include <sys/ioctl.h>
51 #include <sys/tty.h>
52 #include <sys/file.h>
53 #include <sys/selinfo.h>
54 #include <sys/proc.h>
55 #include <sys/vnode.h>
56 #include <sys/poll.h>
57
58 #include <dev/usb/usb.h>
59 #include <dev/usb/usbhid.h>
60
61 #include <dev/usb/usbdi.h>
62 #include <dev/usb/usbdi_util.h>
63 #include <dev/usb/usbdevs.h>
64 #include <dev/usb/usb_quirks.h>
65 #include <dev/usb/uhidev.h>
66 #include <dev/usb/hid.h>
67 #include <dev/usb/ukbdvar.h>
68
69 #include <dev/wscons/wsconsio.h>
70 #include <dev/wscons/wskbdvar.h>
71 #include <dev/wscons/wsksymdef.h>
72 #include <dev/wscons/wsksymvar.h>
73
74 #ifdef UKBD_DEBUG
75 #define DPRINTF(x) do { if (ukbddebug) printf x; } while (0)
76 #define DPRINTFN(n,x) do { if (ukbddebug>(n)) printf x; } while (0)
77 int ukbddebug = 0;
78 #else
79 #define DPRINTF(x)
80 #define DPRINTFN(n,x)
81 #endif
82
83 #define MAXKEYCODE 6
84 #define MAXMOD 8
85
86 struct ukbd_data {
87 u_int32_t modifiers;
88 u_int8_t keycode[MAXKEYCODE];
89 };
90
91 #define PRESS 0x000
92 #define RELEASE 0x100
93 #define CODEMASK 0x0ff
94
95 #if defined(WSDISPLAY_COMPAT_RAWKBD)
96 #define NN 0
97
98
99
100
101
102
103 const u_int8_t ukbd_trtab[256] = {
104 NN, NN, NN, NN, 0x1e, 0x30, 0x2e, 0x20,
105 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26,
106 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14,
107 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03,
108 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
109 0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a,
110 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34,
111 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
112 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46,
113 0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd,
114 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e,
115 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47,
116 0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, NN, 0x59,
117 0x5d, 0x5e, 0x5f, NN, NN, NN, NN, NN,
118 NN, NN, NN, NN, 0x97, NN, 0x93, 0x95,
119 0x91, 0x92, 0x94, 0x9a, 0x96, 0x98, 0x99, NN,
120 NN, NN, NN, NN, NN, 0x7e, NN, 0x73,
121 0x70, 0x7d, 0x79, 0x7b, 0x5c, NN, NN, NN,
122 NN, NN, 0x78, 0x77, 0x76, NN, NN, NN,
123 NN, NN, NN, NN, NN, NN, NN, NN,
124 NN, NN, NN, NN, NN, NN, NN, NN,
125 NN, NN, NN, NN, NN, NN, NN, NN,
126 NN, NN, NN, NN, NN, NN, NN, NN,
127 NN, NN, NN, NN, NN, NN, NN, NN,
128 NN, NN, NN, NN, NN, NN, NN, NN,
129 NN, NN, NN, NN, NN, NN, NN, NN,
130 NN, NN, NN, NN, NN, NN, NN, NN,
131 NN, NN, NN, NN, NN, NN, NN, NN,
132 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc,
133 NN, NN, NN, NN, NN, NN, NN, NN,
134 NN, NN, NN, NN, NN, NN, NN, NN,
135 NN, NN, NN, NN, NN, NN, NN, NN,
136 };
137 #endif
138
139 const kbd_t ukbd_countrylayout[HCC_MAX] = {
140 (kbd_t)-1,
141 (kbd_t)-1,
142 KB_BE,
143 (kbd_t)-1,
144 KB_CF,
145 (kbd_t)-1,
146 KB_DK,
147 (kbd_t)-1,
148 KB_FR,
149 KB_DE,
150 (kbd_t)-1,
151 (kbd_t)-1,
152 KB_HU,
153 (kbd_t)-1,
154 KB_IT,
155 KB_JP,
156 (kbd_t)-1,
157 KB_LA,
158 (kbd_t)-1,
159 KB_NO,
160 (kbd_t)-1,
161 KB_PL,
162 KB_PT,
163 KB_RU,
164 (kbd_t)-1,
165 KB_ES,
166 KB_SF,
167 KB_SG,
168 (kbd_t)-1,
169 (kbd_t)-1,
170 KB_TR,
171 KB_UK,
172 KB_US,
173 (kbd_t)-1,
174 (kbd_t)-1
175 };
176
177 #define SUN_HCC_MIN 0x21
178 #define SUN_HCC_MAX 0x3f
179 const kbd_t ukbd_sunlayout[1 + SUN_HCC_MAX - SUN_HCC_MIN] = {
180 KB_US,
181 KB_US,
182 KB_FR,
183 KB_DK,
184 KB_DE,
185 KB_IT,
186 KB_NL,
187 KB_NO,
188 KB_PT,
189 KB_ES,
190 KB_SV,
191 KB_SF,
192 KB_SG,
193 KB_UK,
194 -1,
195 -1,
196 KB_JP,
197 -1,
198 -1,
199 -1,
200 -1,
201 -1,
202 -1,
203 -1,
204 -1,
205 -1,
206 -1,
207 -1,
208 -1,
209 -1,
210 -1,
211 };
212
213 #define KEY_ERROR 0x01
214
215 #define MAXKEYS (MAXMOD+2*MAXKEYCODE)
216
217 struct ukbd_softc {
218 struct uhidev sc_hdev;
219
220 struct ukbd_data sc_ndata;
221 struct ukbd_data sc_odata;
222 struct hid_location sc_modloc[MAXMOD];
223 u_int sc_nmod;
224 struct {
225 u_int32_t mask;
226 u_int8_t key;
227 } sc_mods[MAXMOD];
228
229 struct hid_location sc_keycodeloc;
230 u_int sc_nkeycode;
231
232 char sc_enabled;
233
234 int sc_console_keyboard;
235
236 char sc_debounce;
237 struct timeout sc_delay;
238 struct ukbd_data sc_data;
239
240 struct hid_location sc_numloc;
241 struct hid_location sc_capsloc;
242 struct hid_location sc_scroloc;
243 int sc_leds;
244
245 struct timeout sc_rawrepeat_ch;
246
247 struct device *sc_wskbddev;
248 #if defined(WSDISPLAY_COMPAT_RAWKBD)
249 #define REP_DELAY1 400
250 #define REP_DELAYN 100
251 int sc_rawkbd;
252 int sc_nrep;
253 char sc_rep[MAXKEYS];
254 #endif
255
256 int sc_spl;
257 int sc_polling;
258 int sc_npollchar;
259 u_int16_t sc_pollchars[MAXKEYS];
260
261 u_char sc_dying;
262 };
263
264 #ifdef UKBD_DEBUG
265 #define UKBDTRACESIZE 64
266 struct ukbdtraceinfo {
267 int unit;
268 struct timeval tv;
269 struct ukbd_data ud;
270 };
271 struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
272 int ukbdtraceindex = 0;
273 int ukbdtrace = 0;
274 void ukbdtracedump(void);
275 void
276 ukbdtracedump(void)
277 {
278 int i;
279 for (i = 0; i < UKBDTRACESIZE; i++) {
280 struct ukbdtraceinfo *p =
281 &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
282 printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
283 "key2=0x%02x key3=0x%02x\n",
284 p->tv.tv_sec, p->tv.tv_usec,
285 p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
286 p->ud.keycode[2], p->ud.keycode[3]);
287 }
288 }
289 #endif
290
291 #define UKBDUNIT(dev) (minor(dev))
292 #define UKBD_CHUNK 128
293 #define UKBD_BSIZE 1020
294
295 int ukbd_is_console;
296
297 void ukbd_cngetc(void *, u_int *, int *);
298 void ukbd_cnpollc(void *, int);
299
300 const struct wskbd_consops ukbd_consops = {
301 ukbd_cngetc,
302 ukbd_cnpollc,
303 };
304
305 const char *ukbd_parse_desc(struct ukbd_softc *sc);
306
307 void ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
308 void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
309 void ukbd_delayed_decode(void *addr);
310
311 int ukbd_enable(void *, int);
312 void ukbd_set_leds(void *, int);
313
314 int ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
315 #ifdef WSDISPLAY_COMPAT_RAWKBD
316 void ukbd_rawrepeat(void *v);
317 #endif
318
319 const struct wskbd_accessops ukbd_accessops = {
320 ukbd_enable,
321 ukbd_set_leds,
322 ukbd_ioctl,
323 };
324
325 extern const struct wscons_keydesc ukbd_keydesctab[];
326
327 struct wskbd_mapdata ukbd_keymapdata = {
328 ukbd_keydesctab
329 };
330
331 int ukbd_match(struct device *, void *, void *);
332 void ukbd_attach(struct device *, struct device *, void *);
333 int ukbd_detach(struct device *, int);
334 int ukbd_activate(struct device *, enum devact);
335
336 struct cfdriver ukbd_cd = {
337 NULL, "ukbd", DV_DULL
338 };
339
340 const struct cfattach ukbd_ca = {
341 sizeof(struct ukbd_softc),
342 ukbd_match,
343 ukbd_attach,
344 ukbd_detach,
345 ukbd_activate,
346 };
347
348 int
349 ukbd_match(struct device *parent, void *match, void *aux)
350 {
351 struct usb_attach_arg *uaa = aux;
352 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
353 int size;
354 void *desc;
355
356 uhidev_get_report_desc(uha->parent, &desc, &size);
357 if (!hid_is_collection(desc, size, uha->reportid,
358 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
359 return (UMATCH_NONE);
360
361 return (UMATCH_IFACECLASS);
362 }
363
364 void
365 ukbd_attach(struct device *parent, struct device *self, void *aux)
366 {
367 struct ukbd_softc *sc = (struct ukbd_softc *)self;
368 struct usb_attach_arg *uaa = aux;
369 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
370 usb_hid_descriptor_t *hid;
371 u_int32_t qflags;
372 const char *parseerr;
373 kbd_t layout = (kbd_t)-1;
374 struct wskbddev_attach_args a;
375
376 sc->sc_hdev.sc_intr = ukbd_intr;
377 sc->sc_hdev.sc_parent = uha->parent;
378 sc->sc_hdev.sc_report_id = uha->reportid;
379
380 parseerr = ukbd_parse_desc(sc);
381 if (parseerr != NULL) {
382 printf("\n%s: attach failed, %s\n",
383 sc->sc_hdev.sc_dev.dv_xname, parseerr);
384 return;
385 }
386
387 hid = usbd_get_hid_descriptor(uha->uaa->iface);
388
389 #ifdef DIAGNOSTIC
390 printf(": %d modifier keys, %d key codes",
391 sc->sc_nmod, sc->sc_nkeycode);
392 #endif
393
394 qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
395 sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
396
397
398
399
400
401
402
403 if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
404
405 ukbd_is_console = 0;
406 }
407
408 if (uha->uaa->vendor == USB_VENDOR_SUN &&
409 (uha->uaa->product == USB_PRODUCT_SUN_KEYBOARD6 ||
410 uha->uaa->product == USB_PRODUCT_SUN_KEYBOARD7)) {
411
412 if (hid->bCountryCode >= SUN_HCC_MIN &&
413 hid->bCountryCode <= SUN_HCC_MAX)
414 layout = ukbd_sunlayout[hid->bCountryCode - SUN_HCC_MIN];
415 #ifdef DIAGNOSTIC
416 if (hid->bCountryCode != 0)
417 printf(", layout %d", hid->bCountryCode);
418 #endif
419 } else {
420 if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
421 uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) {
422
423 } else {
424 if (hid->bCountryCode <= HCC_MAX)
425 layout = ukbd_countrylayout[hid->bCountryCode];
426 #ifdef DIAGNOSTIC
427 if (hid->bCountryCode != 0)
428 printf(", country code %d", hid->bCountryCode);
429 #endif
430 }
431 }
432 if (layout == (kbd_t)-1) {
433 #ifdef UKBD_LAYOUT
434 layout = UKBD_LAYOUT;
435 #else
436 layout = KB_US;
437 #endif
438 }
439 ukbd_keymapdata.layout = layout;
440
441 printf("\n");
442
443 if (sc->sc_console_keyboard) {
444 DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
445 wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
446 ukbd_enable(sc, 1);
447 }
448
449 a.console = sc->sc_console_keyboard;
450
451 a.keymap = &ukbd_keymapdata;
452
453 a.accessops = &ukbd_accessops;
454 a.accesscookie = sc;
455
456 timeout_set(&sc->sc_rawrepeat_ch, NULL, NULL);
457 timeout_set(&sc->sc_delay, NULL, NULL);
458
459
460 ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
461 usbd_delay_ms(uha->parent->sc_udev, 400);
462 ukbd_set_leds(sc, 0);
463
464 sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
465 }
466
467 int
468 ukbd_enable(void *v, int on)
469 {
470 struct ukbd_softc *sc = v;
471
472 if (on && sc->sc_dying)
473 return (EIO);
474
475
476 if (sc->sc_enabled == on) {
477 DPRINTF(("ukbd_enable: %s: bad call on=%d\n",
478 sc->sc_hdev.sc_dev.dv_xname, on));
479 return (EBUSY);
480 }
481
482 DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
483 sc->sc_enabled = on;
484 if (on) {
485 return (uhidev_open(&sc->sc_hdev));
486 } else {
487 uhidev_close(&sc->sc_hdev);
488 return (0);
489 }
490 }
491
492 int
493 ukbd_activate(struct device *self, enum devact act)
494 {
495 struct ukbd_softc *sc = (struct ukbd_softc *)self;
496 int rv = 0;
497
498 switch (act) {
499 case DVACT_ACTIVATE:
500 break;
501
502 case DVACT_DEACTIVATE:
503 if (sc->sc_wskbddev != NULL)
504 rv = config_deactivate(sc->sc_wskbddev);
505 sc->sc_dying = 1;
506 break;
507 }
508 return (rv);
509 }
510
511 int
512 ukbd_detach(struct device *self, int flags)
513 {
514 struct ukbd_softc *sc = (struct ukbd_softc *)self;
515 int rv = 0;
516
517 DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
518
519 if (sc->sc_console_keyboard) {
520 #if 0
521
522
523
524
525
526
527
528
529 panic("ukbd_detach: console keyboard");
530 #else
531
532
533
534
535
536
537
538 printf("%s: was console keyboard\n",
539 sc->sc_hdev.sc_dev.dv_xname);
540 wskbd_cndetach();
541 ukbd_is_console = 1;
542 #endif
543 }
544
545 if (sc->sc_wskbddev != NULL)
546 rv = config_detach(sc->sc_wskbddev, flags);
547
548
549 if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
550 uhidev_close(&sc->sc_hdev);
551
552 return (rv);
553 }
554
555 void
556 ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
557 {
558 struct ukbd_softc *sc = (struct ukbd_softc *)addr;
559 struct ukbd_data *ud = &sc->sc_ndata;
560 int i;
561
562 #ifdef UKBD_DEBUG
563 if (ukbddebug > 5) {
564 printf("ukbd_intr: data");
565 for (i = 0; i < len; i++)
566 printf(" 0x%02x", ((u_char *)ibuf)[i]);
567 printf("\n");
568 }
569 #endif
570
571 ud->modifiers = 0;
572 for (i = 0; i < sc->sc_nmod; i++)
573 if (hid_get_data(ibuf, &sc->sc_modloc[i]))
574 ud->modifiers |= sc->sc_mods[i].mask;
575 memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8,
576 sc->sc_nkeycode);
577
578 if (sc->sc_debounce && !sc->sc_polling) {
579
580
581
582
583
584
585 sc->sc_data = *ud;
586 timeout_del(&sc->sc_delay);
587 timeout_set(&sc->sc_delay, ukbd_delayed_decode, sc);
588 timeout_add(&sc->sc_delay, hz / 50);
589 #ifdef DDB
590 } else if (sc->sc_console_keyboard && !sc->sc_polling) {
591
592
593
594
595
596
597 sc->sc_data = *ud;
598 timeout_del(&sc->sc_delay);
599 timeout_set(&sc->sc_delay, ukbd_delayed_decode, sc);
600 timeout_add(&sc->sc_delay, 1);
601 #endif
602 } else {
603 ukbd_decode(sc, ud);
604 }
605 }
606
607 void
608 ukbd_delayed_decode(void *addr)
609 {
610 struct ukbd_softc *sc = addr;
611
612 ukbd_decode(sc, &sc->sc_data);
613 }
614
615 void
616 ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
617 {
618 int mod, omod;
619 u_int16_t ibuf[MAXKEYS];
620 int s;
621 int nkeys, i, j;
622 int key;
623 #define ADDKEY(c) ibuf[nkeys++] = (c)
624
625 #ifdef UKBD_DEBUG
626
627
628
629
630 if (ukbdtrace) {
631 struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
632 p->unit = sc->sc_hdev.sc_dev.dv_unit;
633 microtime(&p->tv);
634 p->ud = *ud;
635 if (++ukbdtraceindex >= UKBDTRACESIZE)
636 ukbdtraceindex = 0;
637 }
638 if (ukbddebug > 5) {
639 struct timeval tv;
640 microtime(&tv);
641 DPRINTF((" at %lu.%06lu mod=0x%02x key0=0x%02x key1=0x%02x "
642 "key2=0x%02x key3=0x%02x\n",
643 tv.tv_sec, tv.tv_usec,
644 ud->modifiers, ud->keycode[0], ud->keycode[1],
645 ud->keycode[2], ud->keycode[3]));
646 }
647 #endif
648
649 if (ud->keycode[0] == KEY_ERROR) {
650 DPRINTF(("ukbd_intr: KEY_ERROR\n"));
651 return;
652 }
653 nkeys = 0;
654 mod = ud->modifiers;
655 omod = sc->sc_odata.modifiers;
656 if (mod != omod)
657 for (i = 0; i < sc->sc_nmod; i++)
658 if (( mod & sc->sc_mods[i].mask) !=
659 (omod & sc->sc_mods[i].mask))
660 ADDKEY(sc->sc_mods[i].key |
661 (mod & sc->sc_mods[i].mask
662 ? PRESS : RELEASE));
663 if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
664
665 for (i = 0; i < sc->sc_nkeycode; i++) {
666 key = sc->sc_odata.keycode[i];
667 if (key == 0)
668 continue;
669 for (j = 0; j < sc->sc_nkeycode; j++)
670 if (key == ud->keycode[j])
671 goto rfound;
672 DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
673 ADDKEY(key | RELEASE);
674 rfound:
675 ;
676 }
677
678
679 for (i = 0; i < sc->sc_nkeycode; i++) {
680 key = ud->keycode[i];
681 if (key == 0)
682 continue;
683 for (j = 0; j < sc->sc_nkeycode; j++)
684 if (key == sc->sc_odata.keycode[j])
685 goto pfound;
686 DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
687 ADDKEY(key | PRESS);
688 pfound:
689 ;
690 }
691 }
692 sc->sc_odata = *ud;
693
694 if (nkeys == 0)
695 return;
696
697 if (sc->sc_polling) {
698 DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
699 memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
700 sc->sc_npollchar = nkeys;
701 return;
702 }
703 #ifdef WSDISPLAY_COMPAT_RAWKBD
704 if (sc->sc_rawkbd) {
705 u_char cbuf[MAXKEYS * 2];
706 int c;
707 int npress;
708
709 for (npress = i = j = 0; i < nkeys; i++) {
710 key = ibuf[i];
711 c = ukbd_trtab[key & CODEMASK];
712 if (c == NN)
713 continue;
714 if (c & 0x80)
715 cbuf[j++] = 0xe0;
716 cbuf[j] = c & 0x7f;
717 if (key & RELEASE)
718 cbuf[j] |= 0x80;
719 else {
720
721 if (c & 0x80)
722 sc->sc_rep[npress++] = 0xe0;
723 sc->sc_rep[npress++] = c & 0x7f;
724 }
725 DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
726 c & 0x80 ? "0xe0 " : "",
727 cbuf[j]));
728 j++;
729 }
730 s = spltty();
731 wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
732 splx(s);
733 timeout_del(&sc->sc_rawrepeat_ch);
734 if (npress != 0) {
735 sc->sc_nrep = npress;
736 timeout_del(&sc->sc_rawrepeat_ch);
737 timeout_set(&sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
738 timeout_add(&sc->sc_rawrepeat_ch,
739 hz * REP_DELAY1 / 1000);
740 }
741 return;
742 }
743 #endif
744
745 s = spltty();
746 for (i = 0; i < nkeys; i++) {
747 key = ibuf[i];
748 wskbd_input(sc->sc_wskbddev,
749 key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
750 key&CODEMASK);
751 }
752 splx(s);
753 }
754
755 void
756 ukbd_set_leds(void *v, int leds)
757 {
758 struct ukbd_softc *sc = v;
759 u_int8_t res;
760
761 DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
762 sc, leds, sc->sc_leds));
763
764 if (sc->sc_dying)
765 return;
766
767 if (sc->sc_leds == leds)
768 return;
769 sc->sc_leds = leds;
770 res = 0;
771
772 if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
773 res |= 1 << sc->sc_scroloc.pos;
774 if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
775 res |= 1 << sc->sc_numloc.pos;
776 if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
777 res |= 1 << sc->sc_capsloc.pos;
778 uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
779 }
780
781 #ifdef WSDISPLAY_COMPAT_RAWKBD
782 void
783 ukbd_rawrepeat(void *v)
784 {
785 struct ukbd_softc *sc = v;
786 int s;
787
788 s = spltty();
789 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
790 splx(s);
791 timeout_del(&sc->sc_rawrepeat_ch);
792 timeout_set(&sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
793 timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
794 }
795 #endif
796
797 int
798 ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
799 {
800 struct ukbd_softc *sc = v;
801
802 switch (cmd) {
803 case WSKBDIO_GTYPE:
804 *(int *)data = WSKBD_TYPE_USB;
805 return (0);
806 case WSKBDIO_SETLEDS:
807 ukbd_set_leds(v, *(int *)data);
808 return (0);
809 case WSKBDIO_GETLEDS:
810 *(int *)data = sc->sc_leds;
811 return (0);
812 #ifdef WSDISPLAY_COMPAT_RAWKBD
813 case WSKBDIO_SETMODE:
814 DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
815 sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
816 timeout_del(&sc->sc_rawrepeat_ch);
817 return (0);
818 #endif
819 }
820 return (-1);
821 }
822
823
824
825
826
827 static int pollenter, warned;
828
829
830 void
831 ukbd_cngetc(void *v, u_int *type, int *data)
832 {
833 struct ukbd_softc *sc = v;
834 int c;
835 int broken;
836
837 if (pollenter == 0) {
838 if (!warned) {
839 printf("\n"
840 "This port is broken, it does not call cnpollc() before calling cngetc().\n"
841 "This should be fixed, but it will work anyway (for now).\n");
842 warned = 1;
843 }
844 broken = 1;
845 ukbd_cnpollc(v, 1);
846 } else
847 broken = 0;
848
849 DPRINTFN(0,("ukbd_cngetc: enter\n"));
850 sc->sc_polling = 1;
851 while(sc->sc_npollchar <= 0)
852 usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
853 sc->sc_polling = 0;
854 c = sc->sc_pollchars[0];
855 sc->sc_npollchar--;
856 memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
857 sc->sc_npollchar * sizeof(u_int16_t));
858 *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
859 *data = c & CODEMASK;
860 DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
861 if (broken)
862 ukbd_cnpollc(v, 0);
863 }
864
865 void
866 ukbd_cnpollc(void *v, int on)
867 {
868 struct ukbd_softc *sc = v;
869 usbd_device_handle dev;
870
871 DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
872
873 usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev);
874 if (on) {
875 sc->sc_spl = splusb();
876 pollenter++;
877 } else {
878 splx(sc->sc_spl);
879 pollenter--;
880 }
881 usbd_set_polling(dev, on);
882 }
883
884 int
885 ukbd_cnattach(void)
886 {
887
888
889
890
891
892
893 ukbd_is_console = 1;
894 return (0);
895 }
896
897 const char *
898 ukbd_parse_desc(struct ukbd_softc *sc)
899 {
900 struct hid_data *d;
901 struct hid_item h;
902 int size;
903 void *desc;
904 int imod;
905
906 uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
907 imod = 0;
908 sc->sc_nkeycode = 0;
909 d = hid_start_parse(desc, size, hid_input);
910 while (hid_get_item(d, &h)) {
911
912
913 if (h.kind != hid_input || (h.flags & HIO_CONST) ||
914 HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
915 h.report_ID != sc->sc_hdev.sc_report_id)
916 continue;
917 DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
918 "cnt=%d\n", imod,
919 h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
920 if (h.flags & HIO_VARIABLE) {
921 if (h.loc.size != 1)
922 return ("bad modifier size");
923
924 if (imod < MAXMOD) {
925 sc->sc_modloc[imod] = h.loc;
926 sc->sc_mods[imod].mask = 1 << imod;
927 sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
928 imod++;
929 } else
930 return ("too many modifier keys");
931 } else {
932
933 if (h.loc.size != 8)
934 return ("key code size != 8");
935 if (h.loc.count > MAXKEYCODE)
936 return ("too many key codes");
937 if (h.loc.pos % 8 != 0)
938 return ("key codes not on byte boundary");
939 if (sc->sc_nkeycode != 0)
940 return ("multiple key code arrays\n");
941 sc->sc_keycodeloc = h.loc;
942 sc->sc_nkeycode = h.loc.count;
943 }
944 }
945 sc->sc_nmod = imod;
946 hid_end_parse(d);
947
948 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
949 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
950 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
951 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
952 hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
953 sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);
954
955 return (NULL);
956 }