linux/drivers/input/keyboard/maple_keyb.c
<<
>>
Prefs
   1/*
   2 * SEGA Dreamcast keyboard driver
   3 * Based on drivers/usb/usbkbd.c
   4 * Copyright (c) YAEGASHI Takeshi, 2001
   5 * Porting to 2.6 Copyright (c) Adrian McMenamin, 2007 - 2009
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, see the file COPYING, or write
  19 * to the Free Software Foundation, Inc.,
  20 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  21 */
  22
  23#include <linux/kernel.h>
  24#include <linux/slab.h>
  25#include <linux/input.h>
  26#include <linux/module.h>
  27#include <linux/init.h>
  28#include <linux/timer.h>
  29#include <linux/maple.h>
  30
  31/* Very simple mutex to ensure proper cleanup */
  32static DEFINE_MUTEX(maple_keyb_mutex);
  33
  34#define NR_SCANCODES 256
  35
  36MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk");
  37MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
  38MODULE_LICENSE("GPL");
  39
  40struct dc_kbd {
  41        struct input_dev *dev;
  42        unsigned short keycode[NR_SCANCODES];
  43        unsigned char new[8];
  44        unsigned char old[8];
  45};
  46
  47static const unsigned short dc_kbd_keycode[NR_SCANCODES] = {
  48        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B,
  49        KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
  50        KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V,
  51        KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
  52        KEY_7, KEY_8, KEY_9, KEY_0, KEY_ENTER, KEY_ESC, KEY_BACKSPACE,
  53        KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
  54        KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
  55        KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, KEY_SLASH,
  56        KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
  57        KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ,
  58        KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
  59        KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN,
  60        KEY_UP, KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
  61        KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5,
  62        KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, KEY_102ND,
  63        KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
  64        KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22,
  65        KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, KEY_STOP,
  66        KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
  67        KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  68        KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
  69        KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED,
  70        KEY_RESERVED, KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
  71        KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  72        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  73        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  74        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  75        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  76        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  77        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  78        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  79        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  80        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  81        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  82        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  83        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  84        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  85        KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
  86        KEY_RESERVED, KEY_RESERVED, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT,
  87        KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT,
  88        KEY_RIGHTMETA, KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,
  89        KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
  90        KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP,
  91        KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_SCREENLOCK, KEY_REFRESH,
  92        KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
  93};
  94
  95static void dc_scan_kbd(struct dc_kbd *kbd)
  96{
  97        struct input_dev *dev = kbd->dev;
  98        void *ptr;
  99        int code, keycode;
 100        int i;
 101
 102        for (i = 0; i < 8; i++) {
 103                code = i + 224;
 104                keycode = kbd->keycode[code];
 105                input_event(dev, EV_MSC, MSC_SCAN, code);
 106                input_report_key(dev, keycode, (kbd->new[0] >> i) & 1);
 107        }
 108
 109        for (i = 2; i < 8; i++) {
 110                ptr = memchr(kbd->new + 2, kbd->old[i], 6);
 111                code = kbd->old[i];
 112                if (code > 3 && ptr == NULL) {
 113                        keycode = kbd->keycode[code];
 114                        if (keycode) {
 115                                input_event(dev, EV_MSC, MSC_SCAN, code);
 116                                input_report_key(dev, keycode, 0);
 117                        } else
 118                                dev_dbg(&dev->dev,
 119                                        "Unknown key (scancode %#x) released.",
 120                                        code);
 121                }
 122                ptr = memchr(kbd->old + 2, kbd->new[i], 6);
 123                code = kbd->new[i];
 124                if (code > 3 && ptr) {
 125                        keycode = kbd->keycode[code];
 126                        if (keycode) {
 127                                input_event(dev, EV_MSC, MSC_SCAN, code);
 128                                input_report_key(dev, keycode, 1);
 129                        } else
 130                                dev_dbg(&dev->dev,
 131                                        "Unknown key (scancode %#x) pressed.",
 132                                        code);
 133                }
 134        }
 135        input_sync(dev);
 136        memcpy(kbd->old, kbd->new, 8);
 137}
 138
 139static void dc_kbd_callback(struct mapleq *mq)
 140{
 141        struct maple_device *mapledev = mq->dev;
 142        struct dc_kbd *kbd = maple_get_drvdata(mapledev);
 143        unsigned long *buf = (unsigned long *)(mq->recvbuf->buf);
 144
 145        /*
 146         * We should always get the lock because the only
 147         * time it may be locked is if the driver is in the cleanup phase.
 148         */
 149        if (likely(mutex_trylock(&maple_keyb_mutex))) {
 150
 151                if (buf[1] == mapledev->function) {
 152                        memcpy(kbd->new, buf + 2, 8);
 153                        dc_scan_kbd(kbd);
 154                }
 155
 156                mutex_unlock(&maple_keyb_mutex);
 157        }
 158}
 159
 160static int probe_maple_kbd(struct device *dev)
 161{
 162        struct maple_device *mdev;
 163        struct maple_driver *mdrv;
 164        int i, error;
 165        struct dc_kbd *kbd;
 166        struct input_dev *idev;
 167
 168        mdev = to_maple_dev(dev);
 169        mdrv = to_maple_driver(dev->driver);
 170
 171        kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
 172        if (!kbd) {
 173                error = -ENOMEM;
 174                goto fail;
 175        }
 176
 177        idev = input_allocate_device();
 178        if (!idev) {
 179                error = -ENOMEM;
 180                goto fail_idev_alloc;
 181        }
 182
 183        kbd->dev = idev;
 184        memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
 185
 186        idev->name = mdev->product_name;
 187        idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 188        idev->keycode = kbd->keycode;
 189        idev->keycodesize = sizeof(unsigned short);
 190        idev->keycodemax = ARRAY_SIZE(kbd->keycode);
 191        idev->id.bustype = BUS_HOST;
 192        idev->dev.parent = &mdev->dev;
 193
 194        for (i = 0; i < NR_SCANCODES; i++)
 195                __set_bit(dc_kbd_keycode[i], idev->keybit);
 196        __clear_bit(KEY_RESERVED, idev->keybit);
 197
 198        input_set_capability(idev, EV_MSC, MSC_SCAN);
 199
 200        error = input_register_device(idev);
 201        if (error)
 202                goto fail_register;
 203
 204        /* Maple polling is locked to VBLANK - which may be just 50/s */
 205        maple_getcond_callback(mdev, dc_kbd_callback, HZ/50,
 206                MAPLE_FUNC_KEYBOARD);
 207
 208        mdev->driver = mdrv;
 209
 210        maple_set_drvdata(mdev, kbd);
 211
 212        return error;
 213
 214fail_register:
 215        maple_set_drvdata(mdev, NULL);
 216        input_free_device(idev);
 217fail_idev_alloc:
 218        kfree(kbd);
 219fail:
 220        return error;
 221}
 222
 223static int remove_maple_kbd(struct device *dev)
 224{
 225        struct maple_device *mdev = to_maple_dev(dev);
 226        struct dc_kbd *kbd = maple_get_drvdata(mdev);
 227
 228        mutex_lock(&maple_keyb_mutex);
 229
 230        input_unregister_device(kbd->dev);
 231        kfree(kbd);
 232
 233        maple_set_drvdata(mdev, NULL);
 234
 235        mutex_unlock(&maple_keyb_mutex);
 236        return 0;
 237}
 238
 239static struct maple_driver dc_kbd_driver = {
 240        .function = MAPLE_FUNC_KEYBOARD,
 241        .drv = {
 242                .name = "Dreamcast_keyboard",
 243                .probe = probe_maple_kbd,
 244                .remove = remove_maple_kbd,
 245        },
 246};
 247
 248static int __init dc_kbd_init(void)
 249{
 250        return maple_driver_register(&dc_kbd_driver);
 251}
 252
 253static void __exit dc_kbd_exit(void)
 254{
 255        maple_driver_unregister(&dc_kbd_driver);
 256}
 257
 258module_init(dc_kbd_init);
 259module_exit(dc_kbd_exit);
 260