[BACK]Return to keypad.c CVS log [TXT][DIR] Up to [local] / prex-old / dev / arm / gba

Annotation of prex-old/dev/arm/gba/keypad.c, Revision 1.1

1.1     ! nbrk        1: /*-
        !             2:  * Copyright (c) 2005, Kohsuke Ohtani
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. Neither the name of the author nor the names of any co-contributors
        !            14:  *    may be used to endorse or promote products derived from this software
        !            15:  *    without specific prior written permission.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * keypad.c - GBA keypad driver
        !            32:  */
        !            33:
        !            34: #include <driver.h>
        !            35: #include <prex/keycode.h>
        !            36:
        !            37: /* Parameters */
        !            38: #define KEYQ_SIZE      32
        !            39: #define KEYPAD_IRQ     12
        !            40:
        !            41: /* Registers for keypad control */
        !            42: #define REG_KEYSTS     (*(volatile uint16_t *)0x4000130)
        !            43: #define REG_KEYCNT     (*(volatile uint16_t *)0x4000132)
        !            44:
        !            45: /* KEY_STS/KEY_CNT */
        !            46: #define KEY_A          0x0001
        !            47: #define KEY_B          0x0002
        !            48: #define KEY_SELECT     0x0004
        !            49: #define KEY_START      0x0008
        !            50: #define KEY_RIGHT      0x0010
        !            51: #define KEY_LEFT       0x0020
        !            52: #define KEY_UP         0x0040
        !            53: #define KEY_DOWN       0x0080
        !            54: #define KEY_R          0x0100
        !            55: #define KEY_L          0x0200
        !            56:
        !            57: #define KEY_ALL                0x03ff
        !            58:
        !            59: /* KEY_CNT value */
        !            60: #define KEYIRQ_EN      0x4000  /* 0=Disable, 1=Enable */
        !            61: #define KEYIRQ_COND    0x8000  /* 0=Logical OR, 1=Logical AND */
        !            62:
        !            63: typedef void (*input_func)(u_char);
        !            64:
        !            65: static int keypad_init(void);
        !            66: static int keypad_open(device_t, int);
        !            67: static int keypad_close(device_t);
        !            68: static int keypad_read(device_t, char *, size_t *, int);
        !            69:
        !            70: /*
        !            71:  * Driver structure
        !            72:  */
        !            73: struct driver keypad_drv = {
        !            74:        /* name */      "GBA Keypad",
        !            75:        /* order */     4,
        !            76:        /* init */      keypad_init,
        !            77: };
        !            78:
        !            79: static struct devio keypad_io = {
        !            80:        /* open */      keypad_open,
        !            81:        /* close */     keypad_close,
        !            82:        /* read */      keypad_read,
        !            83:        /* write */     NULL,
        !            84:        /* ioctl */     NULL,
        !            85:        /* event */     NULL,
        !            86: };
        !            87:
        !            88: /*
        !            89:  * Key map
        !            90:  */
        !            91: static const u_char key_map[] = {
        !            92:        0,
        !            93:        'A',            /* A */
        !            94:        'B',            /* B */
        !            95:        '\t',           /* Select */
        !            96:        '\n',           /* Start */
        !            97:        K_RGHT,         /* Right */
        !            98:        K_LEFT,         /* Left */
        !            99:        K_UP,           /* Up */
        !           100:        K_DOWN,         /* Down */
        !           101:        'R',            /* R */
        !           102:        'L',            /* L */
        !           103: };
        !           104:
        !           105: #define KEY_MAX (sizeof(key_map) / sizeof(u_char))
        !           106:
        !           107: static device_t keypad_dev;    /* Device object */
        !           108: static int keypad_irq;         /* Handle for keyboard irq */
        !           109: static int nr_open;            /* Open count */
        !           110: static struct event io_event = EVENT_INIT(io_event, "keypad");
        !           111:
        !           112: static u_char keyq[KEYQ_SIZE]; /* Queue for ascii character */
        !           113: static int q_tail;
        !           114: static int q_head;
        !           115:
        !           116: static input_func input_handler;
        !           117:
        !           118: /*
        !           119:  * Keyboard queue operation
        !           120:  */
        !           121: #define keyq_next(i)    (((i) + 1) & (KEYQ_SIZE - 1))
        !           122: #define keyq_empty()    (q_tail == q_head)
        !           123: #define keyq_full()     (keyq_next(q_tail) == q_head)
        !           124:
        !           125: /*
        !           126:  * Put one charcter on key queue
        !           127:  */
        !           128: static void
        !           129: keyq_enqueue(u_char c)
        !           130: {
        !           131:
        !           132:        /* Forward key to input handker */
        !           133:        if (input_handler)
        !           134:                input_handler(c);
        !           135:        else {
        !           136:                sched_wakeup(&io_event);
        !           137:                if (keyq_full())
        !           138:                        return;
        !           139:                keyq[q_tail] = c;
        !           140:                q_tail = keyq_next(q_tail);
        !           141:        }
        !           142: }
        !           143:
        !           144: /*
        !           145:  * Get one character from key queue
        !           146:  */
        !           147: static u_char
        !           148: keyq_dequeue(void)
        !           149: {
        !           150:        u_char c;
        !           151:
        !           152:        c = keyq[q_head];
        !           153:        q_head = keyq_next(q_head);
        !           154:        return c;
        !           155: }
        !           156:
        !           157: /*
        !           158:  * Interrupt service routine
        !           159:  */
        !           160: static int
        !           161: keypad_isr(int irq)
        !           162: {
        !           163:        uint16_t sts;
        !           164:
        !           165:        sts = ~REG_KEYSTS & KEY_ALL;
        !           166:
        !           167:        if (sts == (KEY_SELECT|KEY_START))
        !           168:                machine_reset();
        !           169:
        !           170:        if (sts & KEY_A)
        !           171:                keyq_enqueue('A');
        !           172:        if (sts & KEY_B)
        !           173:                keyq_enqueue('B');
        !           174:        if (sts & KEY_SELECT)
        !           175:                keyq_enqueue('\t');
        !           176:        if (sts & KEY_START)
        !           177:                keyq_enqueue('\n');
        !           178:        if (sts & KEY_RIGHT)
        !           179:                keyq_enqueue(K_RGHT);
        !           180:        if (sts & KEY_LEFT)
        !           181:                keyq_enqueue(K_LEFT);
        !           182:        if (sts & KEY_UP)
        !           183:                keyq_enqueue(K_UP);
        !           184:        if (sts & KEY_DOWN)
        !           185:                keyq_enqueue(K_DOWN);
        !           186:        if (sts & KEY_R)
        !           187:                keyq_enqueue('R');
        !           188:        if (sts & KEY_L)
        !           189:                keyq_enqueue('L');
        !           190:
        !           191:        return 0;
        !           192: }
        !           193:
        !           194: /*
        !           195:  * Open
        !           196:  */
        !           197: static int
        !           198: keypad_open(device_t dev, int mode)
        !           199: {
        !           200:
        !           201:        if (input_handler)
        !           202:                return EBUSY;
        !           203:        if (nr_open > 0)
        !           204:                return EBUSY;
        !           205:        nr_open++;
        !           206:        return 0;
        !           207: }
        !           208:
        !           209: /*
        !           210:  * Close
        !           211:  */
        !           212: static int
        !           213: keypad_close(device_t dev)
        !           214: {
        !           215:
        !           216:        if (input_handler)
        !           217:                return EBUSY;
        !           218:        if (nr_open != 1)
        !           219:                return EINVAL;
        !           220:        nr_open--;
        !           221:        return 0;
        !           222: }
        !           223:
        !           224: /*
        !           225:  * Read
        !           226:  */
        !           227: static int
        !           228: keypad_read(device_t dev, char *buf, size_t *nbyte, int blkno)
        !           229: {
        !           230:        int rc;
        !           231:        size_t count;
        !           232:
        !           233:        if (input_handler)
        !           234:                return EBUSY;
        !           235:        if (*nbyte == 0)
        !           236:                return 0;
        !           237:        if (keyq_empty()) {
        !           238:                rc = sched_sleep(&io_event);
        !           239:                if (rc == SLP_INTR)
        !           240:                        return EINTR;
        !           241:        }
        !           242:        for (count = 0; count < *nbyte; count++) {
        !           243:                if (keyq_empty())
        !           244:                        break;
        !           245:                *buf = keyq_dequeue();
        !           246:                buf++;
        !           247:        }
        !           248:        *nbyte = count;
        !           249:        return 0;
        !           250: }
        !           251:
        !           252: /*
        !           253:  * Attach input handler for another driver.
        !           254:  *
        !           255:  * After an input handler is attached, all key event is forwarded
        !           256:  * to that handler.
        !           257:  */
        !           258: void
        !           259: keypad_attach(void (*handler)(u_char))
        !           260: {
        !           261:
        !           262:        input_handler = handler;
        !           263: }
        !           264:
        !           265: /*
        !           266:  * Initialize
        !           267:  */
        !           268: int
        !           269: keypad_init(void)
        !           270: {
        !           271:        input_handler = NULL;
        !           272:
        !           273:        keypad_dev = device_create(&keypad_io, "keypad", DF_CHR);
        !           274:        ASSERT(keypad_dev);
        !           275:
        !           276:        /* Disable keypad interrupt */
        !           277:        REG_KEYCNT = 0;
        !           278:
        !           279:        /* Setup isr */
        !           280:        keypad_irq = irq_attach(KEYPAD_IRQ, IPL_INPUT, 0, keypad_isr, NULL);
        !           281:        ASSERT(keypad_irq != -1);
        !           282:
        !           283:        /* Enable interrupt for all key */
        !           284:        REG_KEYCNT = KEY_ALL | KEYIRQ_EN;
        !           285:        return 0;
        !           286: }
        !           287:

CVSweb