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

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

1.1       nbrk        1: /*     $OpenBSD: zaurus_remote.c,v 1.1 2005/11/17 05:26:31 uwe Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/param.h>
                     20: #include <sys/device.h>
                     21: #include <sys/kernel.h>
                     22: #include <sys/limits.h>
                     23: #include <sys/timeout.h>
                     24: #include <sys/systm.h>
                     25:
                     26: #include <dev/wscons/wsconsio.h>
                     27: #include <dev/wscons/wskbdraw.h>
                     28: #include <dev/wscons/wskbdvar.h>
                     29: #include <dev/wscons/wsksymdef.h>
                     30: #include <dev/wscons/wsksymvar.h>
                     31:
                     32: #include <machine/intr.h>
                     33: #include <machine/zaurus_var.h>
                     34:
                     35: #include <arm/xscale/pxa2x0reg.h>
                     36: #include <arm/xscale/pxa2x0_gpio.h>
                     37:
                     38: #include <zaurus/dev/zaurus_scoopvar.h>
                     39: #include <zaurus/dev/zaurus_sspvar.h>
                     40:
                     41: #define RESCAN_INTERVAL                (hz/100)
                     42:
                     43: #define KEY_RELEASE            0       /* button release */
                     44: #define KEY_VOL_DOWN           1
                     45: #define KEY_MUTE               2
                     46: #define KEY_REWIND             3
                     47: #define KEY_VOL_UP             4
                     48: #define KEY_FORWARD            5
                     49: #define KEY_PLAY               6
                     50: #define KEY_STOP               7
                     51: #define KEY_EARPHONE           8
                     52:
                     53: #ifdef DEBUG
                     54: static const char *zrc_keyname[] = {
                     55:        "(release)", "volume down", "mute", "rewind", "volume up",
                     56:        "forward", "play", "stop", "(earphone)"
                     57: };
                     58: #endif
                     59:
                     60: struct zrc_akey {
                     61:        int     min;            /* minimum ADC value or INT_MIN */
                     62:        int     key;            /* remote control key number */
                     63: };
                     64:
                     65: /* Values match the resistors in the CE-RH2 remote control. */
                     66: static const struct zrc_akey zrc_akeytab_c3000[] = {
                     67:        { 238,          KEY_RELEASE  },
                     68:        { 202,          KEY_VOL_DOWN },
                     69:        { 168,          KEY_MUTE     },
                     70:        { 135,          KEY_REWIND   },
                     71:        { 105,          KEY_VOL_UP   },
                     72:        { 74,           KEY_FORWARD  },
                     73:        { 42,           KEY_PLAY     },
                     74:        { 12,           KEY_STOP     },
                     75:        { INT_MIN,      KEY_EARPHONE }
                     76: };
                     77:
                     78: static const struct zrc_akey *zrc_akeytab = zrc_akeytab_c3000;
                     79:
                     80: struct zrc_softc {
                     81:        struct device    sc_dev;
                     82:        struct timeout   sc_to;
                     83:        void            *sc_ih;
                     84:        int              sc_key;        /* being scanned */
                     85:        int              sc_scans;      /* rescan counter */
                     86:        int              sc_noise;      /* discard if too noisy? */
                     87:        int              sc_keydown;    /* currently pressed key */
                     88:        struct device   *sc_wskbddev;
                     89: #ifdef WSDISPLAY_COMPAT_RAWKBD
                     90:        int              sc_rawkbd;
                     91: #endif
                     92: };
                     93:
                     94: int    zrc_match(struct device *, void *, void *);
                     95: void   zrc_attach(struct device *, struct device *, void *);
                     96:
                     97: int    zrc_intr(void *);
                     98: void   zrc_timeout(void *);
                     99: int    zrc_scan(void);
                    100: void   zrc_input(struct zrc_softc *, int, int);
                    101:
                    102: struct cfattach zrc_ca = {
                    103:        sizeof(struct zrc_softc), zrc_match, zrc_attach
                    104: };
                    105:
                    106: struct cfdriver zrc_cd = {
                    107:        NULL, "zrc", DV_DULL
                    108: };
                    109:
                    110: int    zrc_enable(void *, int);
                    111: void   zrc_set_leds(void *, int);
                    112: int    zrc_ioctl(void *, u_long, caddr_t, int, struct proc *);
                    113:
                    114: struct wskbd_accessops zrc_accessops = {
                    115:        zrc_enable,
                    116:        zrc_set_leds,
                    117:        zrc_ioctl,
                    118: };
                    119:
                    120: #define KC(n) KS_KEYCODE(n)
                    121:
                    122: /* XXX what keys should be generated in translated mode? */
                    123: static const keysym_t zrc_keydesc[] = {
                    124:        KC(KEY_VOL_DOWN),       KS_minus,
                    125:        KC(KEY_MUTE),           KS_m,
                    126:        KC(KEY_REWIND),         KS_b,
                    127:        KC(KEY_VOL_UP),         KS_plus,
                    128:        KC(KEY_FORWARD),        KS_f,
                    129:        KC(KEY_PLAY),           KS_p,
                    130:        KC(KEY_STOP),           KS_s,
                    131: };
                    132:
                    133: #ifdef WSDISPLAY_COMPAT_RAWKBD
                    134: #define        RAWKEY_AudioRewind      0xa0
                    135: #define        RAWKEY_AudioForward     0xa1
                    136: #define        RAWKEY_AudioPlay        0xa2
                    137: #define        RAWKEY_AudioStop        0xa3
                    138: static const keysym_t zrc_xt_keymap[] = {
                    139:        /* KC(KEY_RELEASE), */  RAWKEY_Null,
                    140:        /* KC(KEY_VOL_DOWN), */ RAWKEY_AudioLower,
                    141:        /* KC(KEY_MUTE), */     RAWKEY_AudioMute,
                    142:        /* KC(KEY_REWIND), */   RAWKEY_AudioRewind,
                    143:        /* KC(KEY_VOL_UP), */   RAWKEY_AudioRaise,
                    144:        /* KC(KEY_FORWARD), */  RAWKEY_AudioForward,
                    145:        /* KC(KEY_PLAY), */     RAWKEY_AudioPlay,
                    146:        /* KC(KEY_STOP), */     RAWKEY_AudioStop,
                    147: };
                    148: #endif
                    149:
                    150: static const struct wscons_keydesc zrc_keydesctab[] = {
                    151:         {KB_US, 0, sizeof(zrc_keydesc)/sizeof(keysym_t), zrc_keydesc},
                    152:         {0, 0, 0, 0}
                    153: };
                    154:
                    155: struct wskbd_mapdata zrc_keymapdata = {
                    156:        zrc_keydesctab, KB_US
                    157: };
                    158:
                    159:
                    160: int
                    161: zrc_match(struct device *parent, void *match, void *aux)
                    162: {
                    163:        return (ZAURUS_ISC3000);
                    164: }
                    165:
                    166: void
                    167: zrc_attach(struct device *parent, struct device *self, void *aux)
                    168: {
                    169:        struct zrc_softc *sc = (struct zrc_softc *)self;
                    170:        struct wskbddev_attach_args a;
                    171:
                    172:        /* Configure remote control interrupt handling. */
                    173:        timeout_set(&sc->sc_to, zrc_timeout, sc);
                    174:        pxa2x0_gpio_set_function(C3000_RC_IRQ_PIN, GPIO_IN);
                    175:        sc->sc_ih = pxa2x0_gpio_intr_establish(C3000_RC_IRQ_PIN,
                    176:            IST_EDGE_BOTH, IPL_BIO, zrc_intr, sc, "zrc");
                    177:
                    178:        /* Enable the pullup while waiting for an interrupt. */
                    179:        scoop_akin_pullup(1);
                    180:
                    181:        sc->sc_keydown = KEY_RELEASE;
                    182:
                    183:        printf(": CE-RH2 remote control\n");
                    184:
                    185:        a.console = 0;
                    186:        a.keymap = &zrc_keymapdata;
                    187:        a.accessops = &zrc_accessops;
                    188:        a.accesscookie = sc;
                    189:
                    190:        sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
                    191: }
                    192:
                    193: int
                    194: zrc_intr(void *v)
                    195: {
                    196:        struct zrc_softc *sc = v;
                    197:
                    198:        /* just return if remote control isn't present */
                    199:
                    200:        pxa2x0_gpio_intr_mask(sc->sc_ih);
                    201:        scoop_akin_pullup(0);
                    202:        sc->sc_key = zrc_scan();
                    203:        sc->sc_scans = 0;
                    204:        sc->sc_noise = 0;
                    205:        timeout_add(&sc->sc_to, RESCAN_INTERVAL);
                    206:        return (1);
                    207: }
                    208:
                    209: void
                    210: zrc_timeout(void *v)
                    211: {
                    212:        struct zrc_softc *sc = v;
                    213:        int     key;
                    214:
                    215:        key = zrc_scan();
                    216:        switch (sc->sc_scans) {
                    217:        case 0:
                    218:        case 1:
                    219:        case 2:
                    220:                /* wait for a stable read */
                    221:                if (sc->sc_key == key)
                    222:                        sc->sc_scans++;
                    223:                else {
                    224:                        sc->sc_key = key;
                    225:                        sc->sc_scans = 0;
                    226:                        sc->sc_noise++;
                    227:                }
                    228:                timeout_add(&sc->sc_to, RESCAN_INTERVAL);
                    229:                break;
                    230:        case 3:
                    231:                /* generate key press event */
                    232:                if (sc->sc_key != key) {
                    233:                        key = sc->sc_key;
                    234:                        sc->sc_noise++;
                    235:                }
                    236:                sc->sc_scans++;
                    237:                switch (key) {
                    238:                case KEY_EARPHONE:
                    239:                case KEY_RELEASE:
                    240:                        sc->sc_scans = 6;
                    241:                        break;
                    242:                default:
                    243: #ifdef DEBUG
                    244:                        printf("%s pressed (%d noise)\n", zrc_keyname[key],
                    245:                            sc->sc_noise);
                    246: #endif
                    247:                        sc->sc_keydown = key;
                    248:                        sc->sc_noise = 0;
                    249:                        zrc_input(sc, key, 1);
                    250:                        break;
                    251:                }
                    252:                timeout_add(&sc->sc_to, RESCAN_INTERVAL);
                    253:                break;
                    254:        case 4:
                    255:        case 5:
                    256:                /* wait for key release, permit noise */
                    257:                if (sc->sc_key == key) {
                    258:                        if (sc->sc_scans == 5)
                    259:                                sc->sc_noise++;
                    260:                        sc->sc_scans = 4;
                    261:                } else
                    262:                        sc->sc_scans++;
                    263:                timeout_add(&sc->sc_to, RESCAN_INTERVAL);
                    264:                break;
                    265:        case 6:
                    266:                /* generate key release event */
                    267:                if (sc->sc_keydown != KEY_RELEASE) {
                    268:                        zrc_input(sc, sc->sc_keydown, 0);
                    269: #ifdef DEBUG
                    270:                        printf("%s released (%d noise)\n",
                    271:                            zrc_keyname[sc->sc_keydown], sc->sc_noise);
                    272: #endif
                    273:                        sc->sc_keydown = KEY_RELEASE;
                    274:                }
                    275:                /* FALLTHROUGH */
                    276:        default:
                    277:                /* unmask interrupt again */
                    278:                timeout_del(&sc->sc_to);
                    279:                sc->sc_scans = 7;
                    280:                scoop_akin_pullup(1);
                    281:                pxa2x0_gpio_intr_unmask(sc->sc_ih);
                    282:        }
                    283: }
                    284:
                    285: int
                    286: zrc_scan(void)
                    287: {
                    288:        int     val;
                    289:        int     i;
                    290:
                    291: /* XXX MAX1111 command word - also appears in zaurus_apm.c */
                    292: #define MAXCTRL_PD0            (1<<0)
                    293: #define MAXCTRL_PD1            (1<<1)
                    294: #define MAXCTRL_SGL            (1<<2)
                    295: #define MAXCTRL_UNI            (1<<3)
                    296: #define MAXCTRL_SEL_SHIFT      4
                    297: #define MAXCTRL_STR            (1<<7)
                    298:
                    299: #define C3000_ADCCH_ZRC 0
                    300:        val = zssp_read_max1111(MAXCTRL_PD0 | MAXCTRL_PD1 | MAXCTRL_SGL |
                    301:            MAXCTRL_UNI | (C3000_ADCCH_ZRC << MAXCTRL_SEL_SHIFT) |
                    302:            MAXCTRL_STR);
                    303:        for (i = 0; zrc_akeytab[i].min != INT_MIN; i++)
                    304:                if (val >= zrc_akeytab[i].min)
                    305:                        break;
                    306:        return (zrc_akeytab[i].key);
                    307: }
                    308:
                    309: void
                    310: zrc_input(struct zrc_softc *sc, int key, int down)
                    311: {
                    312:        u_int   type = down ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
                    313:        int     s;
                    314:
                    315:        s = spltty();
                    316:
                    317: #ifdef WSDISPLAY_COMPAT_RAWKBD
                    318:        if (sc->sc_rawkbd) {
                    319:                int     c;
                    320:                u_char  cbuf[2];
                    321:                int     ncbuf = 0;
                    322:
                    323:                c = zrc_xt_keymap[key];
                    324:                if (c & 0x80)
                    325:                        cbuf[ncbuf++] = 0xe0;
                    326:                cbuf[ncbuf] = c & 0x7f;
                    327:
                    328:                if (!down)
                    329:                        cbuf[ncbuf] |= 0x80;
                    330:                ncbuf++;
                    331:
                    332:                wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
                    333:        } else
                    334: #endif
                    335:                wskbd_input(sc->sc_wskbddev, type, key);
                    336:
                    337:        splx(s);
                    338: }
                    339:
                    340: int
                    341: zrc_enable(void *v, int on)
                    342: {
                    343:        return (0);
                    344: }
                    345:
                    346: void
                    347: zrc_set_leds(void *v, int on)
                    348: {
                    349: }
                    350:
                    351: int
                    352: zrc_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
                    353: {
                    354: #ifdef WSDISPLAY_COMPAT_RAWKBD
                    355:        struct zrc_softc *sc = v;
                    356: #endif
                    357:
                    358:        switch (cmd) {
                    359:        case WSKBDIO_GTYPE:
                    360:                *(int *)data = WSKBD_TYPE_ZAURUS;
                    361:                return (0);
                    362:        case WSKBDIO_SETLEDS:
                    363:                return (0);
                    364:        case WSKBDIO_GETLEDS:
                    365:                *(int *)data = 0;
                    366:                return (0);
                    367: #ifdef WSDISPLAY_COMPAT_RAWKBD
                    368:        case WSKBDIO_SETMODE:
                    369:                sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
                    370:                return (0);
                    371: #endif
                    372:        }
                    373:        return (-1);
                    374: }

CVSweb