@@ 45,11 45,13 @@
#define WRITE_MASK BIT(7)
#define _KEY_CAPSLOCK BIT(5)
#define _KEY_NUMLOCK BIT(6)
-//#define DEBUG
+#define DEBUG
/* structs */
struct ppbbq10_data {
+ unsigned int is_symed;
unsigned short keymap_norm[NUM_KEYCODES];
+ short keymap_sym[NUM_KEYCODES];
struct i2c_client *client;
struct input_dev *input;
};
@@ 64,6 66,7 @@ static int ppbbq10_poll_kthread(void *data);
static int ppbbq10_probe(struct i2c_client *client);
static void ppbbq10_read_fifo(struct ppbbq10_data *drv_data);
static int ppbbq10_read_reg(struct ppbbq10_data *drv_data, u8 reg, u8 *buf, u8 len);
+static void ppbbq10_report_keyevent(struct ppbbq10_data *drv_data, u8 keystate, u8 keycode);
static void ppbbq10_update_locks(struct ppbbq10_data *drv_data);
static int ppbbq10_write_data(struct ppbbq10_data *drv_data, u8 reg, const u8 *buf, u8 len);
static int ppbbq10_write_reg(struct ppbbq10_data *drv_data, u8 reg);
@@ 113,6 116,49 @@ static unsigned short keymap_norm[NUM_KEYCODES] = {
['\b'] = KEY_BACKSPACE,
['\n'] = KEY_ENTER,
};
+static short keymap_sym[NUM_KEYCODES] = {
+ [0x01] = KEY_UP,
+ [0x02] = KEY_DOWN,
+ [0x03] = KEY_LEFT,
+ [0x04] = KEY_RIGHT,
+ [0x05] = KEY_ENTER,
+ [0x06] = KEY_MENU,
+ [0x07] = KEY_BACK,
+ [26] = KEY_LEFTALT,
+ [27] = KEY_LEFTSHIFT,
+ [28] = KEY_LEFTCTRL,
+ ['A'] = KEY_A,
+ ['B'] = KEY_1 * -1, // (!)
+ ['C'] = KEY_9,
+ ['D'] = KEY_5,
+ ['E'] = KEY_2,
+ ['F'] = KEY_6,
+ ['G'] = KEY_G,
+ ['H'] = KEY_H,
+ ['I'] = KEY_I,
+ ['J'] = KEY_J,
+ ['K'] = KEY_K,
+ ['L'] = KEY_L,
+ ['M'] = KEY_M,
+ ['N'] = KEY_N,
+ ['O'] = KEY_O,
+ ['P'] = KEY_P,
+ ['Q'] = KEY_Q,
+ ['R'] = KEY_3,
+ ['S'] = KEY_4,
+ ['T'] = KEY_T,
+ ['U'] = KEY_U,
+ ['W'] = KEY_1,
+ ['V'] = KEY_V,
+ ['X'] = KEY_8,
+ ['Y'] = KEY_Y,
+ ['Z'] = KEY_7,
+ [' '] = KEY_SPACE,
+ ['~'] = KEY_0,
+ ['$'] = KEY_GRAVE,
+ ['\b'] = KEY_BACKSPACE,
+ ['\n'] = KEY_ENTER,
+};
static struct i2c_board_info ppbbq10_i2c_board_info[] __initdata = {
{ I2C_BOARD_INFO("ppbbq10", 0x1f), /*.irq = gpio_to_irq(11)*/ }
};
@@ 212,7 258,7 @@ ppbbq10_irq_handler(int irq, void *dev_id)
static int ppbbq10_poll_kthread(void *data)
{
while (!kthread_should_stop()) {
- usleep_range(1000 * 10, (1000 * 10) + 1); // 10ms poll
+ usleep_range(1000 * 1, (1000 * 1) + 1); // 5ms poll
ppbbq10_irq_handler(0, NULL);
}
return 0;
@@ 234,6 280,8 @@ ppbbq10_probe(struct i2c_client *client)
drv_data->client = client;
memcpy(drv_data->keymap_norm, keymap_norm, sizeof(drv_data->keymap_norm));
+ memcpy(drv_data->keymap_sym, keymap_sym, sizeof(drv_data->keymap_sym));
+ drv_data->is_symed = 0;
error = ppbbq10_write_reg(drv_data, REG_RST);
if (error)
@@ 276,12 324,14 @@ ppbbq10_probe(struct i2c_client *client)
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0001;
- input->keycode= drv_data->keymap_norm;
+ input->keycode = drv_data->keymap_norm;
input->keycodesize = sizeof(drv_data->keymap_norm[0]);
- input->keycodemax = ARRAY_SIZE(drv_data->keymap_norm);
+ input->keycodemax = ARRAY_SIZE(drv_data->keymap_norm) + ARRAY_SIZE(drv_data->keymap_sym) ;
for (i = 0; i < NUM_KEYCODES; i++)
__set_bit(drv_data->keymap_norm[i], input->keybit);
+ for (i = 0; i < NUM_KEYCODES; i++)
+ __set_bit(drv_data->keymap_sym[i], input->keybit);
__clear_bit(KEY_RESERVED, input->keybit);
@@ 336,22 386,8 @@ ppbbq10_read_fifo(struct ppbbq10_data *drv_data)
__func__, error);
return;
}
-
- pr_debug("%s key %d/%c, state: %d\n",
- __func__, data[1], data[1], data[0]);
-
count -= 1;
-
- if (data[0] == STATE_PRESS || data[0] == STATE_RELEASE) {
- input_event(input, EV_MSC, MSC_SCAN, data[1]);
-
- keycode = drv_data->keymap_norm[data[1]];
- if (keycode == KEY_UNKNOWN) {
- pr_warn("%s code 0x%02X UNKNOWN\n", __func__, data[1]);
- } else {
- input_report_key(input, keycode, data[0] == STATE_PRESS);
- }
- }
+ ppbbq10_report_keyevent(drv_data, data[0], data[1]);
}
input_sync(input);
@@ 380,6 416,52 @@ ppbbq10_read_reg(struct ppbbq10_data *drv_data, u8 reg, u8 *buf, u8 len)
}
static void
+ppbbq10_report_keyevent(struct ppbbq10_data *drv_data, u8 keystate, u8 keycode)
+{
+ unsigned int key_mapped;
+ int send_shift = 0;
+
+ printk(KERN_INFO "%s key %d/%c, state: %d\n", __func__, keycode, keycode, keystate);
+
+ // Determine key_mapped
+ if (drv_data->is_symed) {
+ send_shift = drv_data->keymap_sym[keycode] < 0;
+ key_mapped = abs(drv_data->keymap_sym[keycode]);
+ if (drv_data->is_symed && keystate == STATE_RELEASE) drv_data->is_symed = 0;
+ printk(KERN_INFO "Sending sym'd: %s key %d/%c, state: %d and !! %d and is_shifted %d\n", __func__, keycode, keycode, keystate, drv_data->keymap_sym[keycode], send_shift);
+ } else {
+ key_mapped = drv_data->keymap_norm[keycode];
+ }
+
+ // Reset is_symed after 1 keypress
+ if (drv_data->is_symed && keystate == STATE_RELEASE) drv_data->is_symed = 0;
+
+ // Symbol layer tap, activates symbol for next pressed key
+ if (keycode == 29 && keystate == STATE_RELEASE) {
+ printk(KERN_INFO "SYM press - next key symbol.\n");
+ drv_data->is_symed = 1;
+ } else if (keystate == STATE_PRESS || keystate == STATE_RELEASE) {
+ input_event(drv_data->input, EV_MSC, MSC_SCAN, key_mapped);
+ if (key_mapped == KEY_UNKNOWN) {
+ pr_warn("%s code 0x%02X UNKNOWN\n", __func__, key_mapped);
+ } else if (drv_data->is_symed && send_shift) {
+ ppbbq10_report_keyevent(drv_data, STATE_PRESS, 27);
+ usleep_range(10, 20);
+ ppbbq10_report_keyevent(drv_data, STATE_HOLD, 27);
+ usleep_range(10, 20);
+ input_report_key(drv_data->input, key_mapped, keystate == STATE_PRESS);
+ usleep_range(10, 20);
+ input_report_key(drv_data->input, key_mapped, keystate == STATE_RELEASE);
+ usleep_range(10, 20);
+ ppbbq10_report_keyevent(drv_data, STATE_RELEASE, 27);
+ } else if ((drv_data->is_symed&& !send_shift) || !drv_data->is_symed) {
+ input_report_key(drv_data->input, key_mapped, keystate == STATE_PRESS);
+ }
+ }
+}
+
+
+static void
ppbbq10_update_locks(struct ppbbq10_data *drv_data)
{
struct input_dev *input = drv_data->input;