void power_off_timer(unsigned long arg) { struct dock_keyboard_data *data = (struct dock_keyboard_data *)arg; data->keyboard_enable = false; if (data->power) data->power(false); data->dockconnected = false; data->kl = UNKNOWN_KEYLAYOUT; data->handshaking = false; release_all_keys(data); }
static void keyboard_early_suspend(struct early_suspend *early_sus) { struct sec_keyboard_drvdata *data = container_of(early_sus, struct sec_keyboard_drvdata, early_suspend); if (data->kl != UNKOWN_KEYLAYOUT) { /* if the command of the caps lock off is needed, this command should be sent. sec_keyboard_tx(0xcb); msleep(20); */ release_all_keys(data); sec_keyboard_tx(data, 0x10); /* the idle mode */ } }
static void sec_keyboard_process_data( struct sec_keyboard_drvdata *data, u8 scan_code) { bool press; unsigned int keycode; /* keyboard driver need the contry code*/ if (data->kl == UNKOWN_KEYLAYOUT) { switch (scan_code) { case US_KEYBOARD: data->kl = US_KEYLAYOUT; data->keycode[49] = KEY_BACKSLASH; /* for the wakeup state*/ data->pre_kl = data->kl; printk(KERN_DEBUG "[Keyboard] US keyboard is attacted.\n"); break; case UK_KEYBOARD: data->kl = UK_KEYLAYOUT; data->keycode[49] = KEY_NUMERIC_POUND; /* for the wakeup state*/ data->pre_kl = data->kl; printk(KERN_DEBUG "[Keyboard] UK keyboard is attacted.\n"); break; default: printk(KERN_DEBUG "[Keyboard] Unkown layout : %x\n", scan_code); break; } } else { switch (scan_code) { case 0x0: release_all_keys(data); break; case 0xca: /* Caps lock on */ case 0xcb: /* Caps lock off */ case 0xeb: /* US keyboard */ case 0xec: /* UK keyboard */ break; /* Ignore */ case 0x45: case 0x48: data->remap_key = scan_code; data->pressed[scan_code] = true; schedule_delayed_work(&data->remap_dwork, HZ/3); break; case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: data->ack_code = scan_code; schedule_delayed_work(&data->ack_dwork, HZ/200); printk(KERN_DEBUG "[Keyboard] scan_code %d Received.\n", scan_code); break; case 0xc5: case 0xc8: keycode = (scan_code & 0x7f); data->pressed[keycode] = false; if (0 == data->remap_key) { input_report_key(data->input_dev, data->keycode[keycode], 0); input_sync(data->input_dev); } else { cancel_delayed_work_sync(&data->remap_dwork); if (0x48 == keycode) keycode = KEY_NEXTSONG; else keycode = KEY_PREVIOUSSONG; input_report_key(data->input_dev, keycode, 1); input_report_key(data->input_dev, keycode, 0); input_sync(data->input_dev); } break; default: keycode = (scan_code & 0x7f); press = ((scan_code & 0x80) != 0x80); if (keycode >= KEYBOARD_MIN || keycode <= KEYBOARD_MAX) { data->pressed[keycode] = press; input_report_key(data->input_dev, data->keycode[keycode], press); input_sync(data->input_dev); } break; } } }
static int check_keyboard_dock(struct sec_keyboard_callbacks *cb, bool val) { struct sec_keyboard_drvdata *data = container_of(cb, struct sec_keyboard_drvdata, callbacks); int try_cnt = 0; int max_cnt = 14; if (NULL == data->serio) { for (try_cnt = 0; try_cnt < max_cnt; try_cnt++) { msleep(50); if (data->tx_ready) break; if (gpio_get_value(data->acc_int_gpio)) { printk(KERN_DEBUG "[Keyboard] acc is disconnected.\n"); return 0; } } /* To block acc_power enable in LPM mode */ if ((data->tx_ready != true) && (val == true)) return 0 ; } if (!val) { data->dockconnected = false; data->univ_kbd_dock = false; } else { cancel_delayed_work_sync(&data->power_dwork); /* wakeup by keyboard dock */ if (data->pre_connected) { if (UNKOWN_KEYLAYOUT != data->pre_kl) { data->kl = data->pre_kl; data->acc_power(1, true); printk(KERN_DEBUG "[Keyboard] kl : %d\n", data->pre_kl); return 1; } } else data->pre_kl = UNKOWN_KEYLAYOUT; data->pre_connected = true; /* to prevent the over current issue */ data->acc_power(0, false); if (data->check_uart_path) data->check_uart_path(true); msleep(200); data->acc_power(1, true); /* try to get handshake data */ for (try_cnt = 0; try_cnt < max_cnt; try_cnt++) { msleep(50); if (data->kl != UNKOWN_KEYLAYOUT) { data->dockconnected = true; break; } if (gpio_get_value(data->acc_int_gpio)) { printk(KERN_DEBUG "[Keyboard] acc is disconnected.\n"); break; } } } if (data->dockconnected) { return 1; } else { if (data->pre_connected) { data->dockconnected = false; schedule_delayed_work(&data->power_dwork, HZ/2); data->kl = UNKOWN_KEYLAYOUT; release_all_keys(data); } return 0; } }
static void key_event_work(struct work_struct *work) { struct sec_keyboard_drvdata *data = container_of(work, struct sec_keyboard_drvdata, work_msg); bool press; unsigned int keycode; unsigned char scan_code; while (data->buf_front != data->buf_rear) { mutex_lock(&data->mutex); scan_code = data->key_buf[data->buf_front]; data->buf_front++; if (data->buf_front > MAX_BUF) data->buf_front = 0; mutex_unlock(&data->mutex); /* keyboard driver need the contry code*/ if (data->kl == UNKOWN_KEYLAYOUT) { switch (scan_code) { case US_KEYBOARD: data->kl = US_KEYLAYOUT; data->keycode[49] = KEY_BACKSLASH; /* for the wakeup state*/ data->pre_kl = data->kl; pr_info("[Keyboard] US keyboard is attacted.\n"); break; case UK_KEYBOARD: data->kl = UK_KEYLAYOUT; data->keycode[49] = KEY_NUMERIC_POUND; /* for the wakeup state*/ data->pre_kl = data->kl; pr_info("[Keyboard] UK keyboard is attacted.\n"); break; default: pr_info("[Keyboard] Unkown layout : %x\n", scan_code); break; } } else { switch (scan_code) { case 0x0: release_all_keys(data); break; case 0xca: /* Caps lock on */ case 0xcb: /* Caps lock off */ case 0xeb: /* US keyboard */ case 0xec: /* UK keyboard */ break; /* Ignore */ case 0x45: case 0x48: data->remap_key = scan_code; data->pressed[scan_code] = true; mod_timer(&data->key_timer, jiffies + HZ/3); break; case 0xc5: case 0xc8: keycode = (scan_code & 0x7f); data->pressed[keycode] = false; if (0 == data->remap_key) { input_report_key(data->input_dev, data->keycode[keycode], 0); input_sync(data->input_dev); } else { del_timer(&data->key_timer); if (0x48 == keycode) keycode = KEY_NEXTSONG; else keycode = KEY_PREVIOUSSONG; input_report_key(data->input_dev, keycode, 1); input_report_key(data->input_dev, keycode, 0); input_sync(data->input_dev); } break; default: keycode = (scan_code & 0x7f); press = ((scan_code & 0x80) != 0x80); if (keycode >= KEYBOARD_MIN || keycode <= KEYBOARD_MAX) { data->pressed[keycode] = press; input_report_key(data->input_dev, data->keycode[keycode], press); input_sync(data->input_dev); } break; } } } }
static int check_keyboard_dock(struct sec_keyboard_callbacks *cb, bool val) { struct sec_keyboard_drvdata *data = container_of(cb, struct sec_keyboard_drvdata, callbacks); int try_cnt = 0; int error = 0; int max_cnt = 14; if (!val) data->dockconnected = false; else { del_timer(&data->timer); /* wakeup by keyboard dock */ if (data->pre_connected) { if (UNKOWN_KEYLAYOUT != data->pre_kl) { data->kl = data->pre_kl; data->acc_power(1, true); pr_info("[Keyboard] kl : %d\n", data->pre_kl); return 1; } } else data->pre_kl = UNKOWN_KEYLAYOUT; data->pre_connected = true; /* to prevent the over current issue */ data->acc_power(0, false); if (data->check_uart_path) data->check_uart_path(true); /* Set baud rate for the keyboard uart */ error = change_console_baud_rate(9600); if (error < 0) pr_err("[Keyboard] Couldn't modify the baud rate.\n"); msleep(200); data->acc_power(1, true); /* try to get handshake data */ for (try_cnt = 0; try_cnt < max_cnt; try_cnt++) { msleep(50); if (data->kl != UNKOWN_KEYLAYOUT) { data->dockconnected = true; break; } if (gpio_get_value(data->acc_int_gpio)) { pr_info("[Keyboard] acc is disconnected.\n"); break; } } } if (data->dockconnected) return 1; else { if (data->pre_connected) { /* stop the thread and clear the buffer*/ data->buf_front = data->buf_rear = 0; data->dockconnected = false; mod_timer(&data->timer, jiffies + HZ/2); data->kl = UNKOWN_KEYLAYOUT; release_all_keys(data); } return 0; } }
void dock_keyboard_process_scancode(struct dock_keyboard_data *data, unsigned char scancode) { bool press; unsigned int keycode; /* Do not send the key_event durring the handshake time */ if (data->handshaking) { if (scancode == SCAN_CODE_HS) { release_all_keys(data); data->release_cnt = 16; } else { press = ((scancode & MASK_PRESS) != MASK_PRESS); keycode = (scancode & MASK_SCAN_CODE); if (keycode >= KBD_MIN && keycode <= KBD_MAX) { if (press) { /* workaround keyboard issue */ if (dock_keycodes[keycode].pressed) { input_report_key (data->input_dev, dock_keycodes [keycode].keycode, 0); msleep(20); } dock_keycodes[keycode].pressed = true; } else { dock_keycodes[keycode].pressed = false; } /* for the remap keys */ if (keycode == SCAN_CODE_REW || keycode == SCAN_CODE_FF) { if (press) { data->remap_keycode = keycode; mod_timer (&data->key_timer, jiffies + HZ / 3); } else { if (data->remap_state == REMAPKEY_PRESSED) { data->remap_state = REMAPKEY_RELEASED; input_report_key (data->input_dev, dock_keycodes [keycode].keycode, press); input_sync (data->input_dev); } } } else { input_report_key (data->input_dev, dock_keycodes [keycode].keycode, press); input_sync(data->input_dev); } } if (data->release_cnt > 0) { if (press) { input_report_key (data->input_dev, dock_keycodes[keycode].keycode, 0); } data->release_cnt--; } } } }
static void key_event_work(struct work_struct *work) { bool press; static int release_cnt = 0; unsigned int keycode; unsigned char scan_code; struct dock_keyboard_data *data = container_of(work, struct dock_keyboard_data, work_msg); while(buf_front != buf_rear) { buf_front = (1+buf_front)%MAX_BUF; scan_code = key_buf[buf_front]; /* keyboard driver need the contry code*/ if(data->kl == UNKOWN_KEYLAYOUT) { switch(scan_code) { case US_KEYBOARD: data->kl = US_KEYLAYOUT; dock_keycodes[49].keycode = KEY_BACKSLASH; /* for the wakeup state*/ pre_kl = data->kl; printk(KERN_DEBUG "[Keyboard] US keyboard is attacted.\n"); break; case UK_KEYBOARD: data->kl = UK_KEYLAYOUT; dock_keycodes[49].keycode = KEY_NUMERIC_POUND; /* for the wakeup state*/ pre_kl = data->kl; printk(KERN_DEBUG "[Keyboard] UK keyboard is attacted.\n"); break; default: printk(KERN_DEBUG "[Keyboard] Unkown key layout : %x\n", scan_code); break; } } else { /* Do not send the key_event durring the handshake time */ if(handshaking) { /* Caps lock led on/off */ if(scan_code == 0xca || scan_code == 0xcb) { // Ignore //dock_keyboard_tx(scan_code); } else if(scan_code == 0x0) { release_all_keys(); release_cnt = 16; } else { press = ((scan_code & 0x80) != 0x80); keycode = (scan_code & 0x7f); if(keycode >= KEYBOARD_MIN || keycode <= KEYBOARD_MAX) { if(press) { // workaround keyboard issue if(dock_keycodes[keycode].pressed) { input_report_key(data->input_dev, dock_keycodes[keycode].keycode, 0); msleep(1); } dock_keycodes[keycode].pressed = true; printk(KERN_DEBUG "[Keyboard] %d key is pressed.\n", dock_keycodes[keycode].keycode); } else { dock_keycodes[keycode].pressed = false; printk(KERN_DEBUG "[Keyboard] %d key is released.\n", dock_keycodes[keycode].keycode); } /* for the remap keys*/ if(keycode == 0x45 || keycode == 0x48) { if(press) { data->key_timer.data = (unsigned long) keycode; mod_timer(&data->key_timer, jiffies + HZ/3); } else { if(remap_state == REMAPKEY_PRESSED) { remap_state = REMAPKEY_RELEASED; input_report_key(data->input_dev, dock_keycodes[keycode].keycode, press); input_sync(data->input_dev); } } } else { input_report_key(data->input_dev, dock_keycodes[keycode].keycode, press); input_sync(data->input_dev); } } /* This is not working */ #if 0 else { /* request last scancode again*/ dock_keyboard_tx(0xaa); printk(KERN_DEBUG "[Keyboard] wrong key_code : 0x%x\n", scan_code); } #endif if(release_cnt >0) { if(press) { input_report_key(data->input_dev, dock_keycodes[keycode].keycode, 0); printk(KERN_DEBUG "[Keyboard] forced release %d key.\n", dock_keycodes[keycode].keycode); } release_cnt--; } } } else { /* device don't send the key_event durring the handshaking */ if((jiffies_to_msecs(jiffies) - connected_time) >= 500) { handshaking =true; } } } } }
int check_keyboard_dock(void) { static bool dockconnected = false; static bool pre_connected =false; static bool pre_uart_path =false; static bool first_connection =true; static unsigned long disconnected_time=0; int try_cnt = 0; int error = 0; int max_cnt = 10; if(gpio_get_value(g_data->gpio)) { dockconnected = false; } else { /*Do not use the keyboard in this version. * Because of the issue with the USB otg. */ #if defined (CONFIG_TARGET_LOCALE_EUR) || defined (CONFIG_TARGET_LOCALE_HKTW) || defined (CONFIG_TARGET_LOCALE_HKTW_FET) if(HWREV == 0x10||HWREV == 0x11) #elif defined (CONFIG_TARGET_LOCALE_KOR) if(HWREV < 0xf) // It works only on Rev 13 or later. #elif defined (CONFIG_TARGET_LOCALE_USAGSM) if(HWREV < 0x10) #else if(HWREV >= 0xff) #endif { return 0; } pre_connected = true; /*for checking handshake*/ connected_time = jiffies_to_msecs(jiffies); /* check the keyboard is connected durring the boot*/ if(first_connection) { if((connected_time - boot_time) <= 2000) { max_cnt = 30; printk(KERN_DEBUG "[Keyboard] ACCESSORY is connected durring the boot.\n"); } first_connection = false; } else if((connected_time - disconnected_time) < 1000) { g_data->kl = pre_kl; // dockconnected = true; printk(KERN_DEBUG "[Keyboard] kl : %d\n", pre_kl); } else { pre_kl = UNKOWN_KEYLAYOUT; } if(!keyboard_enable) { s3c_gpio_cfgpin(ACCESSORY_EN, S3C_GPIO_OUTPUT); s3c_gpio_setpull(ACCESSORY_EN, S3C_GPIO_PULL_UP); gpio_set_value(ACCESSORY_EN, 1); keyboard_enable = true; } /* if the uart is set as cp path, the path should be switched to ap path.*/ pre_uart_path = gpio_get_value(GPIO_UART_SEL); if(!pre_uart_path) { gpio_set_value(GPIO_UART_SEL, 1); printk(KERN_DEBUG "[Keyboard] console uart path is switched to AP.\n"); } /* Set baud rate for the keyboard uart */ error = change_console_baud_rate(9600); if(error<0) { printk(KERN_ERR "[Keyboard] Couldn't modify the baud rate.\n"); } if(!dockconnected) { /* try to get handshake data */ for(try_cnt=0; try_cnt<max_cnt; try_cnt++) { msleep(100); if(g_data->kl != UNKOWN_KEYLAYOUT) { dockconnected = true; break; } /* the accessory is dettached. */ if(gpio_get_value(g_data->gpio)) { dockconnected = false; break; } } } } if(dockconnected) { // if the led is on, the led should be off. g_data->led_on= false; if (!work_pending(&g_data->work_led)) { schedule_work(&g_data->work_led); } return 1; } else { if(pre_connected) { error = change_console_baud_rate(115200); if(error<0) { printk(KERN_ERR "[Keyboard] Couldn't modify the baud rate.\n"); } dockconnected = false; gpio_set_value(GPIO_UART_SEL, pre_uart_path); mod_timer(&g_data->timer, jiffies + HZ); g_data->kl = UNKOWN_KEYLAYOUT; pre_connected = false; handshaking = false; disconnected_time = jiffies_to_msecs(jiffies); release_all_keys(); } return 0; } }
int check_keyboard_dock(void) { static bool dockconnected = false; static bool pre_connected =false; static bool pre_uart_path =false; static unsigned long disconnected_time=0; int try_cnt = 0; int error = 0; int max_cnt = 10; if(gpio_get_value(g_data->gpio)) { dockconnected = false; } else { pre_connected = true; /*for checking handshake*/ connected_time = jiffies; if((connected_time - disconnected_time) < HZ) { g_data->kl = pre_kl; // dockconnected = true; printk(KERN_DEBUG "[Keyboard] kl : %d\n", pre_kl); } else { pre_kl = UNKOWN_KEYLAYOUT; } set_uart_suspend(0); /* if the uart is set as cp path, the path should be switched to ap path.*/ pre_uart_path = gpio_get_value(OMAP_GPIO_UART_SEL); if(!pre_uart_path) { gpio_set_value(OMAP_GPIO_UART_SEL, 1); printk(KERN_DEBUG "[Keyboard] console uart path is switched to AP.\n"); } /* Set baud rate for the keyboard uart */ error = change_console_baud_rate(9600); if(error<0) { printk(KERN_ERR "[Keyboard] Couldn't modify the baud rate.\n"); goto con_err; } if(!keyboard_enable) { printk("[Keyboard] check_keyboard_dock 6"); gpio_set_value(en_gpio, 1); keyboard_enable = true; } if(!dockconnected) { /* try to get handshake data */ for(try_cnt=0; try_cnt<max_cnt; try_cnt++) { msleep(100); if(g_data->kl != UNKOWN_KEYLAYOUT) { dockconnected = true; break; } /* the accessory is dettached. */ if(gpio_get_value(g_data->gpio)) { dockconnected = false; break; } } } } if(dockconnected) { // if the led is on, the led should be off. g_data->led_on= false; if (!work_pending(&g_data->work_led)) { schedule_work(&g_data->work_led); } return 1; } else { if(pre_connected) { gpio_set_value(en_gpio, 0); keyboard_enable = false; error = change_console_baud_rate(115200); if(error<0) { printk(KERN_ERR "[Keyboard] Couldn't modify the baud rate.\n"); } con_err: dockconnected = false; gpio_set_value(OMAP_GPIO_UART_SEL, pre_uart_path); g_data->kl = UNKOWN_KEYLAYOUT; pre_connected = false; handshaking = false; disconnected_time = jiffies; release_all_keys(); } set_uart_suspend(1); return 0; } }