zkbd.c revision 1.16 1 1.16 tsutsui /* $NetBSD: zkbd.c,v 1.16 2012/01/29 10:12:42 tsutsui Exp $ */
2 1.1 ober /* $OpenBSD: zaurus_kbd.c,v 1.28 2005/12/21 20:36:03 deraadt Exp $ */
3 1.1 ober
4 1.1 ober /*
5 1.1 ober * Copyright (c) 2005 Dale Rahn <drahn (at) openbsd.org>
6 1.1 ober *
7 1.1 ober * Permission to use, copy, modify, and distribute this software for any
8 1.1 ober * purpose with or without fee is hereby granted, provided that the above
9 1.1 ober * copyright notice and this permission notice appear in all copies.
10 1.1 ober *
11 1.1 ober * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 ober * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 ober * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 ober * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 ober * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 ober * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 ober * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 ober */
19 1.1 ober
20 1.1 ober #include <sys/cdefs.h>
21 1.16 tsutsui __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.16 2012/01/29 10:12:42 tsutsui Exp $");
22 1.1 ober
23 1.1 ober #include "opt_wsdisplay_compat.h"
24 1.1 ober #if 0 /* XXX */
25 1.1 ober #include "apm.h"
26 1.1 ober #endif
27 1.15 tsutsui #include "lcdctl.h"
28 1.1 ober
29 1.1 ober #include <sys/param.h>
30 1.1 ober #include <sys/systm.h>
31 1.1 ober #include <sys/device.h>
32 1.1 ober #include <sys/malloc.h>
33 1.1 ober #include <sys/kernel.h>
34 1.1 ober #include <sys/proc.h>
35 1.1 ober #include <sys/signalvar.h>
36 1.1 ober #include <sys/callout.h>
37 1.1 ober
38 1.1 ober #include <arm/xscale/pxa2x0reg.h>
39 1.1 ober #include <arm/xscale/pxa2x0_gpio.h>
40 1.1 ober
41 1.1 ober #include <dev/wscons/wsconsio.h>
42 1.1 ober #include <dev/wscons/wskbdvar.h>
43 1.1 ober #include <dev/wscons/wsksymdef.h>
44 1.1 ober #include <dev/wscons/wsksymvar.h>
45 1.1 ober
46 1.12 nonaka #include <zaurus/zaurus/zaurus_var.h>
47 1.1 ober #include <zaurus/dev/zkbdmap.h>
48 1.15 tsutsui #if NLCDCTL > 0
49 1.15 tsutsui #include <zaurus/dev/lcdctlvar.h>
50 1.15 tsutsui #endif
51 1.1 ober
52 1.1 ober static const int gpio_sense_pins_c3000[] = {
53 1.1 ober 12,
54 1.1 ober 17,
55 1.1 ober 91,
56 1.1 ober 34,
57 1.1 ober 36,
58 1.1 ober 38,
59 1.1 ober 39,
60 1.1 ober -1
61 1.1 ober };
62 1.1 ober
63 1.1 ober static const int gpio_strobe_pins_c3000[] = {
64 1.1 ober 88,
65 1.1 ober 23,
66 1.1 ober 24,
67 1.1 ober 25,
68 1.1 ober 26,
69 1.1 ober 27,
70 1.1 ober 52,
71 1.1 ober 103,
72 1.1 ober 107,
73 1.1 ober -1,
74 1.1 ober 108,
75 1.1 ober 114
76 1.1 ober };
77 1.1 ober
78 1.16 tsutsui static const int gpio_sense_pins_c860[] = {
79 1.16 tsutsui 58,
80 1.16 tsutsui 59,
81 1.16 tsutsui 60,
82 1.16 tsutsui 61,
83 1.16 tsutsui 62,
84 1.16 tsutsui 63,
85 1.16 tsutsui 64,
86 1.16 tsutsui 65
87 1.16 tsutsui };
88 1.16 tsutsui
89 1.16 tsutsui static const int gpio_strobe_pins_c860[] = {
90 1.16 tsutsui 66,
91 1.16 tsutsui 67,
92 1.16 tsutsui 68,
93 1.16 tsutsui 69,
94 1.16 tsutsui 70,
95 1.16 tsutsui 71,
96 1.16 tsutsui 72,
97 1.16 tsutsui 73,
98 1.16 tsutsui 74,
99 1.16 tsutsui 75,
100 1.16 tsutsui 76,
101 1.16 tsutsui 77
102 1.16 tsutsui };
103 1.16 tsutsui
104 1.1 ober static const int stuck_keys[] = {
105 1.1 ober 7,
106 1.1 ober 15,
107 1.1 ober 23,
108 1.1 ober 31
109 1.1 ober };
110 1.1 ober
111 1.1 ober #define REP_DELAY1 400
112 1.1 ober #define REP_DELAYN 100
113 1.1 ober
114 1.1 ober struct zkbd_softc {
115 1.8 nonaka device_t sc_dev;
116 1.1 ober
117 1.1 ober const int *sc_sense_array;
118 1.1 ober const int *sc_strobe_array;
119 1.16 tsutsui const int *sc_stuck_keys;
120 1.1 ober int sc_nsense;
121 1.1 ober int sc_nstrobe;
122 1.16 tsutsui int sc_nstuck;
123 1.1 ober
124 1.1 ober short sc_onkey_pin;
125 1.1 ober short sc_sync_pin;
126 1.1 ober short sc_swa_pin;
127 1.1 ober short sc_swb_pin;
128 1.1 ober char *sc_okeystate;
129 1.1 ober char *sc_keystate;
130 1.1 ober char sc_hinge; /* 0=open, 1=nonsense, 2=backwards, 3=closed */
131 1.1 ober char sc_maxkbdcol;
132 1.1 ober
133 1.1 ober struct callout sc_roll_to;
134 1.1 ober
135 1.1 ober /* console stuff */
136 1.1 ober int sc_polling;
137 1.1 ober int sc_pollUD;
138 1.1 ober int sc_pollkey;
139 1.1 ober
140 1.1 ober /* wskbd bits */
141 1.2 peter struct device *sc_wskbddev;
142 1.16 tsutsui struct wskbd_mapdata *sc_keymapdata;
143 1.1 ober int sc_rawkbd;
144 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
145 1.1 ober const char *sc_xt_keymap;
146 1.1 ober struct callout sc_rawrepeat_ch;
147 1.1 ober #define MAXKEYS 20
148 1.1 ober char sc_rep[MAXKEYS];
149 1.1 ober int sc_nrep;
150 1.1 ober #endif
151 1.1 ober };
152 1.1 ober
153 1.2 peter static struct zkbd_softc *zkbd_sc;
154 1.1 ober
155 1.8 nonaka static int zkbd_match(device_t, cfdata_t, void *);
156 1.8 nonaka static void zkbd_attach(device_t, device_t, void *);
157 1.1 ober
158 1.8 nonaka CFATTACH_DECL_NEW(zkbd, sizeof(struct zkbd_softc),
159 1.1 ober zkbd_match, zkbd_attach, NULL, NULL);
160 1.1 ober
161 1.1 ober static int zkbd_irq(void *v);
162 1.1 ober static void zkbd_poll(void *v);
163 1.1 ober static int zkbd_on(void *v);
164 1.1 ober static int zkbd_sync(void *v);
165 1.1 ober static int zkbd_hinge(void *v);
166 1.11 dyoung static bool zkbd_resume(device_t dv, const pmf_qual_t *);
167 1.1 ober
168 1.1 ober int zkbd_modstate;
169 1.1 ober
170 1.1 ober static int zkbd_enable(void *, int);
171 1.1 ober static void zkbd_set_leds(void *, int);
172 1.3 christos static int zkbd_ioctl(void *, u_long, void *, int, struct lwp *);
173 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
174 1.1 ober static void zkbd_rawrepeat(void *v);
175 1.1 ober #endif
176 1.1 ober
177 1.2 peter static struct wskbd_accessops zkbd_accessops = {
178 1.1 ober zkbd_enable,
179 1.1 ober zkbd_set_leds,
180 1.1 ober zkbd_ioctl,
181 1.1 ober };
182 1.1 ober
183 1.1 ober static void zkbd_cngetc(void *, u_int *, int *);
184 1.1 ober static void zkbd_cnpollc(void *, int);
185 1.1 ober
186 1.2 peter static struct wskbd_consops zkbd_consops = {
187 1.1 ober zkbd_cngetc,
188 1.1 ober zkbd_cnpollc,
189 1.1 ober };
190 1.1 ober
191 1.2 peter static struct wskbd_mapdata zkbd_keymapdata = {
192 1.1 ober zkbd_keydesctab,
193 1.1 ober KB_US,
194 1.1 ober };
195 1.1 ober
196 1.16 tsutsui static struct wskbd_mapdata zkbd_keymapdata_c860 = {
197 1.16 tsutsui zkbd_keydesctab_c860,
198 1.16 tsutsui KB_US,
199 1.16 tsutsui };
200 1.16 tsutsui
201 1.1 ober static int
202 1.8 nonaka zkbd_match(device_t parent, cfdata_t cf, void *aux)
203 1.1 ober {
204 1.1 ober
205 1.4 nonaka if (zkbd_sc)
206 1.4 nonaka return 0;
207 1.4 nonaka
208 1.1 ober return 1;
209 1.1 ober }
210 1.1 ober
211 1.1 ober static void
212 1.8 nonaka zkbd_attach(device_t parent, device_t self, void *aux)
213 1.1 ober {
214 1.8 nonaka struct zkbd_softc *sc = device_private(self);
215 1.1 ober struct wskbddev_attach_args a;
216 1.1 ober int pin, i;
217 1.1 ober
218 1.8 nonaka sc->sc_dev = self;
219 1.2 peter zkbd_sc = sc;
220 1.4 nonaka
221 1.8 nonaka aprint_normal("\n");
222 1.8 nonaka aprint_naive("\n");
223 1.4 nonaka
224 1.1 ober sc->sc_polling = 0;
225 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
226 1.1 ober sc->sc_rawkbd = 0;
227 1.1 ober #endif
228 1.1 ober
229 1.6 nonaka callout_init(&sc->sc_roll_to, 0);
230 1.6 nonaka callout_setfunc(&sc->sc_roll_to, zkbd_poll, sc);
231 1.6 nonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
232 1.6 nonaka callout_init(&sc->sc_rawrepeat_ch, 0);
233 1.6 nonaka callout_setfunc(&sc->sc_rawrepeat_ch, zkbd_rawrepeat, sc);
234 1.6 nonaka #endif
235 1.6 nonaka
236 1.12 nonaka if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
237 1.1 ober sc->sc_sense_array = gpio_sense_pins_c3000;
238 1.1 ober sc->sc_strobe_array = gpio_strobe_pins_c3000;
239 1.2 peter sc->sc_nsense = __arraycount(gpio_sense_pins_c3000);
240 1.2 peter sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c3000);
241 1.16 tsutsui sc->sc_stuck_keys = stuck_keys;
242 1.16 tsutsui sc->sc_nstuck = __arraycount(stuck_keys);
243 1.1 ober sc->sc_maxkbdcol = 10;
244 1.1 ober sc->sc_onkey_pin = 95;
245 1.1 ober sc->sc_sync_pin = 16;
246 1.1 ober sc->sc_swa_pin = 97;
247 1.1 ober sc->sc_swb_pin = 96;
248 1.16 tsutsui sc->sc_keymapdata = &zkbd_keymapdata;
249 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
250 1.1 ober sc->sc_xt_keymap = xt_keymap;
251 1.1 ober #endif
252 1.16 tsutsui } else if (ZAURUS_ISC860) {
253 1.16 tsutsui sc->sc_sense_array = gpio_sense_pins_c860;
254 1.16 tsutsui sc->sc_strobe_array = gpio_strobe_pins_c860;
255 1.16 tsutsui sc->sc_nsense = __arraycount(gpio_sense_pins_c860);
256 1.16 tsutsui sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c860);
257 1.16 tsutsui sc->sc_stuck_keys = NULL;
258 1.16 tsutsui sc->sc_nstuck = 0;
259 1.16 tsutsui sc->sc_maxkbdcol = 0;
260 1.16 tsutsui sc->sc_onkey_pin = -1;
261 1.16 tsutsui sc->sc_sync_pin = -1;
262 1.16 tsutsui sc->sc_swa_pin = -1;
263 1.16 tsutsui sc->sc_swb_pin = -1;
264 1.16 tsutsui sc->sc_keymapdata = &zkbd_keymapdata_c860;
265 1.16 tsutsui #ifdef WSDISPLAY_COMPAT_RAWKBD
266 1.16 tsutsui sc->sc_xt_keymap = xt_keymap_c860;
267 1.16 tsutsui #endif
268 1.4 nonaka } else {
269 1.4 nonaka /* XXX */
270 1.4 nonaka return;
271 1.4 nonaka }
272 1.4 nonaka
273 1.9 nonaka if (!pmf_device_register(sc->sc_dev, NULL, zkbd_resume))
274 1.9 nonaka aprint_error_dev(sc->sc_dev,
275 1.9 nonaka "couldn't establish power handler\n");
276 1.1 ober
277 1.1 ober sc->sc_okeystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
278 1.1 ober M_DEVBUF, M_NOWAIT);
279 1.2 peter memset(sc->sc_okeystate, 0, sc->sc_nsense * sc->sc_nstrobe);
280 1.1 ober
281 1.1 ober sc->sc_keystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
282 1.1 ober M_DEVBUF, M_NOWAIT);
283 1.2 peter memset(sc->sc_keystate, 0, sc->sc_nsense * sc->sc_nstrobe);
284 1.1 ober
285 1.1 ober /* set all the strobe bits */
286 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
287 1.1 ober pin = sc->sc_strobe_array[i];
288 1.4 nonaka if (pin == -1)
289 1.1 ober continue;
290 1.1 ober pxa2x0_gpio_set_function(pin, GPIO_SET|GPIO_OUT);
291 1.1 ober }
292 1.2 peter
293 1.1 ober /* set all the sense bits */
294 1.1 ober for (i = 0; i < sc->sc_nsense; i++) {
295 1.1 ober pin = sc->sc_sense_array[i];
296 1.4 nonaka if (pin == -1)
297 1.1 ober continue;
298 1.1 ober pxa2x0_gpio_set_function(pin, GPIO_IN);
299 1.1 ober pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH, IPL_TTY,
300 1.1 ober zkbd_irq, sc);
301 1.1 ober }
302 1.2 peter
303 1.16 tsutsui if (sc->sc_onkey_pin >= 0)
304 1.16 tsutsui pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH,
305 1.16 tsutsui IPL_TTY, zkbd_on, sc);
306 1.16 tsutsui if (sc->sc_sync_pin >= 0)
307 1.16 tsutsui pxa2x0_gpio_intr_establish(sc->sc_sync_pin, IST_EDGE_RISING,
308 1.16 tsutsui IPL_TTY, zkbd_sync, sc);
309 1.16 tsutsui if (sc->sc_swa_pin >= 0)
310 1.16 tsutsui pxa2x0_gpio_intr_establish(sc->sc_swa_pin, IST_EDGE_BOTH,
311 1.16 tsutsui IPL_TTY, zkbd_hinge, sc);
312 1.16 tsutsui if (sc->sc_swb_pin >= 0)
313 1.16 tsutsui pxa2x0_gpio_intr_establish(sc->sc_swb_pin, IST_EDGE_BOTH,
314 1.16 tsutsui IPL_TTY, zkbd_hinge, sc);
315 1.1 ober
316 1.1 ober if (glass_console) {
317 1.16 tsutsui wskbd_cnattach(&zkbd_consops, sc, sc->sc_keymapdata);
318 1.1 ober a.console = 1;
319 1.1 ober } else {
320 1.1 ober a.console = 0;
321 1.1 ober }
322 1.16 tsutsui a.keymap = sc->sc_keymapdata;
323 1.1 ober a.accessops = &zkbd_accessops;
324 1.1 ober a.accesscookie = sc;
325 1.1 ober
326 1.1 ober zkbd_hinge(sc); /* to initialize sc_hinge */
327 1.1 ober
328 1.1 ober sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
329 1.1 ober }
330 1.1 ober
331 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
332 1.1 ober static void
333 1.1 ober zkbd_rawrepeat(void *v)
334 1.1 ober {
335 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
336 1.1 ober int s;
337 1.1 ober
338 1.1 ober s = spltty();
339 1.1 ober wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
340 1.1 ober splx(s);
341 1.1 ober callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
342 1.1 ober }
343 1.1 ober #endif
344 1.1 ober
345 1.1 ober /* XXX only deal with keys that can be pressed when display is open? */
346 1.1 ober /* XXX are some not in the array? */
347 1.1 ober /* handle keypress interrupt */
348 1.1 ober static int
349 1.1 ober zkbd_irq(void *v)
350 1.1 ober {
351 1.1 ober
352 1.1 ober zkbd_poll(v);
353 1.1 ober
354 1.1 ober return 1;
355 1.1 ober }
356 1.1 ober
357 1.1 ober static void
358 1.1 ober zkbd_poll(void *v)
359 1.1 ober {
360 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
361 1.2 peter int i, j, col, pin, type, keysdown = 0;
362 1.14 nonaka int stuck;
363 1.1 ober int keystate;
364 1.2 peter int s;
365 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
366 1.14 nonaka int npress = 0, ncbuf = 0, c;
367 1.2 peter char cbuf[MAXKEYS * 2];
368 1.1 ober #endif
369 1.1 ober
370 1.1 ober s = spltty();
371 1.1 ober
372 1.1 ober /* discharge all */
373 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
374 1.1 ober pin = sc->sc_strobe_array[i];
375 1.4 nonaka if (pin == -1)
376 1.4 nonaka continue;
377 1.4 nonaka pxa2x0_gpio_clear_bit(pin);
378 1.4 nonaka pxa2x0_gpio_set_dir(pin, GPIO_IN);
379 1.1 ober }
380 1.1 ober
381 1.2 peter delay(10);
382 1.2 peter for (col = 0; col < sc->sc_nstrobe; col++) {
383 1.2 peter pin = sc->sc_strobe_array[col];
384 1.2 peter if (pin == -1)
385 1.1 ober continue;
386 1.1 ober
387 1.1 ober /* activate_col */
388 1.1 ober pxa2x0_gpio_set_bit(pin);
389 1.1 ober pxa2x0_gpio_set_dir(pin, GPIO_OUT);
390 1.1 ober
391 1.1 ober /* wait activate delay */
392 1.1 ober delay(10);
393 1.1 ober
394 1.1 ober /* read row */
395 1.1 ober for (i = 0; i < sc->sc_nsense; i++) {
396 1.1 ober int bit;
397 1.1 ober
398 1.4 nonaka if (sc->sc_sense_array[i] == -1)
399 1.1 ober continue;
400 1.1 ober bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
401 1.1 ober if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
402 1.1 ober continue;
403 1.1 ober sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
404 1.1 ober }
405 1.1 ober
406 1.1 ober /* reset_col */
407 1.1 ober pxa2x0_gpio_set_dir(pin, GPIO_IN);
408 1.2 peter
409 1.1 ober /* wait discharge delay */
410 1.1 ober delay(10);
411 1.1 ober }
412 1.2 peter
413 1.1 ober /* charge all */
414 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
415 1.1 ober pin = sc->sc_strobe_array[i];
416 1.4 nonaka if (pin == -1)
417 1.4 nonaka continue;
418 1.4 nonaka pxa2x0_gpio_set_bit(pin);
419 1.4 nonaka pxa2x0_gpio_set_dir(pin, GPIO_OUT);
420 1.1 ober }
421 1.1 ober
422 1.1 ober /* force the irqs to clear as we have just played with them. */
423 1.2 peter for (i = 0; i < sc->sc_nsense; i++) {
424 1.4 nonaka pin = sc->sc_sense_array[i];
425 1.4 nonaka if (pin == -1)
426 1.4 nonaka continue;
427 1.4 nonaka pxa2x0_gpio_clear_intr(pin);
428 1.2 peter }
429 1.1 ober
430 1.1 ober /* process after resetting interrupt */
431 1.1 ober zkbd_modstate = (
432 1.1 ober (sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
433 1.1 ober (sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
434 1.1 ober (sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */
435 1.1 ober
436 1.2 peter for (i = 0; i < sc->sc_nsense * sc->sc_nstrobe; i++) {
437 1.14 nonaka stuck = 0;
438 1.1 ober /* extend xt_keymap to do this faster. */
439 1.1 ober /* ignore 'stuck' keys' */
440 1.16 tsutsui for (j = 0; j < sc->sc_nstuck; j++) {
441 1.16 tsutsui if (sc->sc_stuck_keys[j] == i) {
442 1.2 peter stuck = 1;
443 1.1 ober break;
444 1.1 ober }
445 1.1 ober }
446 1.1 ober if (stuck)
447 1.1 ober continue;
448 1.2 peter
449 1.1 ober keystate = sc->sc_keystate[i];
450 1.1 ober keysdown |= keystate; /* if any keys held */
451 1.1 ober
452 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
453 1.14 nonaka if (sc->sc_polling == 0 && sc->sc_rawkbd) {
454 1.14 nonaka if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
455 1.14 nonaka c = sc->sc_xt_keymap[i];
456 1.1 ober if (c & 0x80) {
457 1.1 ober cbuf[ncbuf++] = 0xe0;
458 1.1 ober }
459 1.1 ober cbuf[ncbuf] = c & 0x7f;
460 1.1 ober
461 1.1 ober if (keystate) {
462 1.1 ober if (c & 0x80) {
463 1.1 ober sc->sc_rep[npress++] = 0xe0;
464 1.1 ober }
465 1.1 ober sc->sc_rep[npress++] = c & 0x7f;
466 1.1 ober } else {
467 1.1 ober cbuf[ncbuf] |= 0x80;
468 1.1 ober }
469 1.1 ober ncbuf++;
470 1.1 ober sc->sc_okeystate[i] = keystate;
471 1.1 ober }
472 1.1 ober }
473 1.1 ober #endif
474 1.1 ober
475 1.14 nonaka if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
476 1.1 ober type = keystate ? WSCONS_EVENT_KEY_DOWN :
477 1.1 ober WSCONS_EVENT_KEY_UP;
478 1.1 ober
479 1.1 ober if (sc->sc_polling) {
480 1.1 ober sc->sc_pollkey = i;
481 1.1 ober sc->sc_pollUD = type;
482 1.1 ober } else {
483 1.1 ober wskbd_input(sc->sc_wskbddev, type, i);
484 1.1 ober }
485 1.1 ober
486 1.1 ober sc->sc_okeystate[i] = keystate;
487 1.1 ober }
488 1.1 ober }
489 1.1 ober
490 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
491 1.14 nonaka if (sc->sc_polling == 0 && sc->sc_rawkbd) {
492 1.1 ober wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
493 1.1 ober sc->sc_nrep = npress;
494 1.1 ober if (npress != 0)
495 1.1 ober callout_schedule(&sc->sc_rawrepeat_ch,
496 1.1 ober hz * REP_DELAY1 / 1000);
497 1.1 ober else
498 1.1 ober callout_stop(&sc->sc_rawrepeat_ch);
499 1.1 ober }
500 1.1 ober #endif
501 1.1 ober if (keysdown)
502 1.1 ober callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
503 1.1 ober else
504 1.1 ober callout_stop(&sc->sc_roll_to); /* always cancel? */
505 1.1 ober
506 1.1 ober splx(s);
507 1.1 ober }
508 1.1 ober
509 1.1 ober #if NAPM > 0
510 1.1 ober extern int kbd_reset;
511 1.1 ober extern int apm_suspends;
512 1.1 ober static int zkbdondown; /* on key is pressed */
513 1.1 ober static struct timeval zkbdontv = { 0, 0 }; /* last on key event */
514 1.1 ober const struct timeval zkbdhalttv = { 3, 0 }; /* 3s for safe shutdown */
515 1.1 ober const struct timeval zkbdsleeptv = { 0, 250000 }; /* .25s for suspend */
516 1.1 ober extern int lid_suspend;
517 1.1 ober #endif
518 1.1 ober
519 1.1 ober static int
520 1.1 ober zkbd_on(void *v)
521 1.1 ober {
522 1.1 ober #if NAPM > 0
523 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
524 1.16 tsutsui int down;
525 1.16 tsutsui
526 1.16 tsutsui if (sc->sc_onkey_pin < 0)
527 1.16 tsutsui return 1;
528 1.16 tsutsui
529 1.16 tsutsui down = pxa2x0_gpio_get_bit(sc->sc_onkey_pin) ? 1 : 0;
530 1.1 ober
531 1.1 ober /*
532 1.1 ober * Change run mode depending on how long the key is held down.
533 1.1 ober * Ignore the key if it gets pressed while the lid is closed.
534 1.1 ober *
535 1.1 ober * Keys can bounce and we have to work around missed interrupts.
536 1.1 ober * Only the second edge is detected upon exit from sleep mode.
537 1.1 ober */
538 1.1 ober if (down) {
539 1.1 ober if (sc->sc_hinge == 3) {
540 1.1 ober zkbdondown = 0;
541 1.1 ober } else {
542 1.1 ober microuptime(&zkbdontv);
543 1.1 ober zkbdondown = 1;
544 1.1 ober }
545 1.1 ober } else if (zkbdondown) {
546 1.1 ober if (ratecheck(&zkbdontv, &zkbdhalttv)) {
547 1.1 ober if (kbd_reset == 1) {
548 1.1 ober kbd_reset = 0;
549 1.1 ober psignal(initproc, SIGUSR1);
550 1.1 ober }
551 1.1 ober } else if (ratecheck(&zkbdontv, &zkbdsleeptv)) {
552 1.1 ober apm_suspends++;
553 1.1 ober }
554 1.1 ober zkbdondown = 0;
555 1.1 ober }
556 1.1 ober #endif
557 1.1 ober return 1;
558 1.1 ober }
559 1.1 ober
560 1.1 ober static int
561 1.1 ober zkbd_sync(void *v)
562 1.1 ober {
563 1.1 ober
564 1.1 ober return 1;
565 1.1 ober }
566 1.1 ober
567 1.1 ober static int
568 1.1 ober zkbd_hinge(void *v)
569 1.1 ober {
570 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
571 1.16 tsutsui int a, b;
572 1.16 tsutsui
573 1.16 tsutsui if (sc->sc_swa_pin < 0 || sc->sc_swb_pin < 0)
574 1.16 tsutsui return 1;
575 1.16 tsutsui
576 1.16 tsutsui a = pxa2x0_gpio_get_bit(sc->sc_swa_pin) ? 1 : 0;
577 1.16 tsutsui b = pxa2x0_gpio_get_bit(sc->sc_swb_pin) ? 2 : 0;
578 1.1 ober
579 1.1 ober sc->sc_hinge = a | b;
580 1.1 ober
581 1.1 ober if (sc->sc_hinge == 3) {
582 1.1 ober #if NAPM > 0
583 1.1 ober if (lid_suspend)
584 1.1 ober apm_suspends++;
585 1.1 ober #endif
586 1.15 tsutsui #if NLCDCTL > 0
587 1.15 tsutsui lcdctl_blank(true);
588 1.15 tsutsui #endif
589 1.1 ober } else {
590 1.15 tsutsui #if NLCDCTL > 0
591 1.15 tsutsui lcdctl_blank(false);
592 1.15 tsutsui #endif
593 1.1 ober }
594 1.1 ober
595 1.1 ober return 1;
596 1.1 ober }
597 1.1 ober
598 1.1 ober static int
599 1.1 ober zkbd_enable(void *v, int on)
600 1.1 ober {
601 1.1 ober
602 1.1 ober return 0;
603 1.1 ober }
604 1.1 ober
605 1.1 ober void
606 1.1 ober zkbd_set_leds(void *v, int on)
607 1.1 ober {
608 1.1 ober }
609 1.1 ober
610 1.1 ober static int
611 1.3 christos zkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
612 1.1 ober {
613 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
614 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
615 1.1 ober #endif
616 1.1 ober
617 1.1 ober switch (cmd) {
618 1.1 ober case WSKBDIO_GTYPE:
619 1.1 ober *(int *)data = WSKBD_TYPE_ZAURUS;
620 1.1 ober return 0;
621 1.1 ober
622 1.1 ober case WSKBDIO_SETLEDS:
623 1.1 ober return 0;
624 1.1 ober
625 1.1 ober case WSKBDIO_GETLEDS:
626 1.1 ober *(int *)data = 0;
627 1.1 ober return 0;
628 1.1 ober
629 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
630 1.1 ober case WSKBDIO_SETMODE:
631 1.1 ober sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
632 1.1 ober callout_stop(&sc->sc_rawrepeat_ch);
633 1.1 ober return 0;
634 1.1 ober #endif
635 1.1 ober
636 1.1 ober }
637 1.2 peter return EPASSTHROUGH;
638 1.1 ober }
639 1.1 ober
640 1.1 ober /* implement polling for zaurus_kbd */
641 1.1 ober static void
642 1.1 ober zkbd_cngetc(void *v, u_int *type, int *data)
643 1.1 ober {
644 1.2 peter struct zkbd_softc *sc = (struct zkbd_softc *)zkbd_sc;
645 1.1 ober
646 1.1 ober sc->sc_pollkey = -1;
647 1.1 ober sc->sc_pollUD = -1;
648 1.1 ober sc->sc_polling = 1;
649 1.1 ober while (sc->sc_pollkey == -1) {
650 1.2 peter zkbd_poll(sc);
651 1.1 ober DELAY(10000); /* XXX */
652 1.1 ober }
653 1.1 ober sc->sc_polling = 0;
654 1.1 ober *data = sc->sc_pollkey;
655 1.1 ober *type = sc->sc_pollUD;
656 1.1 ober }
657 1.1 ober
658 1.1 ober static void
659 1.1 ober zkbd_cnpollc(void *v, int on)
660 1.1 ober {
661 1.1 ober }
662 1.1 ober
663 1.9 nonaka static bool
664 1.11 dyoung zkbd_resume(device_t dv, const pmf_qual_t *qual)
665 1.1 ober {
666 1.9 nonaka struct zkbd_softc *sc = device_private(dv);
667 1.9 nonaka
668 1.9 nonaka zkbd_hinge(sc);
669 1.1 ober
670 1.9 nonaka return true;
671 1.1 ober }
672