[Balloon-svn] r1898 - balloon/branches/menuconfig2/package/k…

トップ ページ
添付ファイル:
Eメールのメッセージ
+ (text/plain)
このメッセージを削除
このメッセージに返信
著者: subversion@balloonboard.org
日付:  
To: balloon-svn
題目: [Balloon-svn] r1898 - balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4
Author: nick
Date: 2012-06-12 17:05:16 +0100 (Tue, 12 Jun 2012)
New Revision: 1898

Modified:
balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/balloon3config-bubble-tt
balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/keyboard-tt.patch
Log:
update keyboard for led handling. Kernel config to include devtmpfs for udev in buildroot 20012.05

Modified: balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/balloon3config-bubble-tt
===================================================================
--- balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/balloon3config-bubble-tt    2012-06-11 15:54:25 UTC (rev 1897)
+++ balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/balloon3config-bubble-tt    2012-06-12 16:05:16 UTC (rev 1898)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux/arm 2.6.39.4 Kernel Configuration
-# Mon May 14 18:11:17 2012
+# Tue Jun 12 10:01:07 2012
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -694,7 +694,8 @@
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_DEVTMPFS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y


Modified: balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/keyboard-tt.patch
===================================================================
--- balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/keyboard-tt.patch    2012-06-11 15:54:25 UTC (rev 1897)
+++ balloon/branches/menuconfig2/package/kernel/patches/2.6.39.4/keyboard-tt.patch    2012-06-12 16:05:16 UTC (rev 1898)
@@ -1,25 +1,24 @@
 Index: linux-2.6.39.4/drivers/input/keyboard/Kconfig
 ===================================================================
---- linux-2.6.39.4.orig/drivers/input/keyboard/Kconfig    2012-06-01 10:11:48.000000000 +0100
-+++ linux-2.6.39.4/drivers/input/keyboard/Kconfig    2012-06-01 10:14:51.000000000 +0100
-@@ -530,4 +530,13 @@
+--- linux-2.6.39.4.orig/drivers/input/keyboard/Kconfig    2011-08-03 20:43:28.000000000 +0100
++++ linux-2.6.39.4/drivers/input/keyboard/Kconfig    2012-06-08 11:48:06.000000000 +0100
+@@ -530,4 +530,12 @@
        To compile this driver as a module, choose M here: the
        module will be called w90p910_keypad.


 +config KEYBOARD_TT
-+    tristate "Bubble-TT Keyboard support"
++    tristate "Bubble SPI Keyboard support"
 +    depends on MACH_BALLOON3_BUBBLE && SAMOSA
 +    help
-+      Say Y here to enable the keyboard on Bubble-tt
++      Say Y here to enable the keyboard on Bubble
 +
 +      To compile this driver as a module, choose M here: the
 +      module will be called tt-keyboard.
-+
  endif
 Index: linux-2.6.39.4/drivers/input/keyboard/Makefile
 ===================================================================
---- linux-2.6.39.4.orig/drivers/input/keyboard/Makefile    2012-06-01 10:11:48.000000000 +0100
-+++ linux-2.6.39.4/drivers/input/keyboard/Makefile    2012-06-01 10:14:51.000000000 +0100
+--- linux-2.6.39.4.orig/drivers/input/keyboard/Makefile    2011-08-03 20:43:28.000000000 +0100
++++ linux-2.6.39.4/drivers/input/keyboard/Makefile    2012-06-07 10:36:33.000000000 +0100
 @@ -48,3 +48,4 @@
  obj-$(CONFIG_KEYBOARD_TWL4030)        += twl4030_keypad.o
  obj-$(CONFIG_KEYBOARD_XTKBD)        += xtkbd.o
@@ -28,8 +27,8 @@
 Index: linux-2.6.39.4/drivers/input/keyboard/tt-keyboard.c
 ===================================================================
 --- /dev/null    1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.39.4/drivers/input/keyboard/tt-keyboard.c    2012-06-01 13:10:53.000000000 +0100
