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

Annotation of prex/dev/arm/gba/swkbd.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:  * swkbd.c - GBA software keyboard driver
                     32:  */
                     33:
                     34: /**
                     35:  * This driver emulates a generic keyboard by using GBA keypad.
                     36:  *
                     37:  * <Key assign>
                     38:  *
                     39:  * On-screen keyboard:
                     40:  *
                     41:  *  A        : Select pointed key
                     42:  *  B        : Enter key
                     43:  *  Select   : Hide keyboard
                     44:  *  Start    :
                     45:  *  Right    : Move keyboard cursor right
                     46:  *  Left     : Move keyboard cursor left
                     47:  *  Up       : Move keyboard cursor up
                     48:  *  Down     : Move keyboard cursor down
                     49:  *  Button R : Toggle shift state
                     50:  *  Button L : Toggle shift state
                     51:  *
                     52:  * No on-screen keyboard:
                     53:  *
                     54:  *  A        : A key
                     55:  *  B        : B key
                     56:  *  Select   : Show keyboard
                     57:  *  Start    : Enter key
                     58:  *  Right    : Right key
                     59:  *  Left     : Left key
                     60:  *  Up       : Up key
                     61:  *  Down     : Down key
                     62:  *  Button R : R key
                     63:  *  Button L : L Key
                     64:  *
                     65:  */
                     66:
                     67: #include <driver.h>
                     68: #include <prex/keycode.h>
                     69: #include <sys/tty.h>
                     70: #include <console.h>
                     71: #include "lcd.h"
                     72: #include "kbd_img.h"
                     73: #include "keymap.h"
                     74: #include "keypad.h"
                     75:
                     76: /*
                     77:  * Since GBA does not kick interrupt for the button release, we have
                     78:  * to wait for a while after button is pressed. Otherwise, many key
                     79:  * events are queued by one button press.
                     80:  */
                     81: #define CURSOR_WAIT    100     /* 100 msec */
                     82: #define BUTTON_WAIT    200     /* 200 msec */
                     83:
                     84: static int kbd_init(void);
                     85: static int kbd_ioctl(device_t, u_long, void *);
                     86:
                     87: static void move_cursor(void);
                     88:
                     89: /*
                     90:  * Driver structure
                     91:  */
                     92: struct driver kbd_drv = {
                     93:        /* name */      "GBA S/W Keyboard",
                     94:        /* order */     11,
                     95:        /* init */      kbd_init,
                     96: };
                     97:
                     98: static struct devio kbd_io = {
                     99:        /* open */      NULL,
                    100:        /* close */     NULL,
                    101:        /* read */      NULL,
                    102:        /* write */     NULL,
                    103:        /* ioctl */     kbd_ioctl,
                    104:        /* event */     NULL,
                    105: };
                    106:
                    107: static device_t kbd_dev;       /* Device object */
                    108: static struct tty *tty;
                    109: static struct timer kbd_tmr;
                    110:
                    111: /* Meta key status */
                    112: static int shift;
                    113: static int alt;
                    114: static int ctrl;
                    115: static int capslk;
                    116:
                    117: static int kbd_on;
                    118: static int kbd_page;
                    119: static volatile int ignore_key;
                    120: static u_int pos_x, pos_y;
                    121: static int cur_obj;            /* Current object for cursor */
                    122:
                    123: /*
                    124:  * Select keyboard page.
                    125:  *
                    126:  *   Page0 ... Text only
                    127:  *   Page1 ... Text & Normal keyboard
                    128:  *   Page2 ... Text & Shifted keyboard
                    129:  */
                    130: static void
                    131: kbd_select(int page)
                    132: {
                    133:
                    134:        if (page == 0)
                    135:                REG_DISPCNT = 0x0840;   /* only BG3 */
                    136:        else if (page == 1) {
                    137:                REG_DISPCNT = 0x1A40;   /* use BG1&3 */
                    138:                move_cursor();
                    139:        } else {
                    140:                REG_DISPCNT = 0x1C40;   /* use BG2&3 */
                    141:                move_cursor();
                    142:        }
                    143:        kbd_page = page;
                    144: }
                    145:
                    146: /*
                    147:  * Toggle keyboard type: normal or shift.
                    148:  */
                    149: static void
                    150: kbd_toggle(void)
                    151: {
                    152:        int page;
                    153:
                    154:        if (kbd_page == 0)
                    155:                return;
                    156:        if (capslk)
                    157:                page = shift ? 1 : 2;
                    158:        else
                    159:                page = shift ? 2 : 1;
                    160:        kbd_select(page);
                    161: }
                    162:
                    163: /*
                    164:  * Timer call back handler.
                    165:  * Just clear ignoring flag.
                    166:  */
                    167: static void
                    168: kbd_timeout(void *arg)
                    169: {
                    170:
                    171:        ignore_key = 0;
                    172: }
                    173:
                    174: /*
                    175:  * Move cursor to point key.
                    176:  */
                    177: static void
                    178: move_cursor(void)
                    179: {
                    180:        uint16_t *oam = OAM;
                    181:        struct _key_info *ki;
                    182:        int i, x, y;
                    183:
                    184:        ki = (struct _key_info *)&key_info[pos_y][pos_x];
                    185:        x = ki->pos_x + 108;
                    186:        y = pos_y * 8 + 11;
                    187:        i = 0;
                    188:        switch (ki->width) {
                    189:        case 9: i = 0; break;
                    190:        case 11: i = 1; break;
                    191:        case 12: i = 2; break;
                    192:        case 13: i = 3; break;
                    193:        case 15: i = 4; break;
                    194:        case 17: i = 5; break;
                    195:        case 19: i = 6; break;
                    196:        case 53: i = 7; break;
                    197:        }
                    198:        if (i != cur_obj) {
                    199:                oam[cur_obj * 4] = (uint16_t)((oam[cur_obj * 4] & 0xff00) | 160);
                    200:                oam[cur_obj * 4 + 1] = (uint16_t)((oam[cur_obj * 4 + 1] & 0xfe00) | 240);
                    201:                cur_obj = i;
                    202:        }
                    203:        oam[i * 4] = (uint16_t)((oam[i * 4] & 0xff00) | y);
                    204:        oam[i * 4 + 1] = (uint16_t)((oam[i * 4 + 1] & 0xfe00) | x);
                    205: }
                    206:
                    207: /*
                    208:  * Process key press
                    209:  */
                    210: static void
                    211: key_press(void)
                    212: {
                    213:        struct _key_info *ki;
                    214:        u_char ac;
                    215:
                    216:        ki = (struct _key_info *)&key_info[pos_y][pos_x];
                    217:        ac = ki->normal;
                    218:
                    219:        /* Check meta key */
                    220:        switch (ac) {
                    221:        case K_SHFT:
                    222:                shift = !shift;
                    223:                kbd_toggle();
                    224:                return;
                    225:        case K_CTRL:
                    226:                ctrl = !ctrl;
                    227:                return;
                    228:        case K_ALT:
                    229:                alt = !alt;
                    230:                return;
                    231:        case K_CAPS:
                    232:                capslk = !capslk;
                    233:                kbd_toggle();
                    234:                return;
                    235:        }
                    236:        /* Check ctrl & shift state */
                    237:        if (ctrl) {
                    238:                if (ac >= 'a' && ac <= 'z')
                    239:                        ac = ac - 'a' + 0x01;
                    240:                else if (ac == '\\')
                    241:                        ac = 0x1c;
                    242:                else
                    243:                        ac = 0;
                    244:        } else if (kbd_page == 2)
                    245:                ac = ki->shifted;
                    246:
                    247:        if (ac == 0)
                    248:                return;
                    249:
                    250:        /* Check caps lock state */
                    251:        if (capslk) {
                    252:                if (ac >= 'A' && ac <= 'Z')
                    253:                        ac += 'a' - 'A';
                    254:                else if (ac >= 'a' && ac <= 'z')
                    255:                        ac -= 'a' - 'A';
                    256:        }
                    257:
                    258:        /* Check alt key */
                    259:        if (alt)
                    260:                ac |= 0x80;
                    261:
                    262:        /* Insert key to queue */
                    263:        tty_input(ac, tty);
                    264:
                    265:        /* Reset meta status */
                    266:        if (shift) {
                    267:                shift = 0;
                    268:                kbd_toggle();
                    269:        }
                    270:        if (ctrl)
                    271:                ctrl = 0;
                    272:        if (alt)
                    273:                alt = 0;
                    274: }
                    275:
                    276: /*
                    277:  * Input handler
                    278:  * This routine will be called by keypad ISR.
                    279:  */
                    280: static void
                    281: kbd_isr(u_char c)
                    282: {
                    283:        int move = 0;
                    284:        int timeout = BUTTON_WAIT;
                    285:
                    286:        if (ignore_key)
                    287:                return;
                    288:
                    289:        /* Select key */
                    290:        if (c == '\t') {
                    291:                kbd_on = !kbd_on;
                    292:                kbd_select(kbd_on);
                    293:
                    294:                /* Reset meta status */
                    295:                shift = 0;
                    296:                alt = 0;
                    297:                ctrl = 0;
                    298:                capslk = 0;
                    299:                goto out;
                    300:        }
                    301:
                    302:        /* Direct input */
                    303:        if (!kbd_on) {
                    304:                tty_input(c, tty);
                    305:                goto out;
                    306:        }
                    307:
                    308:        switch (c) {
                    309:        case K_LEFT:
                    310:                if (pos_x > 0) {
                    311:                        if (pos_y == 4 && pos_x >=4 && pos_x <= 8) /* Space */
                    312:                                pos_x = 3;
                    313:                        pos_x--;
                    314:                        move = 1;
                    315:                }
                    316:                break;
                    317:        case K_RGHT:
                    318:                if (pos_x < max_x[pos_y]) {
                    319:                        if (pos_y == 4 && pos_x > 3 && pos_x <= 7) /* Space */
                    320:                                pos_x = 8;
                    321:                        pos_x++;
                    322:                        move = 1;
                    323:                }
                    324:                break;
                    325:        case K_UP:
                    326:                if (pos_y > 0 ) {
                    327:                        pos_y--;
                    328:                        move = 1;
                    329:                        if (pos_x > max_x[pos_y])
                    330:                                pos_x = max_x[pos_y];
                    331:                }
                    332:                break;
                    333:        case K_DOWN:
                    334:                if (pos_y < 4) {
                    335:                        pos_y++;
                    336:                        move = 1;
                    337:                        if (pos_x > max_x[pos_y])
                    338:                                pos_x = max_x[pos_y];
                    339:                }
                    340:                break;
                    341:        case 'A':
                    342:                key_press();
                    343:                break;
                    344:        case 'B':
                    345:                tty_input('\n', tty);
                    346:                break;
                    347:        case 'R':
                    348:        case 'L':
                    349:                shift = shift ? 0 : 1;
                    350:                kbd_toggle();
                    351:                break;
                    352:        case '\n':
                    353: #ifdef DEBUG
                    354:                debug_dump(DUMP_THREAD);
                    355:                debug_dump(DUMP_TASK);
                    356:                debug_dump(DUMP_VM);
                    357: #endif
                    358:                break;
                    359:        }
                    360:        if (move) {
                    361:                timeout = CURSOR_WAIT;
                    362:                move_cursor();
                    363:        }
                    364: out:
                    365:        ignore_key = 1;
                    366:        timer_callout(&kbd_tmr, timeout, &kbd_timeout, NULL);
                    367:        return;
                    368: }
                    369:
                    370: /*
                    371:  * I/O control
                    372:  */
                    373: static int
                    374: kbd_ioctl(device_t dev, u_long cmd, void *arg)
                    375: {
                    376:
                    377:        return 0;
                    378: }
                    379:
                    380: /*
                    381:  * Init font
                    382:  */
                    383: static void
                    384: init_kbd_image(void)
                    385: {
                    386:        uint8_t bit;
                    387:        uint16_t val1, val2;
                    388:        uint16_t *pal = BG_PALETTE;
                    389:        uint16_t *tile1 = KBD1_TILE;
                    390:        uint16_t *tile2 = KBD2_TILE;
                    391:        uint16_t *map1 = KBD1_MAP;
                    392:        uint16_t *map2 = KBD2_MAP;
                    393:        int i, j, row, col;
                    394:
                    395:        /* Load tiles for keyboard image */
                    396:        for (i = 0; i < 32; i++)
                    397:                tile1[i] = 0;
                    398:
                    399:        for (i = 0; i < 64 * 12; i++) {
                    400:                bit = 0x01;
                    401:                for (j = 0; j < 4; j++) {
                    402:                        val1 = kbd1_bitmap[i] & bit ? 0xff : 0x03;
                    403:                        val2 = kbd2_bitmap[i] & bit ? 0xff : 0x03;
                    404:                        bit = bit << 1;
                    405:                        val1 |= kbd1_bitmap[i] & bit ? 0xff00 : 0x0300;
                    406:                        val2 |= kbd2_bitmap[i] & bit ? 0xff00 : 0x0300;
                    407:                        bit = bit << 1;
                    408:                        tile1[i * 4 + 32 + j] = val1;
                    409:                        tile2[i * 4 + j] = val2;
                    410:                }
                    411:        }
                    412:
                    413:
                    414:        /* Setup map */
                    415:        i = 1;
                    416:        for (row = 1; row < 7; row++) {
                    417:                for (col = 13; col < 29; col++) {
                    418:                        map1[row * 32 + col] = (uint16_t)i;
                    419:                        map2[row * 32 + col] = (uint16_t)(i + 127);
                    420:                        i++;
                    421:                }
                    422:        }
                    423:
                    424:        pal[3] = RGB(0,0,31);   /* Kbd bg color */
                    425:        pal[255] = RGB(28,28,28);       /* Kbd color */
                    426:
                    427:        /* Setup video */
                    428:        REG_BG1CNT = 0x1284;    /* Size0, 256color, priority0 */
                    429:        REG_BG2CNT = 0x1484;    /* Size0, 256color, priority0 */
                    430:        kbd_select(1);
                    431: }
                    432:
                    433: /*
                    434:  * Initialize keyboard cursor
                    435:  */
                    436: static void
                    437: init_cursor(void)
                    438: {
                    439:        int i, j;
                    440:        uint8_t bit;
                    441:        uint16_t val;
                    442:        uint16_t *oam = OAM;
                    443:        uint16_t *cur = CURSOR_DATA;
                    444:        uint16_t *pal = SPL_PALETTE;
                    445:
                    446:        /* Move out all objects */
                    447:        for (i = 0; i < 128; i++) {
                    448:                oam[0] = 160;
                    449:                oam[1] = 240;
                    450:                oam += 4;
                    451:        }
                    452:        /* Load cursor splite */
                    453:        for (i = 0; i < 64 * 7 + 64 * 8; i++) {
                    454:                bit = 0x01;
                    455:                for (j = 0; j < 4; j++) {
                    456:                        val = cursor_bitmap[i] & bit ? 0xff : 0;
                    457:                        bit = bit << 1;
                    458:                        val |= cursor_bitmap[i] & bit ? 0xff00 : 0;
                    459:                        bit = bit << 1;
                    460:                        cur[i * 4 + j] = val;
                    461:                }
                    462:        }
                    463:
                    464:        /* Setup cursors */
                    465:        oam = OAM;
                    466:        for (i = 0; i < 7; i++) {
                    467:                oam[0] = (uint16_t)(0x6000 + 160); /* 256 color, Horizontal */
                    468:                oam[1] = (uint16_t)(0x8000 + 240); /* 32x16 */
                    469:                oam[2] = (uint16_t)(i * 16); /* Tile number */
                    470:                oam += 4;
                    471:        }
                    472:        /* for space key */
                    473:        oam[0] = 0x6000 + 160; /* 256 color, Horizontal */
                    474:        oam[1] = 0xC000 + 240; /* 64x32 */
                    475:        oam[2] = 112;
                    476:
                    477:        pal[255] = RGB(31,0,0); /* cursor color */
                    478: }
                    479:
                    480: /*
                    481:  * Initialize
                    482:  */
                    483: static int
                    484: kbd_init(void)
                    485: {
                    486:
                    487:        kbd_dev = device_create(&kbd_io, "kbd", DF_CHR);
                    488:        ASSERT(kbd_dev);
                    489:
                    490:        ignore_key = 0;
                    491:        cur_obj = 0;
                    492:        kbd_on = 1;
                    493:        kbd_page = 0;
                    494:        pos_x = 0;
                    495:        pos_y = 0;
                    496:
                    497:        timer_init(&kbd_tmr);
                    498:        init_cursor();
                    499:        init_kbd_image();
                    500:        move_cursor();
                    501:
                    502:        /* Hook keypad isr */
                    503:        keypad_attach(kbd_isr);
                    504:
                    505:        /* Attach to console */
                    506:        console_attach(&tty);
                    507:        return 0;
                    508: }
                    509:

CVSweb