This source file includes following definitions.
- hilkbdprobe
- hilkbdattach
- hilkbddetach
- hilkbd_enable
- hilkbd_set_leds
- hilkbd_ioctl
- hilkbd_cngetc
- hilkbd_cnpollc
- hilkbd_cnbell
- hilkbd_bell
- hilkbd_callback
- hilkbd_decode
- hilkbd_is_console
- hilkbd_rawrepeat
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 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/ioctl.h>
33 #include <sys/kernel.h>
34 #include <sys/timeout.h>
35
36 #include <machine/autoconf.h>
37 #include <machine/bus.h>
38 #include <machine/cpu.h>
39
40 #include <dev/hil/hilreg.h>
41 #include <dev/hil/hilvar.h>
42 #include <dev/hil/hildevs.h>
43
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wscons/wskbdvar.h>
46 #include <dev/wscons/wsksymdef.h>
47 #include <dev/wscons/wsksymvar.h>
48 #ifdef WSDISPLAY_COMPAT_RAWKBD
49 #include <dev/wscons/wskbdraw.h>
50 #endif
51
52 #include <dev/hil/hilkbdmap.h>
53
54 struct hilkbd_softc {
55 struct hildev_softc sc_hildev;
56
57 int sc_numleds;
58 int sc_ledstate;
59 int sc_enabled;
60 int sc_console;
61 int sc_lastarrow;
62
63 struct device *sc_wskbddev;
64
65 #ifdef WSDISPLAY_COMPAT_RAWKBD
66 int sc_rawkbd;
67 int sc_nrep;
68 char sc_rep[HILBUFSIZE * 2];
69 struct timeout sc_rawrepeat_ch;
70 #define REP_DELAY1 400
71 #define REP_DELAYN 100
72 #endif
73 };
74
75 int hilkbdprobe(struct device *, void *, void *);
76 void hilkbdattach(struct device *, struct device *, void *);
77 int hilkbddetach(struct device *, int);
78
79 struct cfdriver hilkbd_cd = {
80 NULL, "hilkbd", DV_DULL
81 };
82
83 struct cfattach hilkbd_ca = {
84 sizeof(struct hilkbd_softc), hilkbdprobe, hilkbdattach, hilkbddetach,
85 };
86
87 int hilkbd_enable(void *, int);
88 void hilkbd_set_leds(void *, int);
89 int hilkbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
90
91 const struct wskbd_accessops hilkbd_accessops = {
92 hilkbd_enable,
93 hilkbd_set_leds,
94 hilkbd_ioctl,
95 };
96
97 void hilkbd_cngetc(void *, u_int *, int *);
98 void hilkbd_cnpollc(void *, int);
99 void hilkbd_cnbell(void *, u_int, u_int, u_int);
100
101 const struct wskbd_consops hilkbd_consops = {
102 hilkbd_cngetc,
103 hilkbd_cnpollc,
104 hilkbd_cnbell,
105 };
106
107 struct wskbd_mapdata hilkbd_keymapdata = {
108 hilkbd_keydesctab,
109 #ifdef HILKBD_LAYOUT
110 HILKBD_LAYOUT,
111 #else
112 KB_US,
113 #endif
114 };
115
116 struct wskbd_mapdata hilkbd_keymapdata_ps2 = {
117 hilkbd_keydesctab_ps2,
118 #ifdef HILKBD_LAYOUT
119 HILKBD_LAYOUT,
120 #else
121 KB_US,
122 #endif
123 };
124
125 void hilkbd_bell(struct hil_softc *, u_int, u_int, u_int);
126 void hilkbd_callback(struct hildev_softc *, u_int, u_int8_t *);
127 void hilkbd_decode(struct hilkbd_softc *, u_int8_t, u_int *, int *, int);
128 int hilkbd_is_console(int);
129 void hilkbd_rawrepeat(void *);
130
131 int seen_hilkbd_console;
132
133 int
134 hilkbdprobe(struct device *parent, void *match, void *aux)
135 {
136 struct hil_attach_args *ha = aux;
137
138 if (ha->ha_type != HIL_DEVICE_KEYBOARD &&
139 ha->ha_type != HIL_DEVICE_BUTTONBOX)
140 return (0);
141
142 return (1);
143 }
144
145 void
146 hilkbdattach(struct device *parent, struct device *self, void *aux)
147 {
148 struct hilkbd_softc *sc = (void *)self;
149 struct hil_attach_args *ha = aux;
150 struct wskbddev_attach_args a;
151 u_int8_t layoutcode;
152 int ps2;
153
154 sc->hd_code = ha->ha_code;
155 sc->hd_type = ha->ha_type;
156 sc->hd_infolen = ha->ha_infolen;
157 bcopy(ha->ha_info, sc->hd_info, ha->ha_infolen);
158 sc->hd_fn = hilkbd_callback;
159
160 if (ha->ha_type == HIL_DEVICE_KEYBOARD) {
161
162
163
164
165 layoutcode = ha->ha_id & (MAXHILKBDLAYOUT - 1);
166 #ifndef HILKBD_LAYOUT
167 if (layoutcode < MAXHILKBDLAYOUT &&
168 hilkbd_layouts[layoutcode] != -1)
169 hilkbd_keymapdata.layout =
170 hilkbd_keymapdata_ps2.layout =
171 hilkbd_layouts[layoutcode];
172 #endif
173
174 printf(", layout %x", layoutcode);
175 }
176
177
178
179
180 if (ha->ha_infolen > 2 && (ha->ha_info[1] & HIL_IOB) != 0) {
181
182 sc->sc_numleds = (ha->ha_info[2] & HILIOB_PMASK) >> 4;
183 if (sc->sc_numleds != 0)
184 printf(", %d leds", sc->sc_numleds);
185 }
186
187 printf("\n");
188
189
190
191
192
193
194
195
196
197 ps2 = (sc->sc_numleds != 0);
198
199 #ifdef WSDISPLAY_COMPAT_RAWKBD
200 timeout_set(&sc->sc_rawrepeat_ch, hilkbd_rawrepeat, sc);
201 #endif
202
203
204 if (ha->ha_type == HIL_DEVICE_BUTTONBOX)
205 a.console = 0;
206 else
207 a.console = hilkbd_is_console(ha->ha_console);
208 a.keymap = ps2 ? &hilkbd_keymapdata_ps2 : &hilkbd_keymapdata;
209 a.accessops = &hilkbd_accessops;
210 a.accesscookie = sc;
211
212 if (a.console) {
213 sc->sc_console = sc->sc_enabled = 1;
214 wskbd_cnattach(&hilkbd_consops, sc, a.keymap);
215 } else {
216 sc->sc_console = sc->sc_enabled = 0;
217 }
218
219 sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
220
221
222
223
224
225
226 if (!ps2 && sc->sc_wskbddev != NULL) {
227 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, 80);
228 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_UP, 80);
229 }
230 }
231
232 int
233 hilkbddetach(struct device *self, int flags)
234 {
235 struct hilkbd_softc *sc = (void *)self;
236
237
238
239
240
241 if (sc->sc_console) {
242 wskbd_cndetach();
243 seen_hilkbd_console = 0;
244 }
245
246 if (sc->sc_wskbddev != NULL)
247 return config_detach(sc->sc_wskbddev, flags);
248
249 return (0);
250 }
251
252 int
253 hilkbd_enable(void *v, int on)
254 {
255 struct hilkbd_softc *sc = v;
256
257 if (on) {
258 if (sc->sc_enabled)
259 return (EBUSY);
260 } else {
261 if (sc->sc_console)
262 return (EBUSY);
263 }
264
265 sc->sc_enabled = on;
266
267 return (0);
268 }
269
270 void
271 hilkbd_set_leds(void *v, int leds)
272 {
273 struct hilkbd_softc *sc = v;
274 int changemask;
275
276 if (sc->sc_numleds == 0)
277 return;
278
279 changemask = leds ^ sc->sc_ledstate;
280 if (changemask == 0)
281 return;
282
283
284 if (changemask & WSKBD_LED_SCROLL)
285 send_hildev_cmd((struct hildev_softc *)sc,
286 (leds & WSKBD_LED_SCROLL) ? HIL_PROMPT1 : HIL_ACK1,
287 NULL, NULL);
288 if (changemask & WSKBD_LED_NUM)
289 send_hildev_cmd((struct hildev_softc *)sc,
290 (leds & WSKBD_LED_NUM) ? HIL_PROMPT2 : HIL_ACK2,
291 NULL, NULL);
292 if (changemask & WSKBD_LED_CAPS)
293 send_hildev_cmd((struct hildev_softc *)sc,
294 (leds & WSKBD_LED_CAPS) ? HIL_PROMPT3 : HIL_ACK3,
295 NULL, NULL);
296
297 sc->sc_ledstate = leds;
298 }
299
300 int
301 hilkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
302 {
303 struct hilkbd_softc *sc = v;
304
305 switch (cmd) {
306 case WSKBDIO_GTYPE:
307 *(int *)data = WSKBD_TYPE_HIL;
308 return 0;
309 case WSKBDIO_SETLEDS:
310 hilkbd_set_leds(v, *(int *)data);
311 return 0;
312 case WSKBDIO_GETLEDS:
313 *(int *)data = sc->sc_ledstate;
314 return 0;
315 #ifdef WSDISPLAY_COMPAT_RAWKBD
316 case WSKBDIO_SETMODE:
317 sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
318 timeout_del(&sc->sc_rawrepeat_ch);
319 return 0;
320 #endif
321 case WSKBDIO_COMPLEXBELL:
322 #define d ((struct wskbd_bell_data *)data)
323 hilkbd_bell((struct hil_softc *)sc->hd_parent,
324 d->pitch, d->period, d->volume);
325 #undef d
326 return 0;
327 }
328
329 return -1;
330 }
331
332 void
333 hilkbd_cngetc(void *v, u_int *type, int *data)
334 {
335 struct hilkbd_softc *sc = v;
336 u_int8_t c, stat;
337
338 for (;;) {
339 while (hil_poll_data((struct hildev_softc *)sc, &stat, &c) != 0)
340 ;
341
342
343
344
345
346 if (c != HIL_KBDBUTTON)
347 break;
348 }
349
350 hilkbd_decode(sc, c, type, data, HIL_KBDBUTTON);
351 }
352
353 void
354 hilkbd_cnpollc(void *v, int on)
355 {
356 struct hilkbd_softc *sc = v;
357
358 hil_set_poll((struct hil_softc *)sc->hd_parent, on);
359 }
360
361 void
362 hilkbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
363 {
364 struct hilkbd_softc *sc = v;
365
366 hilkbd_bell((struct hil_softc *)sc->hd_parent,
367 pitch, period, volume);
368 }
369
370 void
371 hilkbd_bell(struct hil_softc *sc, u_int pitch, u_int period, u_int volume)
372 {
373 u_int8_t buf[2];
374
375
376 #define BELLDUR 80
377 #define BELLFREQ 8
378 buf[0] = ar_format(period - 10);
379 buf[1] = BELLFREQ;
380 send_hil_cmd(sc, HIL_SETTONE, buf, 2, NULL);
381 }
382
383 void
384 hilkbd_callback(struct hildev_softc *dev, u_int buflen, u_int8_t *buf)
385 {
386 struct hilkbd_softc *sc = (struct hilkbd_softc *)dev;
387 u_int type;
388 int kbdtype, key;
389 int i, s;
390
391
392
393
394 if (sc->sc_enabled == 0)
395 return;
396
397 if (buflen == 0)
398 return;
399 switch ((kbdtype = *buf & HIL_KBDDATA)) {
400 case HIL_BUTTONBOX:
401 case HIL_KBDBUTTON:
402 break;
403 default:
404 return;
405 }
406
407 #ifdef WSDISPLAY_COMPAT_RAWKBD
408 if (sc->sc_rawkbd) {
409 u_char cbuf[HILBUFSIZE * 2];
410 int c, j, npress;
411
412 npress = j = 0;
413 for (i = 1, buf++; i < buflen; i++) {
414 hilkbd_decode(sc, *buf++, &type, &key, kbdtype);
415 c = hilkbd_raw[key];
416 if (c == RAWKEY_Null)
417 continue;
418
419 if (c & 0x80)
420 cbuf[j++] = 0xe0;
421 cbuf[j] = c & 0x7f;
422 if (type == WSCONS_EVENT_KEY_UP)
423 cbuf[j] |= 0x80;
424 else {
425
426 if (c & 0x80)
427 sc->sc_rep[npress++] = 0xe0;
428 sc->sc_rep[npress++] = c & 0x7f;
429 }
430 j++;
431 }
432
433 s = spltty();
434 wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
435 splx(s);
436 timeout_del(&sc->sc_rawrepeat_ch);
437 sc->sc_nrep = npress;
438 if (npress != 0) {
439 timeout_add(&sc->sc_rawrepeat_ch,
440 (hz * REP_DELAY1) / 1000);
441 }
442 } else
443 #endif
444 {
445 s = spltty();
446 for (i = 1, buf++; i < buflen; i++) {
447 hilkbd_decode(sc, *buf++, &type, &key, kbdtype);
448 if (sc->sc_wskbddev != NULL)
449 wskbd_input(sc->sc_wskbddev, type, key);
450 }
451 splx(s);
452 }
453 }
454
455 void
456 hilkbd_decode(struct hilkbd_softc *sc, u_int8_t data, u_int *type, int *key,
457 int kbdtype)
458 {
459 if (kbdtype == HIL_BUTTONBOX) {
460 if (data == 0x02)
461 data = sc->sc_lastarrow;
462 else if (data >= 0xf8)
463 sc->sc_lastarrow = data;
464 }
465
466 *type = (data & 1) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
467 *key = data >> 1;
468 }
469
470 int
471 hilkbd_is_console(int hil_is_console)
472 {
473
474 if (seen_hilkbd_console)
475 return (0);
476
477
478 if (hil_is_console == 0)
479 return (0);
480
481 seen_hilkbd_console = 1;
482 return (1);
483 }
484
485 #ifdef WSDISPLAY_COMPAT_RAWKBD
486 void
487 hilkbd_rawrepeat(void *v)
488 {
489 struct hilkbd_softc *sc = v;
490 int s;
491
492 s = spltty();
493 wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
494 splx(s);
495 timeout_add(&sc->sc_rawrepeat_ch, (hz * REP_DELAYN) / 1000);
496 }
497 #endif