-@@ -0,0 +1,431 @@
++++ linux-2.6.39.4/drivers/input/keyboard/tt-keyboard.c    2012-06-08 16:41:45.000000000 +0100
+@@ -0,0 +1,696 @@
 +/*
 + * Balloon3 Bubble TT Keyboard Controller Driver
 + * Based on OpenCores keyboard controller
@@ -50,12 +49,19 @@
 +#include <linux/spi/spi.h>
 +#include <linux/spi/spi_tt.h>
 +#include <linux/samosa_device.h>
++#include <linux/input/matrix_keypad.h>
 +
 +#include <mach/balloon3.h>
 +
 +#include <linux/workqueue.h>
 +#include <linux/delay.h>
 +
++#define KBD_ROWS 8
++#define KBD_COLS 8
++#define KBD_LIGHTS_REG 0x10
++#define KBD_KEY_LIGHT_REG 0x11
++
++
 +struct tt_kbd {
 +    struct spi_device *spi;
 +    struct spi_message spi_msg;
@@ -68,22 +74,112 @@
 +    int switch_up;
 +    int joystick_down;
 +    int joystick_up;
-+    int read_id;
 +    struct work_struct kbd_wq;
++    int debug;
++    unsigned short spi_keycodes[KBD_ROWS][KBD_COLS];
++    unsigned char colours[KBD_ROWS][KBD_COLS];
++    unsigned char colours_buffer[KBD_ROWS][KBD_COLS];
++    u8 keyboard_id;
++    unsigned int keyboard_keymask[8];
 +};
 +
-+static u8 keyboard_id;
-+static unsigned int keyboard_keymask[8];
++static ssize_t
++show_debug(struct device *dev, struct device_attribute *attr, char *buf)
++{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    return sprintf(buf, "debug = %d\n", kbd ? kbd->debug : 0);
++}
 +
 +static ssize_t
++set_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    if (kbd) {
++        unsigned long debug;
++        int res = kstrtol(buf, 10, &debug);
++        if (res == 0)
++            kbd->debug = debug;
++    }
++    return count;
++}
++
++static DEVICE_ATTR(debug, S_IRUGO | S_IWUSR, show_debug, set_debug);
++
++static ssize_t
++show_keymap(struct device *dev, struct device_attribute *attr, char *buf)
++{
++    return sprintf(buf, "swift sl40-48 sl40-52\n");
++}
++
++static int setKeymap(struct tt_kbd* kbd, const char *map_name);
++
++static ssize_t
++set_keymap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    pr_info("%s: setting keymap to <%s> %s\n",__func__, buf, (setKeymap(kbd, buf) == 0) ? "succeded":"failed");
++    return count;
++}
++
++static DEVICE_ATTR(keymap, S_IRUGO | S_IWUSR, show_keymap, set_keymap);
++
++static void setLed(struct tt_kbd *kbd, unsigned int row, unsigned int col, unsigned int colour, int sync);
++static void syncLeds(struct tt_kbd *kbd);
++
++static ssize_t
++show_leds(struct device *dev, struct device_attribute *attr, char *buf)
++{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    ssize_t count = sprintf(buf, "led colours ...\n");
++    int row, col;
++    for (row = 0; row < KBD_ROWS; row++) {
++        for (col = 0; col < KBD_COLS; col++)
++            count += sprintf(buf + count, "%2.2x ", kbd->colours[row][col]);
++        count += sprintf(buf + count, "\n");
++    }
++    return count;
++}
++
++static char *skipws(char *ptr) {
++    while (*ptr==' ')
++        ptr++;
++    return ptr;
++}
++
++static ssize_t
++set_leds(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    char *ptr;
++    int colour = simple_strtol(buf, &ptr, 10);
++    while (ptr != buf) {
++        int row;
++        buf = skipws(ptr);
++        row = simple_strtol(buf, &ptr, 10);
++        if (ptr != buf) {
++            int col;
++            buf = skipws(ptr);
++            col = simple_strtol(buf, &ptr, 10);
++            if (buf != ptr) {
++                setLed(kbd, row, col, colour, 0);
++            }
++        }
++    }
++    syncLeds(kbd);
++    return count;
++}
++
++static DEVICE_ATTR(leds, S_IRUGO | S_IWUSR, show_leds, set_leds);
++
++static ssize_t
 +show_keymask(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +    struct tt_kbd *kbd = dev_get_drvdata(dev);
 +
 +    return sprintf(buf, "dev %p, kbd %p, kbd->spi %p, 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
 +        dev, kbd, kbd->spi,
-+        keyboard_keymask[0], keyboard_keymask[1], keyboard_keymask[2], keyboard_keymask[3],
-+        keyboard_keymask[4], keyboard_keymask[5], keyboard_keymask[6], keyboard_keymask[7]);
++        kbd->keyboard_keymask[0], kbd->keyboard_keymask[1], kbd->keyboard_keymask[2], kbd->keyboard_keymask[3],
++        kbd->keyboard_keymask[4], kbd->keyboard_keymask[5], kbd->keyboard_keymask[6], kbd->keyboard_keymask[7]);
 +}
 +
 +static void maskKey(struct spi_device *dev, int row, int col);
@@ -94,14 +190,14 @@
 +{
 +    struct tt_kbd *kbd = dev_get_drvdata(dev);
 +    int args = sscanf(buf,"%u %u %u %u %u %u %u %u",
-+        &keyboard_keymask[0], &keyboard_keymask[1], &keyboard_keymask[2], &keyboard_keymask[3],
-+        &keyboard_keymask[4], &keyboard_keymask[5], &keyboard_keymask[6], &keyboard_keymask[7]);
++        &kbd->keyboard_keymask[0], &kbd->keyboard_keymask[1], &kbd->keyboard_keymask[2], &kbd->keyboard_keymask[3],
++        &kbd->keyboard_keymask[4], &kbd->keyboard_keymask[5], &kbd->keyboard_keymask[6], &kbd->keyboard_keymask[7]);
 +    if (args == 8) {
 +        int row;
-+        for (row = 0; row < 8; row++) {
++        for (row = 0; row < KBD_ROWS; row++) {
 +            int col;
-+            for (col = 0; col < 8; col++) {
-+                if (keyboard_keymask[row] & (1 << col))
++            for (col = 0; col < KBD_COLS; col++) {
++                if (kbd->keyboard_keymask[row] & (1 << col))
 +                    maskKey(kbd->spi, row, col);
 +                else
 +                    unmaskKey(kbd->spi, row,col);
@@ -118,7 +214,8 @@
 +static ssize_t
 +show_id(struct device *dev, struct device_attribute *attr, char *buf)
 +{
-+    return sprintf(buf, "0x%x\n", keyboard_id);
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    return sprintf(buf, "0x%x\n", kbd->keyboard_id);
 +}
 +
 +static DEVICE_ATTR(kbd_id, S_IRUGO, show_id, NULL);
@@ -184,16 +281,29 @@
 +    msleep(1);
 +}
 +
-+static unsigned short keycodes[16] = {
-+        KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_UP, KEY_KPENTER, KEY_G, KEY_H, KEY_I,
-+        KEY_LEFTMETA, KEY_ESC, KEY_ENTER, KEY_INSERT, KEY_COMPOSE, KEY_6, KEY_7, KEY_8
++static unsigned short tt_keycodes[KBD_ROWS][KBD_COLS] = {
++{0, 0, 0, 0,  0, 0, 0, 0},
++{0, 0, 0, 0,  0, 0, 0, 0},
++{0, 0, 0, 0,  0, 0, 0, 0},
++{0, 0, 0, 0,  0, 0, 0, 0},
++{0, 0, 0, 0,  0, 0, 0, 0},
++{0, 0, 0, 0,  0, 0, 0, 0},
++{KEY_ESC, KEY_COMPOSE, KEY_LEFTMETA, KEY_INSERT, KEY_ENTER, 0, 0, 0},
++{KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_LEFT, 0, 0, 0, KEY_KPENTER}
 +};
 +
-+static unsigned short ss_keycodes[1] = {
-+        KEY_POWER
++static unsigned short sl40_48_keycodes[KBD_ROWS][KBD_COLS] = {
++{KEY_7, KEY_6, KEY_5, KEY_4,  KEY_3, KEY_2, KEY_1, 0},
++{KEY_U, KEY_Y, KEY_T, KEY_R,  KEY_E, KEY_W, KEY_Q, 0},
++{KEY_J, KEY_H, KEY_G, KEY_F,  KEY_D, KEY_S, KEY_A, 0},
++{KEY_Z, KEY_X, KEY_C, KEY_V,  KEY_B, KEY_N, KEY_M, 0},
++{KEY_8, KEY_9, KEY_0, KEY_DOT,  KEY_QUESTION, KEY_SPACE, KEY_SOUND, 0},
++{0, KEY_0, KEY_0, KEY_LEFTSHIFT,  KEY_S, KEY_KPPLUS, KEY_L, 0},
++{KEY_ESC, KEY_COMPOSE, KEY_LEFTMETA, KEY_INSERT, KEY_ENTER, 0, 0, 0},
++{KEY_A, KEY_B, KEY_C, KEY_D, 0, 0, 0, KEY_KPENTER}
 +};
 +
-+static unsigned short spi_keycodes[8][8] = {
++static unsigned short sl40_52_keycodes[KBD_ROWS][KBD_COLS] = {
 +{0, 0, 0, 0,  0, 0, 0, 0},
 +{0, 0, 0, 0,  0, 0, 0, 0},
 +{0, 0, 0, 0,  0, 0, 0, 0},
@@ -201,23 +311,83 @@
 +{0, 0, 0, 0,  0, 0, 0, 0},
 +{0, 0, 0, 0,  0, 0, 0, 0},
 +{KEY_ESC, KEY_COMPOSE, KEY_LEFTMETA, KEY_INSERT, KEY_ENTER, 0, 0, 0},
-+{KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_LEFT, 0, 0, 0, KEY_KPENTER},        // joystick
++{KEY_1, KEY_2, KEY_3, KEY_4, 0, 0, 0, KEY_KPENTER}
 +};
 +
-+static void suspendKeys(struct spi_device *dev) {
++static int setKeymap(struct tt_kbd* kbd, const char *map_name) {
++    int res = 0;
++    unsigned short *map = NULL;
++    if (strncmp(map_name,"swift",5) == 0)
++        map = &tt_keycodes[0][0];
++    else if (strncmp(map_name, "sl40-48",7) == 0)
++        map = &sl40_48_keycodes[0][0];
++    else if (strncmp(map_name, "sl40-52",7) == 0)
++        map = &sl40_52_keycodes[0][0];
++    else
++        res = -1;
++    if (kbd && map && (res == 0)) {
++        int row, col;
++        memcpy(kbd->spi_keycodes, map, sizeof(kbd->spi_keycodes));
++        for (row = 0; row < KBD_ROWS; row++) {
++            for (col = 0; col < KBD_COLS; col++) {
++                __set_bit(kbd->spi_keycodes[row][col], kbd->input->keybit);
++            }
++        }
++    }
++    return res;
++}
++
++static void setLed(struct tt_kbd *kbd, unsigned int row, unsigned int col, unsigned int colour, int sync) {
++    if ((row < KBD_ROWS) && (col < KBD_COLS)) {
++        kbd->colours_buffer[row][col] = colour;
++        if (kbd->debug)
++            pr_info("%s: colour_buffer row %d col %d set to colour %d\n", __func__, row, col, colour);
++        if (sync) {
++            kbd->colours[row][col] = colour;
++            if (kbd->debug)
++                pr_info("%s: colours row %d col %d set to colour %d too and written to atmel\n", __func__, row, col, colour);
++            spiWriteRegData(kbd->spi, KBD_LIGHTS_REG, colour);
++            spiWriteRegData(kbd->spi, KBD_KEY_LIGHT_REG, (row << 4) | col);
++        }
++    }
++}
++
++static void syncLeds(struct tt_kbd *kbd) {
++    int row, col, colour;
++    colour = -1;
++    for (row = 0; row < KBD_ROWS; row++) {
++        for (col = 0; col < KBD_COLS; col++) {
++            int temp = kbd->colours_buffer[row][col];
++            if (kbd->colours[row][col] != temp) {
++                if (colour != temp) {
++                    colour = temp;
++                    if (kbd->debug)
++                        pr_info("%s: setting colour to 0x%x\n", __func__, colour);
++                    spiWriteRegData(kbd->spi, KBD_LIGHTS_REG, colour);
++                }
++                kbd->colours[row][col] = temp;
++                if (kbd->debug)
++                    pr_info("%s: setting colour for row %d col %d\n", __func__, row, col);
++                spiWriteRegData(kbd->spi, KBD_KEY_LIGHT_REG, (row << 4) | col);
++            }
++        }
++    }
++}
++
++static void suspendKeys(struct tt_kbd *kbd) {
 +    int row, col;
-+    for (row = 6; row < 8; row++) {
-+        for (col = 0; col < 8; col++)
-+            if (spi_keycodes[row][col] != KEY_LEFTMETA)
-+                maskKey(dev, row, col);
++    for (row = 6; row < KBD_ROWS; row++) {
++        for (col = 0; col < KBD_COLS; col++)
++            if (kbd->spi_keycodes[row][col] != KEY_LEFTMETA)
++                maskKey(kbd->spi, row, col);
 +    }
 +}
 +
-+static void resumeKeys(struct spi_device *dev) {
++static void resumeKeys(struct tt_kbd *kbd) {
 +    int row, col;
-+    for (row = 6; row < 8; row++) {
-+        for (col = 0; col < 8; col++)
-+            unmaskKey(dev, row, col);
++    for (row = 6; row < KBD_ROWS; row++) {
++        for (col = 0; col < KBD_COLS; col++)
++            unmaskKey(kbd->spi, row, col);
 +    }
 +}
 +
@@ -240,18 +410,40 @@
 +    }
 +    updown = spiReadReg(tt_kbd->spi,0);
 +    rc = spiReadReg(tt_kbd->spi,1);
-+    key = spi_keycodes[(rc >> 4) & 0x7][rc & 0x7];
++    key = tt_kbd->spi_keycodes[(rc >> 4) & 0x7][rc & 0x7];
++    if (tt_kbd->debug)
++        pr_info("%s: updown = %d, rc = 0x%x, key = %d\n", __func__, updown, rc, key);
 +    // check that 'updown' has non-zero in bottom four bits
 +    // indicating that this is a real keypress
-+    if(updown & 0x0f) {
-+        if (key)
-+            input_report_key(input, key ,(updown & 0x80) ? 0:1);
++    if (updown & 0x0f) {
++        unsigned int row = rc >> 4;
++        unsigned int col = rc & 0x7;
++        unsigned int code = MATRIX_SCAN_CODE(row, col, 8);
++//    unsigned int key = keypad->keymap[code];
++        input_event(input, EV_MSC, MSC_SCAN, code);
++        if (key) {
++            int down = (updown & 0x80) == 0;
++            input_report_key(input, key ,down ? 1:0);
++            if (down)
++                input_event(input, EV_SND, SND_CLICK, down);
++            if (key == KEY_LEFT) {
++                input_event(input, EV_LED, LED_MISC, down ? 100:10);
++                input_event(input, EV_MSC, MSC_PULSELED, down ? 100:10);
++            }
++            else if (key == KEY_RIGHT) {
++                input_event(input, EV_LED, LED_MISC, down ? 50:5);
++                input_event(input, EV_MSC, MSC_PULSELED, down ? 50:5);
++            }
++        }
++        input_sync(input);
 +    }
++    else
++        pr_info("%s: unexpected interrupt\nupdown = %d, rc = 0x%x, key = %d\n", __func__, updown, rc, key);
 +
-+    if (tt_kbd->read_id) {
-+        keyboard_id = spiReadReg(tt_kbd->spi,0xf);
-+        pr_info("%s: read keyboard id returns 0x%x\n",__func__, keyboard_id);
-+        tt_kbd->read_id = 0;
++    if (!tt_kbd->keyboard_id) {
++        tt_kbd->keyboard_id = spiReadReg(tt_kbd->spi,0xf);
++        if (tt_kbd->debug)
++            pr_info("%s: read keyboard id returns 0x%x\n",__func__, tt_kbd->keyboard_id);
 +    }
 +
 +}
@@ -271,11 +463,63 @@
 +    return IRQ_HANDLED;
 +}
 +
++/*
++ * tt_kbd_event() handles events from the input module.
++ */
++static int tt_kbd_event(struct input_dev *dev,
++            unsigned int type, unsigned int code, int value)
++{
++    struct tt_kbd *kbd = input_get_drvdata(dev);
++
++    switch (type) {
++    case EV_MSC:
++        switch (code) {
++        case MSC_PULSELED:
++            if (kbd->debug)
++                pr_info("%s: pulse led! value = %d\n", __func__, value);
++            return 0;
++        }
++        break;
++        break;
++
++    case EV_LED:
++        switch (code) {
++        case LED_MISC:
++            if (kbd->debug)
++                pr_info("%s: led misc! value = %d\n", __func__, value);
++            return 0;
++        }
++        break;
++
++    case EV_SND:
++        switch (code) {
++        case SND_CLICK:
++            if (kbd->debug)
++                pr_info("%s: click!\n", __func__);
++            return 0;
++
++        case SND_BELL:
++            if (kbd->debug)
++                pr_info("%s: bell! value = %d\n", __func__, value);
++            return 0;
++        }
++
++        break;
++
++    default:
++        printk(KERN_ERR "%s(): Got unknown type %d, code %d, value %d\n",
++            __func__, type, code, value);
++        break;
++    }
++
++    return -1;
++}
++
 +static int __devinit tt_kbd_probe(struct spi_device *dev)
 +{
 +    struct input_dev *input, *ss_input;
 +    struct tt_kbd *tt_kbd;
-+    int i, error;
++    int error;
 +
 +    tt_kbd = kzalloc(sizeof(*tt_kbd), GFP_KERNEL);
 +    input = input_allocate_device();
@@ -296,6 +540,8 @@
 +
 +    tt_kbd->input = input;
 +
++    memcpy(tt_kbd->spi_keycodes, tt_keycodes, sizeof(tt_kbd->spi_keycodes));
++
 +    input->name = "tt-kbd";
 +    input->phys = "tt-kbd/input0";
 +    input->dev.parent = &dev->dev;
@@ -307,15 +553,30 @@
 +    input->id.product = 0x0001;
 +    input->id.version = 0x0100;
 +
-+    input->keycode = keycodes;
-+    input->keycodesize = sizeof(keycodes[0]);
-+    input->keycodemax = ARRAY_SIZE(keycodes);
++//    input->keycode = tt_kbd->spi_keycodes;
++//    input->keycodesize = sizeof(tt_kbd->spi_keycodes[0]);
++//    input->keycodemax = ARRAY_SIZE(tt_kbd->spi_keycodes);
 +
 +    __set_bit(EV_KEY, input->evbit);
-+    for (i = 0; i < ARRAY_SIZE(keycodes); i++)
-+        __set_bit(keycodes[i], input->keybit);
++    {
++        int row, col;
++        for (row = 0; row < KBD_ROWS; row++) {
++            for (col = 0; col < KBD_COLS; col++) {
++                __set_bit(tt_kbd->spi_keycodes[row][col], input->keybit);
++            }
++        }
++    }
 +    __clear_bit(KEY_RESERVED, input->keybit);
++    input_set_capability(input, EV_MSC, MSC_SCAN);
++    input_set_capability(input, EV_MSC, MSC_PULSELED);
++    input_set_capability(input, EV_SND, SND_CLICK);
++    input_set_capability(input, EV_LED, LED_MISC);
 +
++//    matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT,
++//                   input_dev->keycode, input_dev->keybit);
++
++    input->event = tt_kbd_event;
++
 +    // sys_start input
 +    ss_input = input_allocate_device();
 +    tt_kbd->sys_start_input = ss_input;
@@ -331,13 +592,15 @@
 +    ss_input->id.product = 0x0001;
 +    ss_input->id.version = 0x0100;
 +
-+    ss_input->keycode = ss_keycodes;
-+    ss_input->keycodesize = sizeof(ss_keycodes[0]);
-+    ss_input->keycodemax = ARRAY_SIZE(ss_keycodes);
++//    ss_input->keycode = ss_keycodes;
++//    ss_input->keycodesize = sizeof(ss_keycodes[0]);
++//    ss_input->keycodemax = ARRAY_SIZE(ss_keycodes);
 +
 +    __set_bit(EV_KEY, ss_input->evbit);
-+    for (i = 0; i < ARRAY_SIZE(ss_keycodes); i++)
-+        __set_bit(ss_keycodes[i], ss_input->keybit);
++//    for (i = 0; i < ARRAY_SIZE(ss_keycodes); i++)
++//        __set_bit(ss_keycodes[i], ss_input->keybit);
++    __set_bit(KEY_POWER, ss_input->keybit);
++
 +    __clear_bit(KEY_RESERVED, ss_input->keybit);
 +
 +    tt_kbd->sys_start = 0;
@@ -369,20 +632,19 @@
 +
 +    pr_info("%s: read keyboard INT_FLAGS returns %d\n",__func__, spiReadReg(tt_kbd->spi,0));
 +
-+    keyboard_id = spiReadReg(tt_kbd->spi,0xf);
-+    pr_info("%s: read keyboard id returns 0x%x\n",__func__, keyboard_id);
-+    // seems to fail to read during modprobe so do it again
-+    tt_kbd->read_id = 1;
-+// this doesn't seem to work either - returns 255
-+//    schedule_work(&tt_kbd->kbd_wq);
-+
 +    error = sysfs_create_file(&input->dev.kobj, &dev_attr_kbd_id.attr);
 +    if (!error)
 +        error = sysfs_create_file(&input->dev.kobj, &dev_attr_keymask.attr);
++    if (!error)
++        error = sysfs_create_file(&input->dev.kobj, &dev_attr_debug.attr);
++    if (!error)
++        error = sysfs_create_file(&input->dev.kobj, &dev_attr_leds.attr);
++    if (!error)
++        error = sysfs_create_file(&input->dev.kobj, &dev_attr_keymap.attr);
 +    if (error)
 +        dev_err(&dev->dev, "failed to create sysfs entries\n");
 +
-+    resumeKeys(dev);
++    resumeKeys(tt_kbd);
 +    return 0;
 +
 + err_free_irq:
@@ -413,23 +675,25 @@
 +#ifdef CONFIG_PM_SLEEP
 +static int tt_kbd_suspend(struct device *dev)
 +{
-+    suspendKeys(to_spi_device(dev));
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
++    suspendKeys(kbd);
 +    return 0;
 +}
 +
 +static int tt_kbd_resume(struct device *dev)
 +{
++    struct tt_kbd *kbd = dev_get_drvdata(dev);
 +    // this resets all keys to being unmasked as a side effect
 +    // pending reliably fixing the unmask spi write
 +    ttkeypad_reset();
 +    // reset seems insufficient - odd.
 +    // stry a different sledgehammer
 +    msleep(1);
-+    resumeKeys(to_spi_device(dev));
++    resumeKeys(kbd);
 +    msleep(1);
-+    resumeKeys(to_spi_device(dev));
++    resumeKeys(kbd);
 +    msleep(1);
-+    resumeKeys(to_spi_device(dev));
++    resumeKeys(kbd);
 +    return 0;
 +}
 +#endif
@@ -460,4 +724,4 @@
 +
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Nick Bane <>");
-+MODULE_DESCRIPTION("Keyboard driver for Balloon3 Bubble TT Keyboard Controller");
++MODULE_DESCRIPTION("Keyboard driver for Balloon3 Bubble SPI Keyboard Controller");