Loading arch/arm/plat-spear/include/plat/keyboard.h +0 −7 Original line number Diff line number Diff line Loading @@ -159,11 +159,4 @@ struct kbd_platform_data { unsigned int mode; }; /* This function is used to set platform data field of pdev->dev */ static inline void kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data) { pdev->dev.platform_data = data; } #endif /* __PLAT_KEYBOARD_H */ drivers/input/joystick/amijoy.c +3 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,9 @@ static int __init amijoy_init(void) int i, j; int err; if (!MACH_IS_AMIGA) return -ENODEV; for (i = 0; i < 2; i++) { if (!amijoy[i]) continue; Loading drivers/input/keyboard/gpio_keys.c +169 −90 Original line number Diff line number Diff line Loading @@ -28,14 +28,18 @@ #include <linux/gpio.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/spinlock.h> struct gpio_button_data { struct gpio_keys_button *button; const struct gpio_keys_button *button; struct input_dev *input; struct timer_list timer; struct work_struct work; int timer_debounce; /* in msecs */ unsigned int timer_debounce; /* in msecs */ unsigned int irq; spinlock_t lock; bool disabled; bool key_pressed; }; struct gpio_keys_drvdata { Loading Loading @@ -114,7 +118,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) /* * Disable IRQ and possible debouncing timer. */ disable_irq(gpio_to_irq(bdata->button->gpio)); disable_irq(bdata->irq); if (bdata->timer_debounce) del_timer_sync(&bdata->timer); Loading @@ -135,7 +139,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) static void gpio_keys_enable_button(struct gpio_button_data *bdata) { if (bdata->disabled) { enable_irq(gpio_to_irq(bdata->button->gpio)); enable_irq(bdata->irq); bdata->disabled = false; } } Loading Loading @@ -195,7 +199,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, * @type: button type (%EV_KEY, %EV_SW) * * This function parses stringified bitmap from @buf and disables/enables * GPIO buttons accordinly. Returns 0 on success and negative error * GPIO buttons accordingly. Returns 0 on success and negative error * on failure. */ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, Loading Loading @@ -320,9 +324,9 @@ static struct attribute_group gpio_keys_attr_group = { .attrs = gpio_keys_attrs, }; static void gpio_keys_report_event(struct gpio_button_data *bdata) static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) { struct gpio_keys_button *button = bdata->button; const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; Loading @@ -336,27 +340,26 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) input_sync(input); } static void gpio_keys_work_func(struct work_struct *work) static void gpio_keys_gpio_work_func(struct work_struct *work) { struct gpio_button_data *bdata = container_of(work, struct gpio_button_data, work); gpio_keys_report_event(bdata); gpio_keys_gpio_report_event(bdata); } static void gpio_keys_timer(unsigned long _data) static void gpio_keys_gpio_timer(unsigned long _data) { struct gpio_button_data *data = (struct gpio_button_data *)_data; struct gpio_button_data *bdata = (struct gpio_button_data *)_data; schedule_work(&data->work); schedule_work(&bdata->work); } static irqreturn_t gpio_keys_isr(int irq, void *dev_id) static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; BUG_ON(irq != gpio_to_irq(button->gpio)); BUG_ON(irq != bdata->irq); if (bdata->timer_debounce) mod_timer(&bdata->timer, Loading @@ -367,31 +370,83 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) return IRQ_HANDLED; } static void gpio_keys_irq_timer(unsigned long _data) { struct gpio_button_data *bdata = (struct gpio_button_data *)_data; struct input_dev *input = bdata->input; unsigned long flags; spin_lock_irqsave(&bdata->lock, flags); if (bdata->key_pressed) { input_event(input, EV_KEY, bdata->button->code, 0); input_sync(input); bdata->key_pressed = false; } spin_unlock_irqrestore(&bdata->lock, flags); } static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned long flags; BUG_ON(irq != bdata->irq); spin_lock_irqsave(&bdata->lock, flags); if (!bdata->key_pressed) { input_event(input, EV_KEY, button->code, 1); input_sync(input); if (!bdata->timer_debounce) { input_event(input, EV_KEY, button->code, 0); input_sync(input); goto out; } bdata->key_pressed = true; } if (bdata->timer_debounce) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); out: spin_unlock_irqrestore(&bdata->lock, flags); return IRQ_HANDLED; } static int __devinit gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_button_data *bdata, struct gpio_keys_button *button) const struct gpio_keys_button *button) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; irq_handler_t isr; unsigned long irqflags; int irq, error; setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); INIT_WORK(&bdata->work, gpio_keys_work_func); bdata->input = input; bdata->button = button; spin_lock_init(&bdata->lock); if (gpio_is_valid(button->gpio)) { error = gpio_request(button->gpio, desc); if (error < 0) { dev_err(dev, "failed to request GPIO %d, error %d\n", dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); goto fail2; return error; } error = gpio_direction_input(button->gpio); if (error < 0) { dev_err(dev, "failed to configure" " direction for GPIO %d, error %d\n", dev_err(dev, "Failed to configure direction for GPIO %d, error %d\n", button->gpio, error); goto fail3; goto fail; } if (button->debounce_interval) { Loading @@ -399,18 +454,49 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, button->debounce_interval * 1000); /* use timer if gpiolib doesn't provide debounce */ if (error < 0) bdata->timer_debounce = button->debounce_interval; bdata->timer_debounce = button->debounce_interval; } irq = gpio_to_irq(button->gpio); if (irq < 0) { error = irq; dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); goto fail3; goto fail; } bdata->irq = irq; INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); setup_timer(&bdata->timer, gpio_keys_gpio_timer, (unsigned long)bdata); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { if (!button->irq) { dev_err(dev, "No IRQ specified\n"); return -EINVAL; } bdata->irq = button->irq; if (button->type && button->type != EV_KEY) { dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); return -EINVAL; } bdata->timer_debounce = button->debounce_interval; setup_timer(&bdata->timer, gpio_keys_irq_timer, (unsigned long)bdata); isr = gpio_keys_irq_isr; irqflags = 0; } input_set_capability(input, button->type ?: EV_KEY, button->code); /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. Loading @@ -418,18 +504,19 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, if (!button->can_disable) irqflags |= IRQF_SHARED; error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata); error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", irq, error); goto fail3; bdata->irq, error); goto fail; } return 0; fail3: fail: if (gpio_is_valid(button->gpio)) gpio_free(button->gpio); fail2: return error; } Loading Loading @@ -547,9 +634,19 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, #endif static void gpio_remove_key(struct gpio_button_data *bdata) { free_irq(bdata->irq, bdata); if (bdata->timer_debounce) del_timer_sync(&bdata->timer); cancel_work_sync(&bdata->work); if (gpio_is_valid(bdata->button->gpio)) gpio_free(bdata->button->gpio); } static int __devinit gpio_keys_probe(struct platform_device *pdev) { struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; struct gpio_keys_platform_data alt_pdata; Loading Loading @@ -599,21 +696,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; unsigned int type = button->type ?: EV_KEY; bdata->input = input; bdata->button = button; error = gpio_keys_setup_key(pdev, bdata, button); error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) goto fail2; if (button->wakeup) wakeup = 1; input_set_capability(input, type, button->code); } error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); Loading @@ -630,9 +721,12 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail3; } /* get current state of buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_report_event(&ddata->data[i]); /* get current state of buttons that are connected to GPIOs */ for (i = 0; i < pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (gpio_is_valid(bdata->button->gpio)) gpio_keys_gpio_report_event(bdata); } input_sync(input); device_init_wakeup(&pdev->dev, wakeup); Loading @@ -642,13 +736,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail3: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } while (--i >= 0) gpio_remove_key(&ddata->data[i]); platform_set_drvdata(pdev, NULL); fail1: Loading @@ -671,14 +760,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); for (i = 0; i < ddata->n_buttons; i++) { int irq = gpio_to_irq(ddata->data[i].button->gpio); free_irq(irq, &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); gpio_free(ddata->data[i].button->gpio); } for (i = 0; i < ddata->n_buttons; i++) gpio_remove_key(&ddata->data[i]); input_unregister_device(input); Loading @@ -703,11 +786,9 @@ static int gpio_keys_suspend(struct device *dev) if (device_may_wakeup(dev)) { for (i = 0; i < ddata->n_buttons; i++) { struct gpio_keys_button *button = ddata->data[i].button; if (button->wakeup) { int irq = gpio_to_irq(button->gpio); enable_irq_wake(irq); } struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); } } Loading @@ -720,14 +801,12 @@ static int gpio_keys_resume(struct device *dev) int i; for (i = 0; i < ddata->n_buttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup && device_may_wakeup(dev)) disable_irq_wake(bdata->irq); struct gpio_keys_button *button = ddata->data[i].button; if (button->wakeup && device_may_wakeup(dev)) { int irq = gpio_to_irq(button->gpio); disable_irq_wake(irq); } gpio_keys_report_event(&ddata->data[i]); if (gpio_is_valid(bdata->button->gpio)) gpio_keys_gpio_report_event(bdata); } input_sync(ddata->input); Loading drivers/input/keyboard/tegra-kbc.c +1 −0 Original line number Diff line number Diff line Loading @@ -630,6 +630,7 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) if (!np) return NULL; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; Loading drivers/input/mouse/sentelic.c +224 −70 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Finger Sensing Pad PS/2 mouse driver. * * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation. * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License Loading @@ -21,6 +21,7 @@ #include <linux/module.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/ctype.h> #include <linux/libps2.h> #include <linux/serio.h> Loading @@ -36,6 +37,9 @@ #define FSP_CMD_TIMEOUT 200 #define FSP_CMD_TIMEOUT2 30 #define GET_ABS_X(packet) ((packet[1] << 2) | ((packet[3] >> 2) & 0x03)) #define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) /** Driver version. */ static const char fsp_drv_ver[] = "1.0.0-K"; Loading Loading @@ -128,7 +132,8 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) out: ps2_end_command(ps2dev); psmouse_activate(psmouse); dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", reg_addr, *reg_val, rc); return rc; } Loading Loading @@ -179,7 +184,8 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) out: ps2_end_command(ps2dev); dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", reg_addr, reg_val, rc); return rc; } Loading Loading @@ -237,7 +243,8 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) out: ps2_end_command(ps2dev); psmouse_activate(psmouse); dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "READ PAGE REG: 0x%02x (rc = %d)\n", *reg_val, rc); return rc; } Loading Loading @@ -274,7 +281,8 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) out: ps2_end_command(ps2dev); dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", reg_val, rc); return rc; } Loading Loading @@ -319,7 +327,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) int res = 0; if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); psmouse_err(psmouse, "Unable get OPC state.\n"); return -EIO; } Loading @@ -336,8 +344,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) } if (res != 0) { dev_err(&psmouse->ps2dev.serio->dev, "Unable to enable OPC tag.\n"); psmouse_err(psmouse, "Unable to enable OPC tag.\n"); res = -EIO; } Loading Loading @@ -616,17 +623,39 @@ static struct attribute_group fsp_attribute_group = { }; #ifdef FSP_DEBUG static void fsp_packet_debug(unsigned char packet[]) static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) { static unsigned int ps2_packet_cnt; static unsigned int ps2_last_second; unsigned int jiffies_msec; const char *packet_type = "UNKNOWN"; unsigned short abs_x = 0, abs_y = 0; /* Interpret & dump the packet data. */ switch (packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: packet_type = "Absolute"; abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); break; case FSP_PKT_TYPE_NORMAL: packet_type = "Normal"; break; case FSP_PKT_TYPE_NOTIFY: packet_type = "Notify"; break; case FSP_PKT_TYPE_NORMAL_OPC: packet_type = "Normal-OPC"; break; } ps2_packet_cnt++; jiffies_msec = jiffies_to_msecs(jiffies); psmouse_dbg(psmouse, "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", jiffies_msec, packet[0], packet[1], packet[2], packet[3]); "%08dms %s packets: %02x, %02x, %02x, %02x; " "abs_x: %d, abs_y: %d\n", jiffies_msec, packet_type, packet[0], packet[1], packet[2], packet[3], abs_x, abs_y); if (jiffies_msec - ps2_last_second > 1000) { psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); Loading @@ -635,17 +664,29 @@ static void fsp_packet_debug(unsigned char packet[]) } } #else static void fsp_packet_debug(unsigned char packet[]) static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) { } #endif static void fsp_set_slot(struct input_dev *dev, int slot, bool active, unsigned int x, unsigned int y) { input_mt_slot(dev, slot); input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); if (active) { input_report_abs(dev, ABS_MT_POSITION_X, x); input_report_abs(dev, ABS_MT_POSITION_Y, y); } } static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; struct fsp_data *ad = psmouse->private; unsigned char *packet = psmouse->packet; unsigned char button_status = 0, lscroll = 0, rscroll = 0; unsigned short abs_x, abs_y, fgrs = 0; int rel_x, rel_y; if (psmouse->pktcnt < 4) Loading @@ -655,16 +696,76 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) * Full packet accumulated, process it */ fsp_packet_debug(psmouse, packet); switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: dev_warn(&psmouse->ps2dev.serio->dev, "Unexpected absolute mode packet, ignored.\n"); abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); if (packet[0] & FSP_PB0_MFMC) { /* * MFMC packet: assume that there are two fingers on * pad */ fgrs = 2; /* MFMC packet */ if (packet[0] & FSP_PB0_MFMC_FGR2) { /* 2nd finger */ if (ad->last_mt_fgr == 2) { /* * workaround for buggy firmware * which doesn't clear MFMC bit if * the 1st finger is up */ fgrs = 1; fsp_set_slot(dev, 0, false, 0, 0); } ad->last_mt_fgr = 2; fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y); } else { /* 1st finger */ if (ad->last_mt_fgr == 1) { /* * workaround for buggy firmware * which doesn't clear MFMC bit if * the 2nd finger is up */ fgrs = 1; fsp_set_slot(dev, 1, false, 0, 0); } ad->last_mt_fgr = 1; fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y); } } else { /* SFAC packet */ /* no multi-finger information */ ad->last_mt_fgr = 0; if (abs_x != 0 && abs_y != 0) fgrs = 1; fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); fsp_set_slot(dev, 1, false, 0, 0); } if (fgrs > 0) { input_report_abs(dev, ABS_X, abs_x); input_report_abs(dev, ABS_Y, abs_y); } input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); input_report_key(dev, BTN_TOUCH, fgrs); input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1); input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2); break; case FSP_PKT_TYPE_NORMAL_OPC: /* on-pad click, filter it if necessary */ if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) packet[0] &= ~BIT(0); packet[0] &= ~FSP_PB0_LBTN; /* fall through */ case FSP_PKT_TYPE_NORMAL: Loading Loading @@ -711,8 +812,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) input_sync(dev); fsp_packet_debug(packet); return PSMOUSE_FULL_PACKET; } Loading @@ -736,17 +835,25 @@ static int fsp_activate_protocol(struct psmouse *psmouse) ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); if (param[0] != 0x04) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to enable 4 bytes packet format.\n"); return -EIO; } if (pad->ver < FSP_VER_STL3888_C0) { /* Preparing relative coordinates output for older hardware */ if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to read SYSCTL5 register.\n"); return -EIO; } if (fsp_get_buttons(psmouse, &pad->buttons)) { psmouse_err(psmouse, "Unable to retrieve number of buttons.\n"); return -EIO; } val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); /* Ensure we are not in absolute mode */ val &= ~FSP_BIT_EN_PKT_G0; Loading @@ -756,22 +863,78 @@ static int fsp_activate_protocol(struct psmouse *psmouse) } if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to set up required mode bits.\n"); return -EIO; } /* * Enable OPC tags such that driver can tell the difference between * on-pad and real button click * Enable OPC tags such that driver can tell the difference * between on-pad and real button click */ if (fsp_opc_tag_enable(psmouse, true)) dev_warn(&psmouse->ps2dev.serio->dev, psmouse_warn(psmouse, "Failed to enable OPC tag mode.\n"); /* enable on-pad click by default */ pad->flags |= FSPDRV_FLAG_EN_OPC; /* Enable on-pad vertical and horizontal scrolling */ fsp_onpad_vscr(psmouse, true); fsp_onpad_hscr(psmouse, true); } else { /* Enable absolute coordinates output for Cx/Dx hardware */ if (fsp_reg_write(psmouse, FSP_REG_SWC1, FSP_BIT_SWC1_EN_ABS_1F | FSP_BIT_SWC1_EN_ABS_2F | FSP_BIT_SWC1_EN_FUP_OUT | FSP_BIT_SWC1_EN_ABS_CON)) { psmouse_err(psmouse, "Unable to enable absolute coordinates output.\n"); return -EIO; } } return 0; } static int fsp_set_input_params(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; struct fsp_data *pad = psmouse->private; if (pad->ver < FSP_VER_STL3888_C0) { __set_bit(BTN_MIDDLE, dev->keybit); __set_bit(BTN_BACK, dev->keybit); __set_bit(BTN_FORWARD, dev->keybit); __set_bit(REL_WHEEL, dev->relbit); __set_bit(REL_HWHEEL, dev->relbit); } else { /* * Hardware prior to Cx performs much better in relative mode; * hence, only enable absolute coordinates output as well as * multi-touch output for the newer hardware. * * Maximum coordinates can be computed as: * * number of scanlines * 64 - 57 * * where number of X/Y scanline lines are 16/12. */ int abs_x = 967, abs_y = 711; __set_bit(EV_ABS, dev->evbit); __clear_bit(EV_REL, dev->evbit); __set_bit(BTN_TOUCH, dev->keybit); __set_bit(BTN_TOOL_FINGER, dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); } return 0; } Loading Loading @@ -829,18 +992,16 @@ static int fsp_reconnect(struct psmouse *psmouse) int fsp_init(struct psmouse *psmouse) { struct fsp_data *priv; int ver, rev, buttons; int ver, rev; int error; if (fsp_get_version(psmouse, &ver) || fsp_get_revision(psmouse, &rev) || fsp_get_buttons(psmouse, &buttons)) { fsp_get_revision(psmouse, &rev)) { return -ENODEV; } psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n", ver >> 4, ver & 0x0F, rev, fsp_drv_ver); psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); if (!priv) Loading @@ -848,17 +1009,6 @@ int fsp_init(struct psmouse *psmouse) priv->ver = ver; priv->rev = rev; priv->buttons = buttons; /* enable on-pad click by default */ priv->flags |= FSPDRV_FLAG_EN_OPC; /* Set up various supported input event bits */ __set_bit(BTN_MIDDLE, psmouse->dev->keybit); __set_bit(BTN_BACK, psmouse->dev->keybit); __set_bit(BTN_FORWARD, psmouse->dev->keybit); __set_bit(REL_WHEEL, psmouse->dev->relbit); __set_bit(REL_HWHEEL, psmouse->dev->relbit); psmouse->protocol_handler = fsp_process_byte; psmouse->disconnect = fsp_disconnect; Loading @@ -866,15 +1016,19 @@ int fsp_init(struct psmouse *psmouse) psmouse->cleanup = fsp_reset; psmouse->pktsize = 4; /* set default packet output based on number of buttons we found */ error = fsp_activate_protocol(psmouse); if (error) goto err_out; /* Set up various supported input event bits */ error = fsp_set_input_params(psmouse); if (error) goto err_out; error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, &fsp_attribute_group); if (error) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Failed to create sysfs attributes (%d)", error); goto err_out; } Loading Loading
arch/arm/plat-spear/include/plat/keyboard.h +0 −7 Original line number Diff line number Diff line Loading @@ -159,11 +159,4 @@ struct kbd_platform_data { unsigned int mode; }; /* This function is used to set platform data field of pdev->dev */ static inline void kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data) { pdev->dev.platform_data = data; } #endif /* __PLAT_KEYBOARD_H */
drivers/input/joystick/amijoy.c +3 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,9 @@ static int __init amijoy_init(void) int i, j; int err; if (!MACH_IS_AMIGA) return -ENODEV; for (i = 0; i < 2; i++) { if (!amijoy[i]) continue; Loading
drivers/input/keyboard/gpio_keys.c +169 −90 Original line number Diff line number Diff line Loading @@ -28,14 +28,18 @@ #include <linux/gpio.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/spinlock.h> struct gpio_button_data { struct gpio_keys_button *button; const struct gpio_keys_button *button; struct input_dev *input; struct timer_list timer; struct work_struct work; int timer_debounce; /* in msecs */ unsigned int timer_debounce; /* in msecs */ unsigned int irq; spinlock_t lock; bool disabled; bool key_pressed; }; struct gpio_keys_drvdata { Loading Loading @@ -114,7 +118,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) /* * Disable IRQ and possible debouncing timer. */ disable_irq(gpio_to_irq(bdata->button->gpio)); disable_irq(bdata->irq); if (bdata->timer_debounce) del_timer_sync(&bdata->timer); Loading @@ -135,7 +139,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) static void gpio_keys_enable_button(struct gpio_button_data *bdata) { if (bdata->disabled) { enable_irq(gpio_to_irq(bdata->button->gpio)); enable_irq(bdata->irq); bdata->disabled = false; } } Loading Loading @@ -195,7 +199,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, * @type: button type (%EV_KEY, %EV_SW) * * This function parses stringified bitmap from @buf and disables/enables * GPIO buttons accordinly. Returns 0 on success and negative error * GPIO buttons accordingly. Returns 0 on success and negative error * on failure. */ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, Loading Loading @@ -320,9 +324,9 @@ static struct attribute_group gpio_keys_attr_group = { .attrs = gpio_keys_attrs, }; static void gpio_keys_report_event(struct gpio_button_data *bdata) static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) { struct gpio_keys_button *button = bdata->button; const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; Loading @@ -336,27 +340,26 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) input_sync(input); } static void gpio_keys_work_func(struct work_struct *work) static void gpio_keys_gpio_work_func(struct work_struct *work) { struct gpio_button_data *bdata = container_of(work, struct gpio_button_data, work); gpio_keys_report_event(bdata); gpio_keys_gpio_report_event(bdata); } static void gpio_keys_timer(unsigned long _data) static void gpio_keys_gpio_timer(unsigned long _data) { struct gpio_button_data *data = (struct gpio_button_data *)_data; struct gpio_button_data *bdata = (struct gpio_button_data *)_data; schedule_work(&data->work); schedule_work(&bdata->work); } static irqreturn_t gpio_keys_isr(int irq, void *dev_id) static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; BUG_ON(irq != gpio_to_irq(button->gpio)); BUG_ON(irq != bdata->irq); if (bdata->timer_debounce) mod_timer(&bdata->timer, Loading @@ -367,31 +370,83 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) return IRQ_HANDLED; } static void gpio_keys_irq_timer(unsigned long _data) { struct gpio_button_data *bdata = (struct gpio_button_data *)_data; struct input_dev *input = bdata->input; unsigned long flags; spin_lock_irqsave(&bdata->lock, flags); if (bdata->key_pressed) { input_event(input, EV_KEY, bdata->button->code, 0); input_sync(input); bdata->key_pressed = false; } spin_unlock_irqrestore(&bdata->lock, flags); } static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned long flags; BUG_ON(irq != bdata->irq); spin_lock_irqsave(&bdata->lock, flags); if (!bdata->key_pressed) { input_event(input, EV_KEY, button->code, 1); input_sync(input); if (!bdata->timer_debounce) { input_event(input, EV_KEY, button->code, 0); input_sync(input); goto out; } bdata->key_pressed = true; } if (bdata->timer_debounce) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); out: spin_unlock_irqrestore(&bdata->lock, flags); return IRQ_HANDLED; } static int __devinit gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_button_data *bdata, struct gpio_keys_button *button) const struct gpio_keys_button *button) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; irq_handler_t isr; unsigned long irqflags; int irq, error; setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); INIT_WORK(&bdata->work, gpio_keys_work_func); bdata->input = input; bdata->button = button; spin_lock_init(&bdata->lock); if (gpio_is_valid(button->gpio)) { error = gpio_request(button->gpio, desc); if (error < 0) { dev_err(dev, "failed to request GPIO %d, error %d\n", dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); goto fail2; return error; } error = gpio_direction_input(button->gpio); if (error < 0) { dev_err(dev, "failed to configure" " direction for GPIO %d, error %d\n", dev_err(dev, "Failed to configure direction for GPIO %d, error %d\n", button->gpio, error); goto fail3; goto fail; } if (button->debounce_interval) { Loading @@ -399,18 +454,49 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, button->debounce_interval * 1000); /* use timer if gpiolib doesn't provide debounce */ if (error < 0) bdata->timer_debounce = button->debounce_interval; bdata->timer_debounce = button->debounce_interval; } irq = gpio_to_irq(button->gpio); if (irq < 0) { error = irq; dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); goto fail3; goto fail; } bdata->irq = irq; INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); setup_timer(&bdata->timer, gpio_keys_gpio_timer, (unsigned long)bdata); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { if (!button->irq) { dev_err(dev, "No IRQ specified\n"); return -EINVAL; } bdata->irq = button->irq; if (button->type && button->type != EV_KEY) { dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); return -EINVAL; } bdata->timer_debounce = button->debounce_interval; setup_timer(&bdata->timer, gpio_keys_irq_timer, (unsigned long)bdata); isr = gpio_keys_irq_isr; irqflags = 0; } input_set_capability(input, button->type ?: EV_KEY, button->code); /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. Loading @@ -418,18 +504,19 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, if (!button->can_disable) irqflags |= IRQF_SHARED; error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata); error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", irq, error); goto fail3; bdata->irq, error); goto fail; } return 0; fail3: fail: if (gpio_is_valid(button->gpio)) gpio_free(button->gpio); fail2: return error; } Loading Loading @@ -547,9 +634,19 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, #endif static void gpio_remove_key(struct gpio_button_data *bdata) { free_irq(bdata->irq, bdata); if (bdata->timer_debounce) del_timer_sync(&bdata->timer); cancel_work_sync(&bdata->work); if (gpio_is_valid(bdata->button->gpio)) gpio_free(bdata->button->gpio); } static int __devinit gpio_keys_probe(struct platform_device *pdev) { struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; struct gpio_keys_platform_data alt_pdata; Loading Loading @@ -599,21 +696,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; unsigned int type = button->type ?: EV_KEY; bdata->input = input; bdata->button = button; error = gpio_keys_setup_key(pdev, bdata, button); error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) goto fail2; if (button->wakeup) wakeup = 1; input_set_capability(input, type, button->code); } error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); Loading @@ -630,9 +721,12 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail3; } /* get current state of buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_report_event(&ddata->data[i]); /* get current state of buttons that are connected to GPIOs */ for (i = 0; i < pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (gpio_is_valid(bdata->button->gpio)) gpio_keys_gpio_report_event(bdata); } input_sync(input); device_init_wakeup(&pdev->dev, wakeup); Loading @@ -642,13 +736,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail3: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } while (--i >= 0) gpio_remove_key(&ddata->data[i]); platform_set_drvdata(pdev, NULL); fail1: Loading @@ -671,14 +760,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); for (i = 0; i < ddata->n_buttons; i++) { int irq = gpio_to_irq(ddata->data[i].button->gpio); free_irq(irq, &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); gpio_free(ddata->data[i].button->gpio); } for (i = 0; i < ddata->n_buttons; i++) gpio_remove_key(&ddata->data[i]); input_unregister_device(input); Loading @@ -703,11 +786,9 @@ static int gpio_keys_suspend(struct device *dev) if (device_may_wakeup(dev)) { for (i = 0; i < ddata->n_buttons; i++) { struct gpio_keys_button *button = ddata->data[i].button; if (button->wakeup) { int irq = gpio_to_irq(button->gpio); enable_irq_wake(irq); } struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); } } Loading @@ -720,14 +801,12 @@ static int gpio_keys_resume(struct device *dev) int i; for (i = 0; i < ddata->n_buttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup && device_may_wakeup(dev)) disable_irq_wake(bdata->irq); struct gpio_keys_button *button = ddata->data[i].button; if (button->wakeup && device_may_wakeup(dev)) { int irq = gpio_to_irq(button->gpio); disable_irq_wake(irq); } gpio_keys_report_event(&ddata->data[i]); if (gpio_is_valid(bdata->button->gpio)) gpio_keys_gpio_report_event(bdata); } input_sync(ddata->input); Loading
drivers/input/keyboard/tegra-kbc.c +1 −0 Original line number Diff line number Diff line Loading @@ -630,6 +630,7 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) if (!np) return NULL; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; Loading
drivers/input/mouse/sentelic.c +224 −70 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Finger Sensing Pad PS/2 mouse driver. * * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation. * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License Loading @@ -21,6 +21,7 @@ #include <linux/module.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/ctype.h> #include <linux/libps2.h> #include <linux/serio.h> Loading @@ -36,6 +37,9 @@ #define FSP_CMD_TIMEOUT 200 #define FSP_CMD_TIMEOUT2 30 #define GET_ABS_X(packet) ((packet[1] << 2) | ((packet[3] >> 2) & 0x03)) #define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) /** Driver version. */ static const char fsp_drv_ver[] = "1.0.0-K"; Loading Loading @@ -128,7 +132,8 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) out: ps2_end_command(ps2dev); psmouse_activate(psmouse); dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", reg_addr, *reg_val, rc); return rc; } Loading Loading @@ -179,7 +184,8 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) out: ps2_end_command(ps2dev); dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", reg_addr, reg_val, rc); return rc; } Loading Loading @@ -237,7 +243,8 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) out: ps2_end_command(ps2dev); psmouse_activate(psmouse); dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "READ PAGE REG: 0x%02x (rc = %d)\n", *reg_val, rc); return rc; } Loading Loading @@ -274,7 +281,8 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) out: ps2_end_command(ps2dev); dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", psmouse_dbg(psmouse, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", reg_val, rc); return rc; } Loading Loading @@ -319,7 +327,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) int res = 0; if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); psmouse_err(psmouse, "Unable get OPC state.\n"); return -EIO; } Loading @@ -336,8 +344,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) } if (res != 0) { dev_err(&psmouse->ps2dev.serio->dev, "Unable to enable OPC tag.\n"); psmouse_err(psmouse, "Unable to enable OPC tag.\n"); res = -EIO; } Loading Loading @@ -616,17 +623,39 @@ static struct attribute_group fsp_attribute_group = { }; #ifdef FSP_DEBUG static void fsp_packet_debug(unsigned char packet[]) static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) { static unsigned int ps2_packet_cnt; static unsigned int ps2_last_second; unsigned int jiffies_msec; const char *packet_type = "UNKNOWN"; unsigned short abs_x = 0, abs_y = 0; /* Interpret & dump the packet data. */ switch (packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: packet_type = "Absolute"; abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); break; case FSP_PKT_TYPE_NORMAL: packet_type = "Normal"; break; case FSP_PKT_TYPE_NOTIFY: packet_type = "Notify"; break; case FSP_PKT_TYPE_NORMAL_OPC: packet_type = "Normal-OPC"; break; } ps2_packet_cnt++; jiffies_msec = jiffies_to_msecs(jiffies); psmouse_dbg(psmouse, "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", jiffies_msec, packet[0], packet[1], packet[2], packet[3]); "%08dms %s packets: %02x, %02x, %02x, %02x; " "abs_x: %d, abs_y: %d\n", jiffies_msec, packet_type, packet[0], packet[1], packet[2], packet[3], abs_x, abs_y); if (jiffies_msec - ps2_last_second > 1000) { psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); Loading @@ -635,17 +664,29 @@ static void fsp_packet_debug(unsigned char packet[]) } } #else static void fsp_packet_debug(unsigned char packet[]) static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) { } #endif static void fsp_set_slot(struct input_dev *dev, int slot, bool active, unsigned int x, unsigned int y) { input_mt_slot(dev, slot); input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); if (active) { input_report_abs(dev, ABS_MT_POSITION_X, x); input_report_abs(dev, ABS_MT_POSITION_Y, y); } } static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; struct fsp_data *ad = psmouse->private; unsigned char *packet = psmouse->packet; unsigned char button_status = 0, lscroll = 0, rscroll = 0; unsigned short abs_x, abs_y, fgrs = 0; int rel_x, rel_y; if (psmouse->pktcnt < 4) Loading @@ -655,16 +696,76 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) * Full packet accumulated, process it */ fsp_packet_debug(psmouse, packet); switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { case FSP_PKT_TYPE_ABS: dev_warn(&psmouse->ps2dev.serio->dev, "Unexpected absolute mode packet, ignored.\n"); abs_x = GET_ABS_X(packet); abs_y = GET_ABS_Y(packet); if (packet[0] & FSP_PB0_MFMC) { /* * MFMC packet: assume that there are two fingers on * pad */ fgrs = 2; /* MFMC packet */ if (packet[0] & FSP_PB0_MFMC_FGR2) { /* 2nd finger */ if (ad->last_mt_fgr == 2) { /* * workaround for buggy firmware * which doesn't clear MFMC bit if * the 1st finger is up */ fgrs = 1; fsp_set_slot(dev, 0, false, 0, 0); } ad->last_mt_fgr = 2; fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y); } else { /* 1st finger */ if (ad->last_mt_fgr == 1) { /* * workaround for buggy firmware * which doesn't clear MFMC bit if * the 2nd finger is up */ fgrs = 1; fsp_set_slot(dev, 1, false, 0, 0); } ad->last_mt_fgr = 1; fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y); } } else { /* SFAC packet */ /* no multi-finger information */ ad->last_mt_fgr = 0; if (abs_x != 0 && abs_y != 0) fgrs = 1; fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); fsp_set_slot(dev, 1, false, 0, 0); } if (fgrs > 0) { input_report_abs(dev, ABS_X, abs_x); input_report_abs(dev, ABS_Y, abs_y); } input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); input_report_key(dev, BTN_TOUCH, fgrs); input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1); input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2); break; case FSP_PKT_TYPE_NORMAL_OPC: /* on-pad click, filter it if necessary */ if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) packet[0] &= ~BIT(0); packet[0] &= ~FSP_PB0_LBTN; /* fall through */ case FSP_PKT_TYPE_NORMAL: Loading Loading @@ -711,8 +812,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) input_sync(dev); fsp_packet_debug(packet); return PSMOUSE_FULL_PACKET; } Loading @@ -736,17 +835,25 @@ static int fsp_activate_protocol(struct psmouse *psmouse) ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); if (param[0] != 0x04) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to enable 4 bytes packet format.\n"); return -EIO; } if (pad->ver < FSP_VER_STL3888_C0) { /* Preparing relative coordinates output for older hardware */ if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to read SYSCTL5 register.\n"); return -EIO; } if (fsp_get_buttons(psmouse, &pad->buttons)) { psmouse_err(psmouse, "Unable to retrieve number of buttons.\n"); return -EIO; } val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); /* Ensure we are not in absolute mode */ val &= ~FSP_BIT_EN_PKT_G0; Loading @@ -756,22 +863,78 @@ static int fsp_activate_protocol(struct psmouse *psmouse) } if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Unable to set up required mode bits.\n"); return -EIO; } /* * Enable OPC tags such that driver can tell the difference between * on-pad and real button click * Enable OPC tags such that driver can tell the difference * between on-pad and real button click */ if (fsp_opc_tag_enable(psmouse, true)) dev_warn(&psmouse->ps2dev.serio->dev, psmouse_warn(psmouse, "Failed to enable OPC tag mode.\n"); /* enable on-pad click by default */ pad->flags |= FSPDRV_FLAG_EN_OPC; /* Enable on-pad vertical and horizontal scrolling */ fsp_onpad_vscr(psmouse, true); fsp_onpad_hscr(psmouse, true); } else { /* Enable absolute coordinates output for Cx/Dx hardware */ if (fsp_reg_write(psmouse, FSP_REG_SWC1, FSP_BIT_SWC1_EN_ABS_1F | FSP_BIT_SWC1_EN_ABS_2F | FSP_BIT_SWC1_EN_FUP_OUT | FSP_BIT_SWC1_EN_ABS_CON)) { psmouse_err(psmouse, "Unable to enable absolute coordinates output.\n"); return -EIO; } } return 0; } static int fsp_set_input_params(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; struct fsp_data *pad = psmouse->private; if (pad->ver < FSP_VER_STL3888_C0) { __set_bit(BTN_MIDDLE, dev->keybit); __set_bit(BTN_BACK, dev->keybit); __set_bit(BTN_FORWARD, dev->keybit); __set_bit(REL_WHEEL, dev->relbit); __set_bit(REL_HWHEEL, dev->relbit); } else { /* * Hardware prior to Cx performs much better in relative mode; * hence, only enable absolute coordinates output as well as * multi-touch output for the newer hardware. * * Maximum coordinates can be computed as: * * number of scanlines * 64 - 57 * * where number of X/Y scanline lines are 16/12. */ int abs_x = 967, abs_y = 711; __set_bit(EV_ABS, dev->evbit); __clear_bit(EV_REL, dev->evbit); __set_bit(BTN_TOUCH, dev->keybit); __set_bit(BTN_TOOL_FINGER, dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); } return 0; } Loading Loading @@ -829,18 +992,16 @@ static int fsp_reconnect(struct psmouse *psmouse) int fsp_init(struct psmouse *psmouse) { struct fsp_data *priv; int ver, rev, buttons; int ver, rev; int error; if (fsp_get_version(psmouse, &ver) || fsp_get_revision(psmouse, &rev) || fsp_get_buttons(psmouse, &buttons)) { fsp_get_revision(psmouse, &rev)) { return -ENODEV; } psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n", ver >> 4, ver & 0x0F, rev, fsp_drv_ver); psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); if (!priv) Loading @@ -848,17 +1009,6 @@ int fsp_init(struct psmouse *psmouse) priv->ver = ver; priv->rev = rev; priv->buttons = buttons; /* enable on-pad click by default */ priv->flags |= FSPDRV_FLAG_EN_OPC; /* Set up various supported input event bits */ __set_bit(BTN_MIDDLE, psmouse->dev->keybit); __set_bit(BTN_BACK, psmouse->dev->keybit); __set_bit(BTN_FORWARD, psmouse->dev->keybit); __set_bit(REL_WHEEL, psmouse->dev->relbit); __set_bit(REL_HWHEEL, psmouse->dev->relbit); psmouse->protocol_handler = fsp_process_byte; psmouse->disconnect = fsp_disconnect; Loading @@ -866,15 +1016,19 @@ int fsp_init(struct psmouse *psmouse) psmouse->cleanup = fsp_reset; psmouse->pktsize = 4; /* set default packet output based on number of buttons we found */ error = fsp_activate_protocol(psmouse); if (error) goto err_out; /* Set up various supported input event bits */ error = fsp_set_input_params(psmouse); if (error) goto err_out; error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, &fsp_attribute_group); if (error) { dev_err(&psmouse->ps2dev.serio->dev, psmouse_err(psmouse, "Failed to create sysfs attributes (%d)", error); goto err_out; } Loading