[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

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