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 */
	}
}
예제 #3
0
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;
		}
	}
}
예제 #4
0
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;
	}
}
예제 #5
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;
            }
        }
    }
}
예제 #6
0
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;
    }
}
예제 #10
0
파일: p1_keyboard.c 프로젝트: FPar/GT-P1010
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;
    }
}