1 1.18 andvar /* $NetBSD: g42xxeb_kmkbd.c,v 1.18 2024/02/09 22:08:32 andvar Exp $ */ 2 1.1 bsh 3 1.1 bsh /*- 4 1.1 bsh * Copyright (c) 2002, 2003, 2005 Genetec corp. 5 1.1 bsh * All rights reserved. 6 1.1 bsh * 7 1.1 bsh * 4x5 matrix key switch driver for TWINTAIL. 8 1.1 bsh * Written by Hiroyuki Bessho for Genetec corp. 9 1.1 bsh * 10 1.1 bsh * Redistribution and use in source and binary forms, with or without 11 1.1 bsh * modification, are permitted provided that the following conditions 12 1.1 bsh * are met: 13 1.1 bsh * 1. Redistributions of source code must retain the above copyright 14 1.1 bsh * notice, this list of conditions and the following disclaimer. 15 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 bsh * notice, this list of conditions and the following disclaimer in the 17 1.1 bsh * documentation and/or other materials provided with the distribution. 18 1.9 martin * 3. Neither the name of The NetBSD Foundation nor the names of its 19 1.9 martin * contributors may be used to endorse or promote products derived 20 1.9 martin * from this software without specific prior written permission. 21 1.1 bsh * 22 1.1 bsh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 1.1 bsh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 1.1 bsh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 1.1 bsh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 1.1 bsh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 bsh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 bsh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 bsh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 bsh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 bsh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 bsh * POSSIBILITY OF SUCH DAMAGE. 33 1.1 bsh */ 34 1.1 bsh 35 1.1 bsh /* 36 1.1 bsh * Use on-board matrix switches as wskbd. 37 1.1 bsh */ 38 1.1 bsh 39 1.1 bsh #include <sys/cdefs.h> 40 1.18 andvar __KERNEL_RCSID(0, "$NetBSD: g42xxeb_kmkbd.c,v 1.18 2024/02/09 22:08:32 andvar Exp $" ); 41 1.1 bsh 42 1.1 bsh #include <sys/param.h> 43 1.1 bsh #include <sys/systm.h> 44 1.1 bsh #include <sys/device.h> 45 1.1 bsh #include <sys/ioctl.h> 46 1.1 bsh #include <sys/callout.h> 47 1.1 bsh #include <sys/kernel.h> /* for hz */ 48 1.1 bsh 49 1.12 dyoung #include <sys/bus.h> 50 1.1 bsh 51 1.1 bsh #include <dev/wscons/wsconsio.h> 52 1.1 bsh #include <dev/wscons/wskbdvar.h> 53 1.1 bsh #include <dev/wscons/wsksymdef.h> 54 1.1 bsh #include <dev/wscons/wsksymvar.h> 55 1.1 bsh 56 1.1 bsh #include <arch/evbarm/g42xxeb/g42xxeb_var.h> 57 1.1 bsh 58 1.1 bsh #include "locators.h" 59 1.13 bsh #include "opt_wsdisplay_compat.h" 60 1.1 bsh 61 1.1 bsh #define DEBOUNCE_TICKS ((hz<=50)?1:hz/50) /* 20ms */ 62 1.1 bsh #define RELEASE_WATCH_TICKS (hz/10) /* 100ms */ 63 1.1 bsh 64 1.13 bsh #define NUMKEYS (4*5) /* the number of keys */ 65 1.13 bsh 66 1.1 bsh struct kmkbd_softc { 67 1.11 bsh device_t dev; 68 1.1 bsh 69 1.14 chs device_t wskbddev; 70 1.1 bsh void *ih; /* interrupt handler */ 71 1.1 bsh struct callout callout; 72 1.1 bsh 73 1.1 bsh uint32_t notified_bits; /* reported state of keys */ 74 1.1 bsh uint32_t last_bits; /* used for debounce */ 75 1.1 bsh u_char debounce_counter; 76 1.1 bsh #define DEBOUNCE_COUNT 3 77 1.1 bsh u_char polling; 78 1.13 bsh u_char rawkbd; 79 1.1 bsh enum kmkbd_state { 80 1.1 bsh ST_INIT, 81 1.1 bsh ST_DISABLED, 82 1.1 bsh ST_ALL_UP, /* waiting for interrupt */ 83 1.1 bsh ST_DEBOUNCE, /* doing debounce */ 84 1.1 bsh ST_KEY_PRESSED /* some keys are pressed */ 85 1.1 bsh } state; 86 1.1 bsh }; 87 1.1 bsh 88 1.1 bsh 89 1.11 bsh int kmkbd_match(device_t, cfdata_t, void *); 90 1.11 bsh void kmkbd_attach(device_t, device_t, void *); 91 1.1 bsh 92 1.11 bsh CFATTACH_DECL_NEW(kmkbd, sizeof(struct kmkbd_softc), 93 1.1 bsh kmkbd_match, kmkbd_attach, NULL, NULL); 94 1.1 bsh 95 1.1 bsh static int kmkbd_enable(void *, int); 96 1.1 bsh static void kmkbd_set_leds(void *, int); 97 1.5 christos static int kmkbd_ioctl(void *, u_long, void *, int, struct lwp *); 98 1.1 bsh 99 1.1 bsh const struct wskbd_accessops kmkbd_accessops = { 100 1.1 bsh kmkbd_enable, 101 1.1 bsh kmkbd_set_leds, 102 1.1 bsh kmkbd_ioctl, 103 1.1 bsh }; 104 1.1 bsh 105 1.1 bsh #if 0 106 1.1 bsh void kmkbd_cngetc(void *, u_int *, int *); 107 1.1 bsh void kmkbd_cnpollc(void *, int); 108 1.1 bsh void kmkbd_cnbell(void *, u_int, u_int, u_int); 109 1.1 bsh 110 1.1 bsh const struct wskbd_consops kmkbd_consops = { 111 1.1 bsh kmkbd_cngetc, 112 1.1 bsh kmkbd_cnpollc, 113 1.1 bsh kmkbd_cnbell, 114 1.1 bsh }; 115 1.1 bsh #endif 116 1.1 bsh 117 1.1 bsh static const keysym_t kmkbd_keydesc_0[] = { 118 1.1 bsh /* pos normal shifted */ 119 1.1 bsh KS_KEYCODE(0), KS_a, KS_A, 120 1.1 bsh KS_KEYCODE(1), KS_b, KS_B, 121 1.1 bsh KS_KEYCODE(2), KS_c, KS_C, 122 1.1 bsh KS_KEYCODE(3), KS_d, KS_D, 123 1.1 bsh KS_KEYCODE(4), KS_e, KS_E, 124 1.1 bsh KS_KEYCODE(5), KS_f, KS_F, 125 1.1 bsh KS_KEYCODE(6), KS_g, KS_G, 126 1.1 bsh KS_KEYCODE(7), KS_h, KS_H, 127 1.1 bsh KS_KEYCODE(8), KS_i, KS_I, 128 1.1 bsh KS_KEYCODE(9), KS_j, KS_J, 129 1.1 bsh KS_KEYCODE(10), KS_k, KS_K, 130 1.1 bsh KS_KEYCODE(11), KS_l, KS_L, 131 1.1 bsh KS_KEYCODE(12), KS_m, KS_M, 132 1.1 bsh KS_KEYCODE(13), KS_n, KS_N, 133 1.1 bsh KS_KEYCODE(14), KS_o, KS_O, 134 1.1 bsh KS_KEYCODE(15), KS_p, KS_P, 135 1.1 bsh KS_KEYCODE(16), KS_q, KS_Q, 136 1.1 bsh KS_KEYCODE(17), KS_r, KS_R, 137 1.1 bsh KS_KEYCODE(18), '\003', '\003', 138 1.1 bsh KS_KEYCODE(19), KS_Return, KS_Linefeed, 139 1.1 bsh }; 140 1.1 bsh 141 1.1 bsh #define KBD_MAP(name, base, map) \ 142 1.1 bsh { name, base, sizeof(map)/sizeof(keysym_t), map } 143 1.1 bsh 144 1.1 bsh static const struct wscons_keydesc kmkbd_keydesctab[] = { 145 1.1 bsh KBD_MAP(KB_MACHDEP, 0, kmkbd_keydesc_0), 146 1.1 bsh {0, 0, 0, 0} 147 1.1 bsh }; 148 1.1 bsh 149 1.1 bsh const struct wskbd_mapdata kmkbd_keymapdata = { 150 1.1 bsh kmkbd_keydesctab, 151 1.1 bsh #ifdef KMKBD_LAYOUT 152 1.1 bsh KMKBD_LAYOUT, 153 1.1 bsh #else 154 1.1 bsh KB_MACHDEP, 155 1.1 bsh #endif 156 1.1 bsh }; 157 1.1 bsh 158 1.1 bsh /* 159 1.18 andvar * Hackish support for a bell on the PC Keyboard; when a suitable beeper 160 1.1 bsh * is found, it attaches itself into the pckbd driver here. 161 1.1 bsh */ 162 1.1 bsh void (*kmkbd_bell_fn)(void *, u_int, u_int, u_int, int); 163 1.1 bsh void *kmkbd_bell_fn_arg; 164 1.1 bsh 165 1.1 bsh void kmkbd_bell(u_int, u_int, u_int, int); 166 1.1 bsh void kmkbd_hookup_bell(void (* fn)(void *, u_int, u_int, u_int, int), void *arg); 167 1.1 bsh 168 1.1 bsh static int kmkbd_intr(void *); 169 1.1 bsh static void kmkbd_new_state(struct kmkbd_softc *, enum kmkbd_state); 170 1.1 bsh 171 1.1 bsh /*struct kmkbd_internal kmkbd_consdata;*/ 172 1.1 bsh 173 1.1 bsh static int 174 1.1 bsh kmkbd_is_console(void) 175 1.1 bsh { 176 1.1 bsh #if 0 177 1.1 bsh return (kmkbd_consdata.t_isconsole && 178 1.1 bsh (tag == kmkbd_consdata.t_kbctag) && 179 1.1 bsh (slot == kmkbd_consdata.t_kbcslot)); 180 1.1 bsh #else 181 1.1 bsh return 0; 182 1.1 bsh #endif 183 1.1 bsh } 184 1.1 bsh 185 1.1 bsh int 186 1.14 chs kmkbd_match(device_t parent, cfdata_t cf, void *aux) 187 1.1 bsh { 188 1.1 bsh return 1; 189 1.1 bsh } 190 1.1 bsh 191 1.1 bsh void 192 1.11 bsh kmkbd_attach(device_t parent, device_t self, void *aux) 193 1.1 bsh { 194 1.11 bsh struct kmkbd_softc *sc = device_private(self); 195 1.1 bsh /*struct obio_attach_args *oa = aux;*/ 196 1.1 bsh int state0; 197 1.1 bsh struct wskbddev_attach_args a; 198 1.11 bsh struct obio_softc *osc = device_private(parent); 199 1.1 bsh int s; 200 1.1 bsh 201 1.1 bsh printf("\n"); 202 1.1 bsh 203 1.11 bsh sc->dev = self; 204 1.1 bsh sc->state = ST_INIT; 205 1.1 bsh 206 1.1 bsh if (kmkbd_is_console()){ 207 1.1 bsh a.console = 1; 208 1.1 bsh state0 = ST_ALL_UP; 209 1.1 bsh } else { 210 1.1 bsh a.console = 0; 211 1.1 bsh state0 = ST_DISABLED; 212 1.1 bsh } 213 1.1 bsh 214 1.13 bsh #ifdef WSDISPLAY_COMPAT_RAWKBD 215 1.13 bsh sc->rawkbd = 0; 216 1.13 bsh #endif 217 1.6 ad callout_init(&sc->callout, 0); 218 1.1 bsh 219 1.1 bsh s = spltty(); 220 1.1 bsh sc->ih = obio_intr_establish(osc, G42XXEB_INT_KEY, IPL_TTY, 221 1.1 bsh IST_EDGE_FALLING, kmkbd_intr, (void *)sc); 222 1.1 bsh kmkbd_new_state(sc, state0); 223 1.1 bsh splx(s); 224 1.1 bsh 225 1.1 bsh a.keymap = &kmkbd_keymapdata; 226 1.1 bsh 227 1.1 bsh a.accessops = &kmkbd_accessops; 228 1.1 bsh a.accesscookie = sc; 229 1.1 bsh 230 1.1 bsh 231 1.1 bsh /* Attach the wskbd. */ 232 1.16 thorpej sc->wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE); 233 1.1 bsh 234 1.1 bsh } 235 1.1 bsh 236 1.1 bsh static int 237 1.1 bsh kmkbd_enable(void *v, int on) 238 1.1 bsh { 239 1.1 bsh struct kmkbd_softc *sc = v; 240 1.1 bsh 241 1.1 bsh if (on) { 242 1.1 bsh if (sc->state != ST_DISABLED) { 243 1.1 bsh #ifdef DIAGNOSTIC 244 1.1 bsh printf("kmkbd_enable: bad enable (state=%d)\n", sc->state); 245 1.1 bsh #endif 246 1.1 bsh return (EBUSY); 247 1.1 bsh } 248 1.1 bsh 249 1.1 bsh kmkbd_new_state(sc, ST_ALL_UP); 250 1.1 bsh } else { 251 1.1 bsh #if 0 252 1.1 bsh if (sc->id->t_isconsole) 253 1.1 bsh return (EBUSY); 254 1.1 bsh #endif 255 1.1 bsh 256 1.1 bsh kmkbd_new_state(sc, ST_DISABLED); 257 1.1 bsh } 258 1.1 bsh 259 1.1 bsh return (0); 260 1.1 bsh } 261 1.1 bsh 262 1.1 bsh 263 1.1 bsh 264 1.1 bsh static void 265 1.1 bsh kmkbd_set_leds(void *v, int leds) 266 1.1 bsh { 267 1.1 bsh } 268 1.1 bsh 269 1.1 bsh static int 270 1.5 christos kmkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 271 1.1 bsh { 272 1.13 bsh #ifdef WSDISPLAY_COMPAT_RAWKBD 273 1.13 bsh struct kmkbd_softc *sc = v; 274 1.13 bsh #endif 275 1.1 bsh 276 1.1 bsh switch (cmd) { 277 1.1 bsh case WSKBDIO_GTYPE: 278 1.1 bsh *(int *)data = WSKBD_TYPE_PC_XT; /* XXX */ 279 1.1 bsh return 0; 280 1.1 bsh case WSKBDIO_COMPLEXBELL: 281 1.1 bsh #define d ((struct wskbd_bell_data *)data) 282 1.1 bsh /* 283 1.1 bsh * Keyboard can't beep directly; we have an 284 1.1 bsh * externally-provided global hook to do this. 285 1.1 bsh */ 286 1.1 bsh kmkbd_bell(d->pitch, d->period, d->volume, 0); 287 1.1 bsh #undef d 288 1.1 bsh return (0); 289 1.1 bsh #ifdef WSDISPLAY_COMPAT_RAWKBD 290 1.1 bsh case WSKBDIO_SETMODE: 291 1.1 bsh sc->rawkbd = (*(int *)data == WSKBD_RAW); 292 1.1 bsh return (0); 293 1.1 bsh #endif 294 1.1 bsh 295 1.1 bsh #if 0 296 1.1 bsh case WSKBDIO_SETLEDS: 297 1.1 bsh case WSKBDIO_GETLEDS: 298 1.1 bsh /* no LED support */ 299 1.1 bsh #endif 300 1.1 bsh } 301 1.1 bsh return EPASSTHROUGH; 302 1.1 bsh } 303 1.1 bsh 304 1.1 bsh void 305 1.1 bsh kmkbd_bell(u_int pitch, u_int period, u_int volume, int poll) 306 1.1 bsh { 307 1.1 bsh 308 1.1 bsh if (kmkbd_bell_fn != NULL) 309 1.1 bsh (*kmkbd_bell_fn)(kmkbd_bell_fn_arg, pitch, period, 310 1.1 bsh volume, poll); 311 1.1 bsh } 312 1.1 bsh 313 1.1 bsh void 314 1.1 bsh kmkbd_hookup_bell(void (* fn)(void *, u_int, u_int, u_int, int), void *arg) 315 1.1 bsh { 316 1.1 bsh 317 1.1 bsh if (kmkbd_bell_fn == NULL) { 318 1.1 bsh kmkbd_bell_fn = fn; 319 1.1 bsh kmkbd_bell_fn_arg = arg; 320 1.1 bsh } 321 1.1 bsh } 322 1.1 bsh 323 1.1 bsh #if 0 324 1.1 bsh int 325 1.10 dsl kmkbd_cnattach(pckbc_tag_t kbctag, int kbcslot) 326 1.1 bsh { 327 1.1 bsh int res; 328 1.1 bsh 329 1.1 bsh res = kmkbd_init(&kmkbd_consdata, kbctag, kbcslot, 1); 330 1.1 bsh 331 1.1 bsh wskbd_cnattach(&kmkbd_consops, &kmkbd_consdata, &kmkbd_keymapdata); 332 1.1 bsh 333 1.1 bsh return (0); 334 1.1 bsh } 335 1.1 bsh 336 1.1 bsh void 337 1.1 bsh kmkbd_cngetc(void *v, u_int type, int *data) 338 1.1 bsh { 339 1.1 bsh struct kmkbd_internal *t = v; 340 1.1 bsh int val; 341 1.1 bsh 342 1.1 bsh for (;;) { 343 1.1 bsh val = pckbc_poll_data(t->t_kbctag, t->t_kbcslot); 344 1.1 bsh if ((val != -1) && kmkbd_decode(t, val, type, data)) 345 1.1 bsh return; 346 1.1 bsh } 347 1.1 bsh } 348 1.1 bsh 349 1.1 bsh void 350 1.1 bsh kmkbd_cnpollc(void *v, int on) 351 1.1 bsh { 352 1.1 bsh struct kmkbd_internal *t = v; 353 1.1 bsh 354 1.1 bsh pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on); 355 1.1 bsh } 356 1.1 bsh 357 1.1 bsh void 358 1.1 bsh kmkbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) 359 1.1 bsh { 360 1.1 bsh 361 1.1 bsh kmkbd_bell(pitch, period, volume, 1); 362 1.1 bsh } 363 1.1 bsh #endif 364 1.1 bsh 365 1.1 bsh 366 1.1 bsh /* 367 1.1 bsh * low level access to key matrix 368 1.1 bsh * 369 1.1 bsh * returns bitset of keys being pressed. 370 1.1 bsh */ 371 1.1 bsh static u_int 372 1.1 bsh kmkbd_read_matrix(struct kmkbd_softc *sc) 373 1.1 bsh { 374 1.1 bsh int i; 375 1.1 bsh u_int ret, data; 376 1.11 bsh struct obio_softc *osc = device_private(device_parent(sc->dev)); 377 1.1 bsh bus_space_tag_t iot = osc->sc_iot; 378 1.1 bsh bus_space_handle_t ioh = osc->sc_obioreg_ioh; 379 1.1 bsh 380 1.1 bsh #define KMDELAY() delay(3) 381 1.1 bsh 382 1.1 bsh bus_space_write_2( iot, ioh, G42XXEB_KEYSCAN, 0 ); 383 1.1 bsh KMDELAY(); 384 1.1 bsh 385 1.1 bsh data = KEYSCAN_SENSE_IN & 386 1.1 bsh bus_space_read_2(iot, ioh, G42XXEB_KEYSCAN); 387 1.1 bsh 388 1.1 bsh bus_space_write_2(iot, ioh, G42XXEB_KEYSCAN, KEYSCAN_SCAN_OUT); 389 1.1 bsh 390 1.1 bsh if (data == KEYSCAN_SENSE_IN) 391 1.1 bsh return 0; 392 1.1 bsh 393 1.1 bsh ret = 0; 394 1.1 bsh for( i=0; i<5; ++i ){ 395 1.1 bsh /* scan one line */ 396 1.1 bsh bus_space_write_2(iot, ioh, G42XXEB_KEYSCAN, ~(0x0100<<i)); 397 1.1 bsh KMDELAY(); 398 1.1 bsh data = bus_space_read_2(iot, ioh, G42XXEB_KEYSCAN ); 399 1.1 bsh 400 1.1 bsh data = ~data & KEYSCAN_SENSE_IN; 401 1.1 bsh ret |= data << (i*4); 402 1.1 bsh } 403 1.1 bsh 404 1.1 bsh bus_space_write_2(iot, ioh, G42XXEB_KEYSCAN, KEYSCAN_SCAN_OUT); 405 1.1 bsh return ret; 406 1.1 bsh 407 1.1 bsh #undef KMDELAY 408 1.1 bsh 409 1.1 bsh } 410 1.1 bsh 411 1.1 bsh /* 412 1.1 bsh * report key status change to wskbd subsystem. 413 1.1 bsh */ 414 1.1 bsh static void 415 1.1 bsh kmkbd_report(struct kmkbd_softc *sc, u_int bitset) 416 1.1 bsh { 417 1.1 bsh u_int changed; 418 1.1 bsh int i; 419 1.1 bsh 420 1.1 bsh if (bitset == sc->notified_bits) 421 1.1 bsh return; 422 1.1 bsh 423 1.1 bsh if (sc->notified_bits && bitset == 0){ 424 1.1 bsh wskbd_input(sc->wskbddev, WSCONS_EVENT_ALL_KEYS_UP, 0); 425 1.1 bsh sc->notified_bits = 0; 426 1.1 bsh return; 427 1.1 bsh } 428 1.1 bsh 429 1.1 bsh changed = bitset ^ sc->notified_bits; 430 1.1 bsh for( i=0; changed; ++i){ 431 1.1 bsh if ((changed & (1<<i)) == 0) 432 1.1 bsh continue; 433 1.1 bsh changed &= ~(1<<i); 434 1.1 bsh 435 1.1 bsh wskbd_input(sc->wskbddev, 436 1.1 bsh (bitset & (1<<i)) ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP, 437 1.1 bsh i); 438 1.1 bsh } 439 1.1 bsh 440 1.1 bsh sc->notified_bits = bitset; 441 1.1 bsh } 442 1.1 bsh 443 1.13 bsh #ifdef WSDISPLAY_COMPAT_RAWKBD 444 1.13 bsh static void 445 1.13 bsh kmkbd_report_raw(struct kmkbd_softc *sc, u_int bitset) 446 1.13 bsh { 447 1.13 bsh int i, nc; 448 1.13 bsh char cbuf[NUMKEYS]; 449 1.13 bsh u_int changed; 450 1.13 bsh 451 1.13 bsh if (bitset == sc->notified_bits) 452 1.13 bsh return; 453 1.13 bsh 454 1.13 bsh nc = 0; 455 1.13 bsh changed = bitset ^ sc->notified_bits; 456 1.13 bsh 457 1.13 bsh while (changed) { 458 1.13 bsh i = ffs(changed) - 1; 459 1.13 bsh if (nc < NUMKEYS) { 460 1.13 bsh cbuf[nc] = i + 1; 461 1.13 bsh if (0 == (bitset & (1<<i))) { 462 1.13 bsh /* the key is released */ 463 1.13 bsh cbuf[nc] |= 0x80; 464 1.13 bsh } 465 1.13 bsh ++nc; 466 1.13 bsh } 467 1.13 bsh 468 1.13 bsh changed &= ~(1<<i); 469 1.13 bsh } 470 1.13 bsh 471 1.13 bsh wskbd_rawinput(sc->wskbddev, cbuf, nc); 472 1.13 bsh sc->notified_bits = bitset; 473 1.13 bsh } 474 1.13 bsh #endif 475 1.13 bsh 476 1.1 bsh static int 477 1.1 bsh kmkbd_intr(void *arg) 478 1.1 bsh { 479 1.1 bsh struct kmkbd_softc *sc = arg; 480 1.11 bsh struct obio_softc *osc = device_private(device_parent(sc->dev)); 481 1.1 bsh 482 1.1 bsh if ( sc->state != ST_ALL_UP ){ 483 1.1 bsh printf("Spurious interrupt from key matrix\n"); 484 1.1 bsh obio_intr_mask(osc, sc->ih); 485 1.1 bsh return 1; 486 1.1 bsh } 487 1.1 bsh 488 1.1 bsh kmkbd_new_state(sc, ST_DEBOUNCE); 489 1.1 bsh 490 1.1 bsh return 1; 491 1.1 bsh } 492 1.1 bsh 493 1.1 bsh static void 494 1.1 bsh kmkbd_debounce(void *arg) 495 1.1 bsh { 496 1.1 bsh struct kmkbd_softc *sc = arg; 497 1.1 bsh u_int newbits; 498 1.1 bsh enum kmkbd_state new_state = ST_DEBOUNCE; 499 1.1 bsh int s = spltty(); 500 1.1 bsh 501 1.1 bsh newbits = kmkbd_read_matrix(sc); 502 1.1 bsh 503 1.1 bsh if (newbits != sc->last_bits){ 504 1.1 bsh sc->last_bits = newbits; 505 1.1 bsh sc->debounce_counter = 0; 506 1.1 bsh } 507 1.1 bsh else if( ++(sc->debounce_counter) >= DEBOUNCE_COUNT ){ 508 1.1 bsh new_state = newbits == 0 ? ST_ALL_UP : ST_KEY_PRESSED; 509 1.13 bsh #ifdef WSDISPLAY_COMPAT_RAWKBD 510 1.13 bsh if (sc->rawkbd) 511 1.13 bsh kmkbd_report_raw(sc, newbits); 512 1.13 bsh else 513 1.13 bsh #endif 514 1.13 bsh kmkbd_report(sc, newbits); 515 1.1 bsh } 516 1.1 bsh 517 1.1 bsh kmkbd_new_state(sc, new_state); 518 1.1 bsh splx(s); 519 1.1 bsh } 520 1.1 bsh 521 1.1 bsh /* callout routine to watch key release */ 522 1.1 bsh static void 523 1.1 bsh kmkbd_watch(void *arg) 524 1.1 bsh { 525 1.1 bsh int s = spltty(); 526 1.1 bsh struct kmkbd_softc *sc = arg; 527 1.1 bsh u_int newbits; 528 1.1 bsh int new_state = ST_KEY_PRESSED; 529 1.1 bsh 530 1.1 bsh newbits = kmkbd_read_matrix(sc); 531 1.1 bsh 532 1.1 bsh if (newbits != sc->last_bits){ 533 1.1 bsh /* some keys are released or new keys are pressed. 534 1.1 bsh start debounce */ 535 1.1 bsh new_state = ST_DEBOUNCE; 536 1.1 bsh sc->last_bits = newbits; 537 1.1 bsh } 538 1.1 bsh 539 1.1 bsh kmkbd_new_state(sc, new_state); 540 1.1 bsh splx(s); 541 1.1 bsh } 542 1.1 bsh 543 1.1 bsh static void 544 1.1 bsh kmkbd_new_state(struct kmkbd_softc *sc, enum kmkbd_state new_state) 545 1.1 bsh { 546 1.11 bsh struct obio_softc *osc = device_private(device_parent(sc->dev)); 547 1.1 bsh 548 1.1 bsh switch(new_state){ 549 1.1 bsh case ST_DISABLED: 550 1.1 bsh if (sc->state != ST_DISABLED){ 551 1.1 bsh callout_stop(&sc->callout); 552 1.1 bsh obio_intr_mask(osc,sc->ih); 553 1.1 bsh } 554 1.1 bsh break; 555 1.1 bsh case ST_DEBOUNCE: 556 1.1 bsh if (sc->state == ST_ALL_UP){ 557 1.1 bsh obio_intr_mask(osc, sc->ih); 558 1.1 bsh sc->last_bits = kmkbd_read_matrix(sc); 559 1.1 bsh } 560 1.1 bsh if (sc->state != ST_DEBOUNCE) 561 1.1 bsh sc->debounce_counter = 0; 562 1.1 bsh 563 1.1 bsh /* start debounce timer */ 564 1.1 bsh callout_reset(&sc->callout, DEBOUNCE_TICKS, kmkbd_debounce, sc); 565 1.1 bsh break; 566 1.1 bsh case ST_KEY_PRESSED: 567 1.1 bsh /* start timer to check key release */ 568 1.1 bsh callout_reset(&sc->callout, RELEASE_WATCH_TICKS, kmkbd_watch, sc); 569 1.1 bsh break; 570 1.1 bsh case ST_ALL_UP: 571 1.1 bsh if (sc->state != ST_ALL_UP){ 572 1.1 bsh bus_space_tag_t iot = osc->sc_iot; 573 1.1 bsh bus_space_handle_t ioh = osc->sc_obioreg_ioh; 574 1.1 bsh 575 1.1 bsh obio_intr_unmask(osc, sc->ih); 576 1.1 bsh bus_space_write_2(iot, ioh, G42XXEB_KEYSCAN, 0); 577 1.1 bsh } 578 1.1 bsh break; 579 1.1 bsh case ST_INIT: 580 1.1 bsh ; /* Nothing to do */ 581 1.1 bsh } 582 1.1 bsh 583 1.1 bsh sc->state = new_state; 584 1.1 bsh } 585