[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     ! 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