zkbd.c revision 1.8 1 1.8 nonaka /* $NetBSD: zkbd.c,v 1.8 2009/01/29 12:28:15 nonaka 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.8 nonaka __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.8 2009/01/29 12:28:15 nonaka Exp $");
22 1.1 ober
23 1.1 ober #include "opt_wsdisplay_compat.h"
24 1.1 ober #include "lcd.h"
25 1.1 ober #if 0 /* XXX */
26 1.1 ober #include "apm.h"
27 1.1 ober #endif
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.1 ober #include <zaurus/dev/zkbdmap.h>
47 1.1 ober #include <zaurus/zaurus/zaurus_var.h>
48 1.1 ober
49 1.1 ober static const int gpio_sense_pins_c3000[] = {
50 1.1 ober 12,
51 1.1 ober 17,
52 1.1 ober 91,
53 1.1 ober 34,
54 1.1 ober 36,
55 1.1 ober 38,
56 1.1 ober 39,
57 1.1 ober -1
58 1.1 ober };
59 1.1 ober
60 1.1 ober static const int gpio_strobe_pins_c3000[] = {
61 1.1 ober 88,
62 1.1 ober 23,
63 1.1 ober 24,
64 1.1 ober 25,
65 1.1 ober 26,
66 1.1 ober 27,
67 1.1 ober 52,
68 1.1 ober 103,
69 1.1 ober 107,
70 1.1 ober -1,
71 1.1 ober 108,
72 1.1 ober 114
73 1.1 ober };
74 1.1 ober
75 1.1 ober static const int stuck_keys[] = {
76 1.1 ober 7,
77 1.1 ober 15,
78 1.1 ober 23,
79 1.1 ober 31
80 1.1 ober };
81 1.1 ober
82 1.1 ober #define REP_DELAY1 400
83 1.1 ober #define REP_DELAYN 100
84 1.1 ober
85 1.1 ober struct zkbd_softc {
86 1.8 nonaka device_t sc_dev;
87 1.1 ober
88 1.1 ober const int *sc_sense_array;
89 1.1 ober const int *sc_strobe_array;
90 1.1 ober int sc_nsense;
91 1.1 ober int sc_nstrobe;
92 1.1 ober
93 1.1 ober short sc_onkey_pin;
94 1.1 ober short sc_sync_pin;
95 1.1 ober short sc_swa_pin;
96 1.1 ober short sc_swb_pin;
97 1.1 ober char *sc_okeystate;
98 1.1 ober char *sc_keystate;
99 1.1 ober char sc_hinge; /* 0=open, 1=nonsense, 2=backwards, 3=closed */
100 1.1 ober char sc_maxkbdcol;
101 1.1 ober
102 1.1 ober struct callout sc_roll_to;
103 1.1 ober
104 1.1 ober /* console stuff */
105 1.1 ober int sc_polling;
106 1.1 ober int sc_pollUD;
107 1.1 ober int sc_pollkey;
108 1.1 ober
109 1.1 ober /* wskbd bits */
110 1.2 peter struct device *sc_wskbddev;
111 1.1 ober int sc_rawkbd;
112 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
113 1.1 ober const char *sc_xt_keymap;
114 1.1 ober struct callout sc_rawrepeat_ch;
115 1.1 ober #define MAXKEYS 20
116 1.1 ober char sc_rep[MAXKEYS];
117 1.1 ober int sc_nrep;
118 1.1 ober #endif
119 1.1 ober void *sc_powerhook;
120 1.1 ober };
121 1.1 ober
122 1.2 peter static struct zkbd_softc *zkbd_sc;
123 1.1 ober
124 1.8 nonaka static int zkbd_match(device_t, cfdata_t, void *);
125 1.8 nonaka static void zkbd_attach(device_t, device_t, void *);
126 1.1 ober
127 1.8 nonaka CFATTACH_DECL_NEW(zkbd, sizeof(struct zkbd_softc),
128 1.1 ober zkbd_match, zkbd_attach, NULL, NULL);
129 1.1 ober
130 1.1 ober static int zkbd_irq(void *v);
131 1.1 ober static void zkbd_poll(void *v);
132 1.1 ober static int zkbd_on(void *v);
133 1.1 ober static int zkbd_sync(void *v);
134 1.1 ober static int zkbd_hinge(void *v);
135 1.1 ober static void zkbd_power(int why, void *arg);
136 1.1 ober
137 1.1 ober int zkbd_modstate;
138 1.1 ober
139 1.1 ober static int zkbd_enable(void *, int);
140 1.1 ober static void zkbd_set_leds(void *, int);
141 1.3 christos static int zkbd_ioctl(void *, u_long, void *, int, struct lwp *);
142 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
143 1.1 ober static void zkbd_rawrepeat(void *v);
144 1.1 ober #endif
145 1.1 ober
146 1.2 peter static struct wskbd_accessops zkbd_accessops = {
147 1.1 ober zkbd_enable,
148 1.1 ober zkbd_set_leds,
149 1.1 ober zkbd_ioctl,
150 1.1 ober };
151 1.1 ober
152 1.1 ober static void zkbd_cngetc(void *, u_int *, int *);
153 1.1 ober static void zkbd_cnpollc(void *, int);
154 1.1 ober
155 1.2 peter static struct wskbd_consops zkbd_consops = {
156 1.1 ober zkbd_cngetc,
157 1.1 ober zkbd_cnpollc,
158 1.1 ober };
159 1.1 ober
160 1.2 peter static struct wskbd_mapdata zkbd_keymapdata = {
161 1.1 ober zkbd_keydesctab,
162 1.1 ober KB_US,
163 1.1 ober };
164 1.1 ober
165 1.1 ober static int
166 1.8 nonaka zkbd_match(device_t parent, cfdata_t cf, void *aux)
167 1.1 ober {
168 1.1 ober
169 1.4 nonaka if (zkbd_sc)
170 1.4 nonaka return 0;
171 1.4 nonaka
172 1.1 ober return 1;
173 1.1 ober }
174 1.1 ober
175 1.1 ober static void
176 1.8 nonaka zkbd_attach(device_t parent, device_t self, void *aux)
177 1.1 ober {
178 1.8 nonaka struct zkbd_softc *sc = device_private(self);
179 1.1 ober struct wskbddev_attach_args a;
180 1.1 ober int pin, i;
181 1.1 ober
182 1.8 nonaka sc->sc_dev = self;
183 1.2 peter zkbd_sc = sc;
184 1.4 nonaka
185 1.8 nonaka aprint_normal("\n");
186 1.8 nonaka aprint_naive("\n");
187 1.4 nonaka
188 1.1 ober sc->sc_polling = 0;
189 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
190 1.1 ober sc->sc_rawkbd = 0;
191 1.1 ober #endif
192 1.1 ober
193 1.6 nonaka callout_init(&sc->sc_roll_to, 0);
194 1.6 nonaka callout_setfunc(&sc->sc_roll_to, zkbd_poll, sc);
195 1.6 nonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
196 1.6 nonaka callout_init(&sc->sc_rawrepeat_ch, 0);
197 1.6 nonaka callout_setfunc(&sc->sc_rawrepeat_ch, zkbd_rawrepeat, sc);
198 1.6 nonaka #endif
199 1.6 nonaka
200 1.4 nonaka if (ZAURUS_ISC3000) {
201 1.1 ober sc->sc_sense_array = gpio_sense_pins_c3000;
202 1.1 ober sc->sc_strobe_array = gpio_strobe_pins_c3000;
203 1.2 peter sc->sc_nsense = __arraycount(gpio_sense_pins_c3000);
204 1.2 peter sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c3000);
205 1.1 ober sc->sc_maxkbdcol = 10;
206 1.1 ober sc->sc_onkey_pin = 95;
207 1.1 ober sc->sc_sync_pin = 16;
208 1.1 ober sc->sc_swa_pin = 97;
209 1.1 ober sc->sc_swb_pin = 96;
210 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
211 1.1 ober sc->sc_xt_keymap = xt_keymap;
212 1.1 ober #endif
213 1.4 nonaka } else {
214 1.4 nonaka /* XXX */
215 1.4 nonaka return;
216 1.4 nonaka }
217 1.4 nonaka
218 1.8 nonaka sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev),
219 1.4 nonaka zkbd_power, sc);
220 1.4 nonaka if (sc->sc_powerhook == NULL) {
221 1.8 nonaka aprint_error_dev(sc->sc_dev, "unable to establish powerhook\n");
222 1.4 nonaka return;
223 1.4 nonaka }
224 1.1 ober
225 1.1 ober sc->sc_okeystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
226 1.1 ober M_DEVBUF, M_NOWAIT);
227 1.2 peter memset(sc->sc_okeystate, 0, sc->sc_nsense * sc->sc_nstrobe);
228 1.1 ober
229 1.1 ober sc->sc_keystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
230 1.1 ober M_DEVBUF, M_NOWAIT);
231 1.2 peter memset(sc->sc_keystate, 0, sc->sc_nsense * sc->sc_nstrobe);
232 1.1 ober
233 1.1 ober /* set all the strobe bits */
234 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
235 1.1 ober pin = sc->sc_strobe_array[i];
236 1.4 nonaka if (pin == -1)
237 1.1 ober continue;
238 1.1 ober pxa2x0_gpio_set_function(pin, GPIO_SET|GPIO_OUT);
239 1.1 ober }
240 1.2 peter
241 1.1 ober /* set all the sense bits */
242 1.1 ober for (i = 0; i < sc->sc_nsense; i++) {
243 1.1 ober pin = sc->sc_sense_array[i];
244 1.4 nonaka if (pin == -1)
245 1.1 ober continue;
246 1.1 ober pxa2x0_gpio_set_function(pin, GPIO_IN);
247 1.1 ober pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH, IPL_TTY,
248 1.1 ober zkbd_irq, sc);
249 1.1 ober }
250 1.2 peter
251 1.1 ober pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH, IPL_TTY,
252 1.1 ober zkbd_on, sc);
253 1.1 ober pxa2x0_gpio_intr_establish(sc->sc_sync_pin, IST_EDGE_RISING, IPL_TTY,
254 1.1 ober zkbd_sync, sc);
255 1.1 ober pxa2x0_gpio_intr_establish(sc->sc_swa_pin, IST_EDGE_BOTH, IPL_TTY,
256 1.1 ober zkbd_hinge, sc);
257 1.1 ober pxa2x0_gpio_intr_establish(sc->sc_swb_pin, IST_EDGE_BOTH, IPL_TTY,
258 1.1 ober zkbd_hinge, sc);
259 1.1 ober
260 1.1 ober if (glass_console) {
261 1.1 ober wskbd_cnattach(&zkbd_consops, sc, &zkbd_keymapdata);
262 1.1 ober a.console = 1;
263 1.1 ober } else {
264 1.1 ober a.console = 0;
265 1.1 ober }
266 1.1 ober a.keymap = &zkbd_keymapdata;
267 1.1 ober a.accessops = &zkbd_accessops;
268 1.1 ober a.accesscookie = sc;
269 1.1 ober
270 1.1 ober zkbd_hinge(sc); /* to initialize sc_hinge */
271 1.1 ober
272 1.1 ober sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
273 1.1 ober }
274 1.1 ober
275 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
276 1.1 ober static void
277 1.1 ober zkbd_rawrepeat(void *v)
278 1.1 ober {
279 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
280 1.1 ober int s;
281 1.1 ober
282 1.1 ober s = spltty();
283 1.1 ober wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
284 1.1 ober splx(s);
285 1.1 ober callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
286 1.1 ober }
287 1.1 ober #endif
288 1.1 ober
289 1.1 ober /* XXX only deal with keys that can be pressed when display is open? */
290 1.1 ober /* XXX are some not in the array? */
291 1.1 ober /* handle keypress interrupt */
292 1.1 ober static int
293 1.1 ober zkbd_irq(void *v)
294 1.1 ober {
295 1.1 ober
296 1.1 ober zkbd_poll(v);
297 1.1 ober
298 1.1 ober return 1;
299 1.1 ober }
300 1.1 ober
301 1.1 ober static void
302 1.1 ober zkbd_poll(void *v)
303 1.1 ober {
304 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
305 1.2 peter int i, j, col, pin, type, keysdown = 0;
306 1.1 ober int stuck;
307 1.1 ober int keystate;
308 1.2 peter int s;
309 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
310 1.1 ober int npress = 0, ncbuf = 0, c;
311 1.2 peter char cbuf[MAXKEYS * 2];
312 1.1 ober #endif
313 1.1 ober
314 1.1 ober s = spltty();
315 1.1 ober
316 1.1 ober /* discharge all */
317 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
318 1.1 ober pin = sc->sc_strobe_array[i];
319 1.4 nonaka if (pin == -1)
320 1.4 nonaka continue;
321 1.4 nonaka pxa2x0_gpio_clear_bit(pin);
322 1.4 nonaka pxa2x0_gpio_set_dir(pin, GPIO_IN);
323 1.1 ober }
324 1.1 ober
325 1.2 peter delay(10);
326 1.2 peter for (col = 0; col < sc->sc_nstrobe; col++) {
327 1.2 peter pin = sc->sc_strobe_array[col];
328 1.2 peter if (pin == -1)
329 1.1 ober continue;
330 1.1 ober
331 1.1 ober /* activate_col */
332 1.1 ober pxa2x0_gpio_set_bit(pin);
333 1.1 ober pxa2x0_gpio_set_dir(pin, GPIO_OUT);
334 1.1 ober
335 1.1 ober /* wait activate delay */
336 1.1 ober delay(10);
337 1.1 ober
338 1.1 ober /* read row */
339 1.1 ober for (i = 0; i < sc->sc_nsense; i++) {
340 1.1 ober int bit;
341 1.1 ober
342 1.4 nonaka if (sc->sc_sense_array[i] == -1)
343 1.1 ober continue;
344 1.1 ober bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
345 1.1 ober if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
346 1.1 ober continue;
347 1.1 ober sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
348 1.1 ober }
349 1.1 ober
350 1.1 ober /* reset_col */
351 1.1 ober pxa2x0_gpio_set_dir(pin, GPIO_IN);
352 1.2 peter
353 1.1 ober /* wait discharge delay */
354 1.1 ober delay(10);
355 1.1 ober }
356 1.2 peter
357 1.1 ober /* charge all */
358 1.1 ober for (i = 0; i < sc->sc_nstrobe; i++) {
359 1.1 ober pin = sc->sc_strobe_array[i];
360 1.4 nonaka if (pin == -1)
361 1.4 nonaka continue;
362 1.4 nonaka pxa2x0_gpio_set_bit(pin);
363 1.4 nonaka pxa2x0_gpio_set_dir(pin, GPIO_OUT);
364 1.1 ober }
365 1.1 ober
366 1.1 ober /* force the irqs to clear as we have just played with them. */
367 1.2 peter for (i = 0; i < sc->sc_nsense; i++) {
368 1.4 nonaka pin = sc->sc_sense_array[i];
369 1.4 nonaka if (pin == -1)
370 1.4 nonaka continue;
371 1.4 nonaka pxa2x0_gpio_clear_intr(pin);
372 1.2 peter }
373 1.1 ober
374 1.1 ober /* process after resetting interrupt */
375 1.1 ober zkbd_modstate = (
376 1.1 ober (sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
377 1.1 ober (sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
378 1.1 ober (sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */
379 1.1 ober
380 1.2 peter for (i = 0; i < sc->sc_nsense * sc->sc_nstrobe; i++) {
381 1.1 ober stuck = 0;
382 1.1 ober /* extend xt_keymap to do this faster. */
383 1.1 ober /* ignore 'stuck' keys' */
384 1.2 peter for (j = 0; j < __arraycount(stuck_keys); j++) {
385 1.1 ober if (stuck_keys[j] == i) {
386 1.2 peter stuck = 1;
387 1.1 ober break;
388 1.1 ober }
389 1.1 ober }
390 1.1 ober if (stuck)
391 1.1 ober continue;
392 1.2 peter
393 1.1 ober keystate = sc->sc_keystate[i];
394 1.1 ober keysdown |= keystate; /* if any keys held */
395 1.1 ober
396 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
397 1.1 ober if (sc->sc_polling == 0 && sc->sc_rawkbd) {
398 1.1 ober if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
399 1.1 ober c = sc->sc_xt_keymap[i];
400 1.1 ober if (c & 0x80) {
401 1.1 ober cbuf[ncbuf++] = 0xe0;
402 1.1 ober }
403 1.1 ober cbuf[ncbuf] = c & 0x7f;
404 1.1 ober
405 1.1 ober if (keystate) {
406 1.1 ober if (c & 0x80) {
407 1.1 ober sc->sc_rep[npress++] = 0xe0;
408 1.1 ober }
409 1.1 ober sc->sc_rep[npress++] = c & 0x7f;
410 1.1 ober } else {
411 1.1 ober cbuf[ncbuf] |= 0x80;
412 1.1 ober }
413 1.1 ober ncbuf++;
414 1.1 ober sc->sc_okeystate[i] = keystate;
415 1.1 ober }
416 1.1 ober }
417 1.1 ober #endif
418 1.1 ober
419 1.1 ober if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
420 1.1 ober type = keystate ? WSCONS_EVENT_KEY_DOWN :
421 1.1 ober WSCONS_EVENT_KEY_UP;
422 1.1 ober
423 1.1 ober if (sc->sc_polling) {
424 1.1 ober sc->sc_pollkey = i;
425 1.1 ober sc->sc_pollUD = type;
426 1.1 ober } else {
427 1.1 ober wskbd_input(sc->sc_wskbddev, type, i);
428 1.1 ober }
429 1.1 ober
430 1.1 ober sc->sc_okeystate[i] = keystate;
431 1.1 ober }
432 1.1 ober }
433 1.1 ober
434 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
435 1.1 ober if (sc->sc_polling == 0 && sc->sc_rawkbd) {
436 1.1 ober wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
437 1.1 ober sc->sc_nrep = npress;
438 1.1 ober if (npress != 0)
439 1.1 ober callout_schedule(&sc->sc_rawrepeat_ch,
440 1.1 ober hz * REP_DELAY1 / 1000);
441 1.1 ober else
442 1.1 ober callout_stop(&sc->sc_rawrepeat_ch);
443 1.1 ober }
444 1.1 ober #endif
445 1.1 ober if (keysdown)
446 1.1 ober callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
447 1.1 ober else
448 1.1 ober callout_stop(&sc->sc_roll_to); /* always cancel? */
449 1.1 ober
450 1.1 ober splx(s);
451 1.1 ober }
452 1.1 ober
453 1.1 ober #if NAPM > 0
454 1.1 ober extern int kbd_reset;
455 1.1 ober extern int apm_suspends;
456 1.1 ober static int zkbdondown; /* on key is pressed */
457 1.1 ober static struct timeval zkbdontv = { 0, 0 }; /* last on key event */
458 1.1 ober const struct timeval zkbdhalttv = { 3, 0 }; /* 3s for safe shutdown */
459 1.1 ober const struct timeval zkbdsleeptv = { 0, 250000 }; /* .25s for suspend */
460 1.1 ober extern int lid_suspend;
461 1.1 ober #endif
462 1.1 ober
463 1.1 ober static int
464 1.1 ober zkbd_on(void *v)
465 1.1 ober {
466 1.1 ober #if NAPM > 0
467 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
468 1.1 ober int down = pxa2x0_gpio_get_bit(sc->sc_onkey_pin) ? 1 : 0;
469 1.1 ober
470 1.1 ober /*
471 1.1 ober * Change run mode depending on how long the key is held down.
472 1.1 ober * Ignore the key if it gets pressed while the lid is closed.
473 1.1 ober *
474 1.1 ober * Keys can bounce and we have to work around missed interrupts.
475 1.1 ober * Only the second edge is detected upon exit from sleep mode.
476 1.1 ober */
477 1.1 ober if (down) {
478 1.1 ober if (sc->sc_hinge == 3) {
479 1.1 ober zkbdondown = 0;
480 1.1 ober } else {
481 1.1 ober microuptime(&zkbdontv);
482 1.1 ober zkbdondown = 1;
483 1.1 ober }
484 1.1 ober } else if (zkbdondown) {
485 1.1 ober if (ratecheck(&zkbdontv, &zkbdhalttv)) {
486 1.1 ober if (kbd_reset == 1) {
487 1.1 ober kbd_reset = 0;
488 1.1 ober psignal(initproc, SIGUSR1);
489 1.1 ober }
490 1.1 ober } else if (ratecheck(&zkbdontv, &zkbdsleeptv)) {
491 1.1 ober apm_suspends++;
492 1.1 ober }
493 1.1 ober zkbdondown = 0;
494 1.1 ober }
495 1.1 ober #endif
496 1.1 ober return 1;
497 1.1 ober }
498 1.1 ober
499 1.1 ober static int
500 1.1 ober zkbd_sync(void *v)
501 1.1 ober {
502 1.1 ober
503 1.1 ober return 1;
504 1.1 ober }
505 1.1 ober
506 1.1 ober static int
507 1.1 ober zkbd_hinge(void *v)
508 1.1 ober {
509 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
510 1.1 ober int a = pxa2x0_gpio_get_bit(sc->sc_swa_pin) ? 1 : 0;
511 1.1 ober int b = pxa2x0_gpio_get_bit(sc->sc_swb_pin) ? 2 : 0;
512 1.1 ober #if NLCD > 0
513 1.1 ober extern void lcd_blank(int);
514 1.1 ober #endif
515 1.1 ober
516 1.1 ober sc->sc_hinge = a | b;
517 1.1 ober
518 1.1 ober if (sc->sc_hinge == 3) {
519 1.1 ober #if NAPM > 0
520 1.1 ober if (lid_suspend)
521 1.1 ober apm_suspends++;
522 1.1 ober #endif
523 1.1 ober #if NLCD > 0
524 1.1 ober lcd_blank(1);
525 1.1 ober #endif
526 1.1 ober } else {
527 1.1 ober #if NLCD > 0
528 1.1 ober lcd_blank(0);
529 1.1 ober #endif
530 1.1 ober }
531 1.1 ober
532 1.1 ober return 1;
533 1.1 ober }
534 1.1 ober
535 1.1 ober static int
536 1.1 ober zkbd_enable(void *v, int on)
537 1.1 ober {
538 1.1 ober
539 1.1 ober return 0;
540 1.1 ober }
541 1.1 ober
542 1.1 ober void
543 1.1 ober zkbd_set_leds(void *v, int on)
544 1.1 ober {
545 1.1 ober }
546 1.1 ober
547 1.1 ober static int
548 1.3 christos zkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
549 1.1 ober {
550 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
551 1.1 ober struct zkbd_softc *sc = (struct zkbd_softc *)v;
552 1.1 ober #endif
553 1.1 ober
554 1.1 ober switch (cmd) {
555 1.1 ober case WSKBDIO_GTYPE:
556 1.1 ober *(int *)data = WSKBD_TYPE_ZAURUS;
557 1.1 ober return 0;
558 1.1 ober
559 1.1 ober case WSKBDIO_SETLEDS:
560 1.1 ober return 0;
561 1.1 ober
562 1.1 ober case WSKBDIO_GETLEDS:
563 1.1 ober *(int *)data = 0;
564 1.1 ober return 0;
565 1.1 ober
566 1.1 ober #ifdef WSDISPLAY_COMPAT_RAWKBD
567 1.1 ober case WSKBDIO_SETMODE:
568 1.1 ober sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
569 1.1 ober callout_stop(&sc->sc_rawrepeat_ch);
570 1.1 ober return 0;
571 1.1 ober #endif
572 1.1 ober
573 1.1 ober }
574 1.2 peter return EPASSTHROUGH;
575 1.1 ober }
576 1.1 ober
577 1.1 ober /* implement polling for zaurus_kbd */
578 1.1 ober static void
579 1.1 ober zkbd_cngetc(void *v, u_int *type, int *data)
580 1.1 ober {
581 1.2 peter struct zkbd_softc *sc = (struct zkbd_softc *)zkbd_sc;
582 1.1 ober
583 1.1 ober sc->sc_pollkey = -1;
584 1.1 ober sc->sc_pollUD = -1;
585 1.1 ober sc->sc_polling = 1;
586 1.1 ober while (sc->sc_pollkey == -1) {
587 1.2 peter zkbd_poll(sc);
588 1.1 ober DELAY(10000); /* XXX */
589 1.1 ober }
590 1.1 ober sc->sc_polling = 0;
591 1.1 ober *data = sc->sc_pollkey;
592 1.1 ober *type = sc->sc_pollUD;
593 1.1 ober }
594 1.1 ober
595 1.1 ober static void
596 1.1 ober zkbd_cnpollc(void *v, int on)
597 1.1 ober {
598 1.1 ober }
599 1.1 ober
600 1.1 ober static void
601 1.1 ober zkbd_power(int why, void *arg)
602 1.1 ober {
603 1.1 ober
604 1.1 ober zkbd_hinge(arg);
605 1.1 ober }
606