[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.2.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>
1.1.1.1.2.1! nbrk       36: #include "keypad.h"
1.1       nbrk       37:
                     38: /* Parameters */
                     39: #define KEYQ_SIZE      32
                     40: #define KEYPAD_IRQ     12
                     41:
                     42: /* Registers for keypad control */
                     43: #define REG_KEYSTS     (*(volatile uint16_t *)0x4000130)
                     44: #define REG_KEYCNT     (*(volatile uint16_t *)0x4000132)
                     45:
                     46: /* KEY_STS/KEY_CNT */
                     47: #define KEY_A          0x0001
                     48: #define KEY_B          0x0002
                     49: #define KEY_SELECT     0x0004
                     50: #define KEY_START      0x0008
                     51: #define KEY_RIGHT      0x0010
                     52: #define KEY_LEFT       0x0020
                     53: #define KEY_UP         0x0040
                     54: #define KEY_DOWN       0x0080
                     55: #define KEY_R          0x0100
                     56: #define KEY_L          0x0200
                     57:
                     58: #define KEY_ALL                0x03ff
                     59:
                     60: /* KEY_CNT value */
                     61: #define KEYIRQ_EN      0x4000  /* 0=Disable, 1=Enable */
                     62: #define KEYIRQ_COND    0x8000  /* 0=Logical OR, 1=Logical AND */
                     63:
                     64: typedef void (*input_func)(u_char);
                     65:
                     66: static int keypad_init(void);
                     67: static int keypad_open(device_t, int);
                     68: static int keypad_close(device_t);
                     69: static int keypad_read(device_t, char *, size_t *, int);
                     70:
                     71: /*
                     72:  * Driver structure
                     73:  */
                     74: struct driver keypad_drv = {
                     75:        /* name */      "GBA Keypad",
                     76:        /* order */     4,
                     77:        /* init */      keypad_init,
                     78: };
                     79:
                     80: static struct devio keypad_io = {
                     81:        /* open */      keypad_open,
                     82:        /* close */     keypad_close,
                     83:        /* read */      keypad_read,
                     84:        /* write */     NULL,
                     85:        /* ioctl */     NULL,
                     86:        /* event */     NULL,
                     87: };
                     88:
                     89: /*
                     90:  * Key map
                     91:  */
                     92: static const u_char key_map[] = {
                     93:        0,
                     94:        'A',            /* A */
                     95:        'B',            /* B */
                     96:        '\t',           /* Select */
                     97:        '\n',           /* Start */
                     98:        K_RGHT,         /* Right */
                     99:        K_LEFT,         /* Left */
                    100:        K_UP,           /* Up */
                    101:        K_DOWN,         /* Down */
                    102:        'R',            /* R */
                    103:        'L',            /* L */
                    104: };
                    105:
                    106: #define KEY_MAX (sizeof(key_map) / sizeof(u_char))
                    107:
                    108: static device_t keypad_dev;    /* Device object */
1.1.1.1.2.1! nbrk      109: static irq_t keypad_irq;       /* Handle for keyboard irq */
1.1       nbrk      110: static int nr_open;            /* Open count */
1.1.1.1.2.1! nbrk      111: static struct event keypad_event;
1.1       nbrk      112:
                    113: static u_char keyq[KEYQ_SIZE]; /* Queue for ascii character */
                    114: static int q_tail;
                    115: static int q_head;
                    116:
                    117: static input_func input_handler;
                    118:
                    119: /*
                    120:  * Keyboard queue operation
                    121:  */
                    122: #define keyq_next(i)    (((i) + 1) & (KEYQ_SIZE - 1))
                    123: #define keyq_empty()    (q_tail == q_head)
                    124: #define keyq_full()     (keyq_next(q_tail) == q_head)
                    125:
                    126: /*
                    127:  * Put one charcter on key queue
                    128:  */
                    129: static void
                    130: keyq_enqueue(u_char c)
                    131: {
                    132:
                    133:        /* Forward key to input handker */
                    134:        if (input_handler)
                    135:                input_handler(c);
                    136:        else {
1.1.1.1.2.1! nbrk      137:                sched_wakeup(&keypad_event);
1.1       nbrk      138:                if (keyq_full())
                    139:                        return;
                    140:                keyq[q_tail] = c;
                    141:                q_tail = keyq_next(q_tail);
                    142:        }
                    143: }
                    144:
                    145: /*
                    146:  * Get one character from key queue
                    147:  */
                    148: static u_char
                    149: keyq_dequeue(void)
                    150: {
                    151:        u_char c;
                    152:
                    153:        c = keyq[q_head];
                    154:        q_head = keyq_next(q_head);
                    155:        return c;
                    156: }
                    157:
                    158: /*
                    159:  * Interrupt service routine
                    160:  */
                    161: static int
                    162: keypad_isr(int irq)
                    163: {
                    164:        uint16_t sts;
                    165:
                    166:        sts = ~REG_KEYSTS & KEY_ALL;
                    167:
                    168:        if (sts == (KEY_SELECT|KEY_START))
                    169:                machine_reset();
                    170:
                    171:        if (sts & KEY_A)
                    172:                keyq_enqueue('A');
                    173:        if (sts & KEY_B)
                    174:                keyq_enqueue('B');
                    175:        if (sts & KEY_SELECT)
                    176:                keyq_enqueue('\t');
                    177:        if (sts & KEY_START)
                    178:                keyq_enqueue('\n');
                    179:        if (sts & KEY_RIGHT)
                    180:                keyq_enqueue(K_RGHT);
                    181:        if (sts & KEY_LEFT)
                    182:                keyq_enqueue(K_LEFT);
                    183:        if (sts & KEY_UP)
                    184:                keyq_enqueue(K_UP);
                    185:        if (sts & KEY_DOWN)
                    186:                keyq_enqueue(K_DOWN);
                    187:        if (sts & KEY_R)
                    188:                keyq_enqueue('R');
                    189:        if (sts & KEY_L)
                    190:                keyq_enqueue('L');
                    191:
                    192:        return 0;
                    193: }
                    194:
                    195: /*
                    196:  * Open
                    197:  */
                    198: static int
                    199: keypad_open(device_t dev, int mode)
                    200: {
                    201:
                    202:        if (input_handler)
                    203:                return EBUSY;
                    204:        if (nr_open > 0)
                    205:                return EBUSY;
                    206:        nr_open++;
                    207:        return 0;
                    208: }
                    209:
                    210: /*
                    211:  * Close
                    212:  */
                    213: static int
                    214: keypad_close(device_t dev)
                    215: {
                    216:
                    217:        if (input_handler)
                    218:                return EBUSY;
                    219:        if (nr_open != 1)
                    220:                return EINVAL;
                    221:        nr_open--;
                    222:        return 0;
                    223: }
                    224:
                    225: /*
                    226:  * Read
                    227:  */
                    228: static int
                    229: keypad_read(device_t dev, char *buf, size_t *nbyte, int blkno)
                    230: {
1.1.1.1.2.1! nbrk      231:        int rc, c;
1.1       nbrk      232:        size_t count;
                    233:
                    234:        if (input_handler)
                    235:                return EBUSY;
                    236:        if (*nbyte == 0)
                    237:                return 0;
                    238:        if (keyq_empty()) {
1.1.1.1.2.1! nbrk      239:                rc = sched_sleep(&keypad_event);
1.1       nbrk      240:                if (rc == SLP_INTR)
                    241:                        return EINTR;
                    242:        }
                    243:        for (count = 0; count < *nbyte; count++) {
                    244:                if (keyq_empty())
                    245:                        break;
1.1.1.1.2.1! nbrk      246:                c = keyq_dequeue();
        !           247:                if (umem_copyout(&c, buf, 1))
        !           248:                        return EFAULT;
1.1       nbrk      249:                buf++;
                    250:        }
                    251:        *nbyte = count;
                    252:        return 0;
                    253: }
                    254:
                    255: /*
                    256:  * Attach input handler for another driver.
                    257:  *
                    258:  * After an input handler is attached, all key event is forwarded
                    259:  * to that handler.
                    260:  */
                    261: void
                    262: keypad_attach(void (*handler)(u_char))
                    263: {
                    264:
                    265:        input_handler = handler;
                    266: }
                    267:
                    268: /*
                    269:  * Initialize
                    270:  */
                    271: int
                    272: keypad_init(void)
                    273: {
                    274:        input_handler = NULL;
                    275:
                    276:        keypad_dev = device_create(&keypad_io, "keypad", DF_CHR);
                    277:        ASSERT(keypad_dev);
                    278:
1.1.1.1.2.1! nbrk      279:        event_init(&keypad_event, "keypad");
        !           280:
1.1       nbrk      281:        /* Disable keypad interrupt */
                    282:        REG_KEYCNT = 0;
                    283:
                    284:        /* Setup isr */
                    285:        keypad_irq = irq_attach(KEYPAD_IRQ, IPL_INPUT, 0, keypad_isr, NULL);
1.1.1.1.2.1! nbrk      286:        ASSERT(keypad_irq != IRQ_NULL);
1.1       nbrk      287:
                    288:        /* Enable interrupt for all key */
                    289:        REG_KEYCNT = KEY_ALL | KEYIRQ_EN;
                    290:        return 0;
                    291: }
                    292:

CVSweb