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