[BACK]Return to zaurus_kbd.c CVS log [TXT][DIR] Up to [local] / sys / arch / zaurus / dev

Annotation of sys/arch/zaurus/dev/zaurus_kbd.c, Revision 1.1.1.1

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

CVSweb