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