diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/imx_keypad.c | 4 | ||||
-rw-r--r-- | drivers/input/misc/ims-pcu.c | 258 | ||||
-rw-r--r-- | drivers/input/misc/sirfsoc-onkey.c | 110 | ||||
-rw-r--r-- | drivers/input/misc/uinput.c | 97 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 19 | ||||
-rw-r--r-- | drivers/input/tablet/gtco.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/zforce_ts.c | 95 |
7 files changed, 500 insertions, 85 deletions
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index cbf4f8038cb..97ec33572e5 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -439,7 +439,7 @@ static int imx_keypad_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq defined in platform data\n"); - return -EINVAL; + return irq; } input_dev = devm_input_allocate_device(&pdev->dev); @@ -449,7 +449,7 @@ static int imx_keypad_probe(struct platform_device *pdev) } keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad), - GFP_KERNEL); + GFP_KERNEL); if (!keypad) { dev_err(&pdev->dev, "not enough memory for driver data\n"); return -ENOMEM; diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index e204f26b001..5a736397d9c 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -51,6 +51,8 @@ struct ims_pcu_backlight { #define IMS_PCU_BL_VERSION_LEN (9 + 1) #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) +#define IMS_PCU_PCU_B_DEVICE_ID 5 + #define IMS_PCU_BUF_SIZE 128 struct ims_pcu { @@ -68,6 +70,9 @@ struct ims_pcu { char bl_version[IMS_PCU_BL_VERSION_LEN]; char reset_reason[IMS_PCU_BL_RESET_REASON_LEN]; int update_firmware_status; + u8 device_id; + + u8 ofn_reg_addr; struct usb_interface *ctrl_intf; @@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) #define IMS_PCU_CMD_GET_DEVICE_ID 0xae #define IMS_PCU_CMD_SPECIAL_INFO 0xb0 #define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */ +#define IMS_PCU_CMD_OFN_SET_CONFIG 0xb3 +#define IMS_PCU_CMD_OFN_GET_CONFIG 0xb4 /* PCU responses */ #define IMS_PCU_RSP_STATUS 0xc0 @@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) #define IMS_PCU_RSP_GET_DEVICE_ID 0xce #define IMS_PCU_RSP_SPECIAL_INFO 0xd0 #define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */ +#define IMS_PCU_RSP_OFN_SET_CONFIG 0xd2 +#define IMS_PCU_RSP_OFN_GET_CONFIG 0xd3 + #define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */ #define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */ @@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = { .attrs = ims_pcu_attrs, }; +/* Support for a separate OFN attribute group */ + +#define OFN_REG_RESULT_OFFSET 2 + +static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data) +{ + int error; + s16 result; + + error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG, + &addr, sizeof(addr)); + if (error) + return error; + + result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); + if (result < 0) + return -EIO; + + /* We only need LSB */ + *data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET]; + return 0; +} + +static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data) +{ + u8 buffer[] = { addr, data }; + int error; + s16 result; + + error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG, + &buffer, sizeof(buffer)); + if (error) + return error; + + result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); + if (result < 0) + return -EIO; + + return 0; +} + +static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, + struct device_attribute *dattr, + char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + int error; + u8 data; + + mutex_lock(&pcu->cmd_mutex); + error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); + mutex_unlock(&pcu->cmd_mutex); + + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%x\n", data); +} + +static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, + struct device_attribute *dattr, + const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + int error; + u8 value; + + error = kstrtou8(buf, 0, &value); + if (error) + return error; + + mutex_lock(&pcu->cmd_mutex); + error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); + mutex_unlock(&pcu->cmd_mutex); + + return error ?: count; +} + +static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, + ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store); + +static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, + struct device_attribute *dattr, + char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + int error; + + mutex_lock(&pcu->cmd_mutex); + error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr); + mutex_unlock(&pcu->cmd_mutex); + + return error; +} + +static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, + struct device_attribute *dattr, + const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + int error; + u8 value; + + error = kstrtou8(buf, 0, &value); + if (error) + return error; + + mutex_lock(&pcu->cmd_mutex); + pcu->ofn_reg_addr = value; + mutex_unlock(&pcu->cmd_mutex); + + return error ?: count; +} + +static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR, + ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store); + +struct ims_pcu_ofn_bit_attribute { + struct device_attribute dattr; + u8 addr; + u8 nr; +}; + +static ssize_t ims_pcu_ofn_bit_show(struct device *dev, + struct device_attribute *dattr, + char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + struct ims_pcu_ofn_bit_attribute *attr = + container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); + int error; + u8 data; + + mutex_lock(&pcu->cmd_mutex); + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + mutex_unlock(&pcu->cmd_mutex); + + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr))); +} + +static ssize_t ims_pcu_ofn_bit_store(struct device *dev, + struct device_attribute *dattr, + const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + struct ims_pcu_ofn_bit_attribute *attr = + container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); + int error; + int value; + u8 data; + + error = kstrtoint(buf, 0, &value); + if (error) + return error; + + if (value > 1) + return -EINVAL; + + mutex_lock(&pcu->cmd_mutex); + + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + if (!error) { + if (value) + data |= 1U << attr->nr; + else + data &= ~(1U << attr->nr); + + error = ims_pcu_write_ofn_config(pcu, attr->addr, data); + } + + mutex_unlock(&pcu->cmd_mutex); + + return error ?: count; +} + +#define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr) \ +struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = { \ + .dattr = __ATTR(_field, S_IWUSR | S_IRUGO, \ + ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store), \ + .addr = _addr, \ + .nr = _nr, \ +} + +static IMS_PCU_OFN_BIT_ATTR(engine_enable, 0x60, 7); +static IMS_PCU_OFN_BIT_ATTR(speed_enable, 0x60, 6); +static IMS_PCU_OFN_BIT_ATTR(assert_enable, 0x60, 5); +static IMS_PCU_OFN_BIT_ATTR(xyquant_enable, 0x60, 4); +static IMS_PCU_OFN_BIT_ATTR(xyscale_enable, 0x60, 1); + +static IMS_PCU_OFN_BIT_ATTR(scale_x2, 0x63, 6); +static IMS_PCU_OFN_BIT_ATTR(scale_y2, 0x63, 7); + +static struct attribute *ims_pcu_ofn_attrs[] = { + &dev_attr_reg_data.attr, + &dev_attr_reg_addr.attr, + &ims_pcu_ofn_attr_engine_enable.dattr.attr, + &ims_pcu_ofn_attr_speed_enable.dattr.attr, + &ims_pcu_ofn_attr_assert_enable.dattr.attr, + &ims_pcu_ofn_attr_xyquant_enable.dattr.attr, + &ims_pcu_ofn_attr_xyscale_enable.dattr.attr, + &ims_pcu_ofn_attr_scale_x2.dattr.attr, + &ims_pcu_ofn_attr_scale_y2.dattr.attr, + NULL +}; + +static struct attribute_group ims_pcu_ofn_attr_group = { + .name = "ofn", + .attrs = ims_pcu_ofn_attrs, +}; + static void ims_pcu_irq(struct urb *urb) { struct ims_pcu *pcu = urb->context; @@ -1624,7 +1853,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) static atomic_t device_no = ATOMIC_INIT(0); const struct ims_pcu_device_info *info; - u8 device_id; int error; error = ims_pcu_get_device_info(pcu); @@ -1633,7 +1861,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) return error; } - error = ims_pcu_identify_type(pcu, &device_id); + error = ims_pcu_identify_type(pcu, &pcu->device_id); if (error) { dev_err(pcu->dev, "Failed to identify device, error: %d\n", error); @@ -1645,9 +1873,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) return 0; } - if (device_id >= ARRAY_SIZE(ims_pcu_device_info) || - !ims_pcu_device_info[device_id].keymap) { - dev_err(pcu->dev, "Device ID %d is not valid\n", device_id); + if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) || + !ims_pcu_device_info[pcu->device_id].keymap) { + dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id); /* Same as above, punt to userspace */ return 0; } @@ -1655,11 +1883,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) /* Device appears to be operable, complete initialization */ pcu->device_no = atomic_inc_return(&device_no) - 1; + /* + * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor + */ + if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { + error = sysfs_create_group(&pcu->dev->kobj, + &ims_pcu_ofn_attr_group); + if (error) + return error; + } + error = ims_pcu_setup_backlight(pcu); if (error) return error; - info = &ims_pcu_device_info[device_id]; + info = &ims_pcu_device_info[pcu->device_id]; error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len); if (error) goto err_destroy_backlight; @@ -1674,10 +1912,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) return 0; -err_destroy_backlight: - ims_pcu_destroy_backlight(pcu); err_destroy_buttons: ims_pcu_destroy_buttons(pcu); +err_destroy_backlight: + ims_pcu_destroy_backlight(pcu); return error; } @@ -1691,6 +1929,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu) ims_pcu_destroy_gamepad(pcu); ims_pcu_destroy_buttons(pcu); ims_pcu_destroy_backlight(pcu); + + if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) + sysfs_remove_group(&pcu->dev->kobj, + &ims_pcu_ofn_attr_group); } } diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index e8897c36d21..4d66c723cf0 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -1,7 +1,8 @@ /* * Power key driver for SiRF PrimaII * - * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. + * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group + * company. * * Licensed under GPLv2 or later. */ @@ -13,16 +14,41 @@ #include <linux/input.h> #include <linux/rtc/sirfsoc_rtciobrg.h> #include <linux/of.h> +#include <linux/workqueue.h> struct sirfsoc_pwrc_drvdata { u32 pwrc_base; struct input_dev *input; + struct delayed_work work; }; #define PWRC_ON_KEY_BIT (1 << 0) #define PWRC_INT_STATUS 0xc #define PWRC_INT_MASK 0x10 +#define PWRC_PIN_STATUS 0x14 +#define PWRC_KEY_DETECT_UP_TIME 20 /* ms*/ + +static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) +{ + u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + + PWRC_PIN_STATUS); + return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ +} + +static void sirfsoc_pwrc_report_event(struct work_struct *work) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = + container_of(work, struct sirfsoc_pwrc_drvdata, work.work); + + if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { + schedule_delayed_work(&pwrcdrv->work, + msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); + } else { + input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); + input_sync(pwrcdrv->input); + } +} static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) { @@ -34,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, pwrcdrv->pwrc_base + PWRC_INT_STATUS); - /* - * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c - * to queue a SUSPEND APM event - */ - input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); + input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1); input_sync(pwrcdrv->input); - - /* - * Todo: report KEY_POWER event for Android platforms, Android PowerManager - * will handle the suspend and powerdown/hibernation - */ + schedule_delayed_work(&pwrcdrv->work, + msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); return IRQ_HANDLED; } +static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv, + bool enable) +{ + u32 int_mask; + + int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK); + if (enable) + int_mask |= PWRC_ON_KEY_BIT; + else + int_mask &= ~PWRC_ON_KEY_BIT; + sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK); +} + +static int sirfsoc_pwrc_open(struct input_dev *input) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); + + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); + + return 0; +} + +static void sirfsoc_pwrc_close(struct input_dev *input) +{ + struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); + + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); + cancel_delayed_work_sync(&pwrcdrv->work); +} + static const struct of_device_id sirfsoc_pwrc_of_match[] = { { .compatible = "sirf,prima2-pwrc" }, {}, @@ -70,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) } /* - * we can't use of_iomap because pwrc is not mapped in memory, + * We can't use of_iomap because pwrc is not mapped in memory, * the so-called base address is only offset in rtciobrg */ error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); @@ -86,11 +135,21 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) pwrcdrv->input->name = "sirfsoc pwrckey"; pwrcdrv->input->phys = "pwrc/input0"; - pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); + pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); + + INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); + + pwrcdrv->input->open = sirfsoc_pwrc_open; + pwrcdrv->input->close = sirfsoc_pwrc_close; + + input_set_drvdata(pwrcdrv->input, pwrcdrv); + + /* Make sure the device is quiesced */ + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); irq = platform_get_irq(pdev, 0); error = devm_request_irq(&pdev->dev, irq, - sirfsoc_pwrc_isr, IRQF_SHARED, + sirfsoc_pwrc_isr, 0, "sirfsoc_pwrc_int", pwrcdrv); if (error) { dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", @@ -98,11 +157,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) return error; } - sirfsoc_rtc_iobrg_writel( - sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | - PWRC_ON_KEY_BIT, - pwrcdrv->pwrc_base + PWRC_INT_MASK); - error = input_register_device(pwrcdrv->input); if (error) { dev_err(&pdev->dev, @@ -111,7 +165,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) return error; } - platform_set_drvdata(pdev, pwrcdrv); + dev_set_drvdata(&pdev->dev, pwrcdrv); device_init_wakeup(&pdev->dev, 1); return 0; @@ -125,25 +179,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP -static int pwrc_resume(struct device *dev) +static int sirfsoc_pwrc_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); + struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); + struct input_dev *input = pwrcdrv->input; /* * Do not mask pwrc interrupt as we want pwrc work as a wakeup source * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c */ - sirfsoc_rtc_iobrg_writel( - sirfsoc_rtc_iobrg_readl( - pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, - pwrcdrv->pwrc_base + PWRC_INT_MASK); + mutex_lock(&input->mutex); + if (input->users) + sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); + mutex_unlock(&input->mutex); return 0; } #endif -static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); +static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume); static struct platform_driver sirfsoc_pwrc_driver = { .probe = sirfsoc_pwrc_probe, diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 772835938a5..85693624750 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -20,6 +20,8 @@ * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> * * Changes/Revisions: + * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) + * - add UI_GET_SYSNAME ioctl * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) * - updated ff support for the changes in kernel interface * - added MODULE_VERSION @@ -670,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer, __ret; \ }) +static int uinput_str_to_user(void __user *dest, const char *str, + unsigned int maxlen) +{ + char __user *p = dest; + int len, ret; + + if (!str) + return -ENOENT; + + if (maxlen == 0) + return -EINVAL; + + len = strlen(str) + 1; + if (len > maxlen) + len = maxlen; + + ret = copy_to_user(p, str, len); + if (ret) + return -EFAULT; + + /* force terminating '\0' */ + ret = put_user(0, p + len - 1); + return ret ? -EFAULT : len; +} + static long uinput_ioctl_handler(struct file *file, unsigned int cmd, unsigned long arg, void __user *p) { @@ -679,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, struct uinput_ff_erase ff_erase; struct uinput_request *req; char *phys; + const char *name; + unsigned int size; retval = mutex_lock_interruptible(&udev->mutex); if (retval) @@ -693,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, switch (cmd) { case UI_DEV_CREATE: retval = uinput_create_device(udev); - break; + goto out; case UI_DEV_DESTROY: uinput_destroy_device(udev); - break; + goto out; case UI_SET_EVBIT: retval = uinput_set_bit(arg, evbit, EV_MAX); - break; + goto out; case UI_SET_KEYBIT: retval = uinput_set_bit(arg, keybit, KEY_MAX); - break; + goto out; case UI_SET_RELBIT: retval = uinput_set_bit(arg, relbit, REL_MAX); - break; + goto out; case UI_SET_ABSBIT: retval = uinput_set_bit(arg, absbit, ABS_MAX); - break; + goto out; case UI_SET_MSCBIT: retval = uinput_set_bit(arg, mscbit, MSC_MAX); - break; + goto out; case UI_SET_LEDBIT: retval = uinput_set_bit(arg, ledbit, LED_MAX); - break; + goto out; case UI_SET_SNDBIT: retval = uinput_set_bit(arg, sndbit, SND_MAX); - break; + goto out; case UI_SET_FFBIT: retval = uinput_set_bit(arg, ffbit, FF_MAX); - break; + goto out; case UI_SET_SWBIT: retval = uinput_set_bit(arg, swbit, SW_MAX); - break; + goto out; case UI_SET_PROPBIT: retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); - break; + goto out; case UI_SET_PHYS: if (udev->state == UIST_CREATED) { @@ -753,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, kfree(udev->dev->phys); udev->dev->phys = phys; - break; + goto out; case UI_BEGIN_FF_UPLOAD: retval = uinput_ff_upload_from_user(p, &ff_up); if (retval) - break; + goto out; req = uinput_request_find(udev, ff_up.request_id); if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { retval = -EINVAL; - break; + goto out; } ff_up.retval = 0; @@ -775,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, memset(&ff_up.old, 0, sizeof(struct ff_effect)); retval = uinput_ff_upload_to_user(p, &ff_up); - break; + goto out; case UI_BEGIN_FF_ERASE: if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { retval = -EFAULT; - break; + goto out; } req = uinput_request_find(udev, ff_erase.request_id); if (!req || req->code != UI_FF_ERASE) { retval = -EINVAL; - break; + goto out; } ff_erase.retval = 0; ff_erase.effect_id = req->u.effect_id; if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { retval = -EFAULT; - break; + goto out; } - break; + goto out; case UI_END_FF_UPLOAD: retval = uinput_ff_upload_from_user(p, &ff_up); if (retval) - break; + goto out; req = uinput_request_find(udev, ff_up.request_id); if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { retval = -EINVAL; - break; + goto out; } req->retval = ff_up.retval; uinput_request_done(udev, req); - break; + goto out; case UI_END_FF_ERASE: if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { retval = -EFAULT; - break; + goto out; } req = uinput_request_find(udev, ff_erase.request_id); if (!req || req->code != UI_FF_ERASE) { retval = -EINVAL; - break; + goto out; } req->retval = ff_erase.retval; uinput_request_done(udev, req); - break; + goto out; + } - default: - retval = -EINVAL; + size = _IOC_SIZE(cmd); + + /* Now check variable-length commands */ + switch (cmd & ~IOCSIZE_MASK) { + case UI_GET_SYSNAME(0): + if (udev->state != UIST_CREATED) { + retval = -ENOENT; + goto out; + } + name = dev_name(&udev->dev->dev); + retval = uinput_str_to_user(p, name, size); + goto out; } + retval = -EINVAL; out: mutex_unlock(&udev->mutex); return retval; diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index b6505454bcc..7b7add5061a 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { { KE_END, 0 } }; +static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { + { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ + { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ + { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ + { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ + { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ + { KE_WIFI, 0x78 }, /* satelite dish button */ + { KE_END, FE_WIFI_LED } +}; + static struct key_entry keymap_fujitsu_n3510[] __initdata = { { KE_KEY, 0x11, {KEY_PROG1} }, { KE_KEY, 0x12, {KEY_PROG2} }, @@ -654,6 +664,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_fs_amilo_pro_v3505 }, { + /* Fujitsu-Siemens Amilo Pro Edition V8210 */ + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), + }, + .driver_data = keymap_fs_amilo_pro_v8210 + }, + { /* Fujitsu-Siemens Amilo M7400 */ .callback = dmi_matched, .matches = { diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index caecffe8caf..858045694e9 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -848,7 +848,7 @@ static int gtco_probe(struct usb_interface *usbinterface, gtco->inputdevice = input_dev; /* Save interface information */ - gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); + gtco->usbdev = interface_to_usbdev(usbinterface); gtco->intf = usbinterface; /* Allocate some data for incoming reports */ diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 2175f341900..01d30cedde4 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -29,10 +29,13 @@ #include <linux/sysfs.h> #include <linux/input/mt.h> #include <linux/platform_data/zforce_ts.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #define WAIT_TIMEOUT msecs_to_jiffies(1000) #define FRAME_START 0xee +#define FRAME_MAXSIZE 257 /* Offsets of the different parts of the payload the controller sends */ #define PAYLOAD_HEADER 0 @@ -64,7 +67,7 @@ #define RESPONSE_STATUS 0X1e /* - * Notifications are send by the touch controller without + * Notifications are sent by the touch controller without * being requested by the driver and include for example * touch indications */ @@ -103,8 +106,8 @@ struct zforce_point { * @suspended device suspended * @access_mutex serialize i2c-access, to keep multipart reads together * @command_done completion to wait for the command result - * @command_mutex serialize commands send to the ic - * @command_waiting the id of the command that that is currently waiting + * @command_mutex serialize commands sent to the ic + * @command_waiting the id of the command that is currently waiting * for a result * @command_result returned result of the command */ @@ -235,7 +238,8 @@ static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger, (finger & 0xff), ((finger >> 8) & 0xff), (stylus & 0xff), ((stylus >> 8) & 0xff) }; - dev_dbg(&client->dev, "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n", + dev_dbg(&client->dev, + "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n", idle, finger, stylus); return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); @@ -255,7 +259,7 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1) static int zforce_start(struct zforce_ts *ts) { struct i2c_client *client = ts->client; - const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); + const struct zforce_ts_platdata *pdata = ts->pdata; int ret; dev_dbg(&client->dev, "starting device\n"); @@ -326,13 +330,14 @@ static int zforce_stop(struct zforce_ts *ts) static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) { struct i2c_client *client = ts->client; - const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); + const struct zforce_ts_platdata *pdata = ts->pdata; struct zforce_point point; int count, i, num = 0; count = payload[0]; if (count > ZFORCE_REPORT_POINTS) { - dev_warn(&client->dev, "to many coordinates %d, expected max %d\n", + dev_warn(&client->dev, + "too many coordinates %d, expected max %d\n", count, ZFORCE_REPORT_POINTS); count = ZFORCE_REPORT_POINTS; } @@ -421,7 +426,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) goto unlock; } - if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) { + if (buf[PAYLOAD_LENGTH] == 0) { dev_err(&client->dev, "invalid payload length: %d\n", buf[PAYLOAD_LENGTH]); ret = -EIO; @@ -471,9 +476,9 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) { struct zforce_ts *ts = dev_id; struct i2c_client *client = ts->client; - const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); + const struct zforce_ts_platdata *pdata = ts->pdata; int ret; - u8 payload_buffer[512]; + u8 payload_buffer[FRAME_MAXSIZE]; u8 *payload; /* @@ -494,8 +499,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) while (!gpio_get_value(pdata->gpio_int)) { ret = zforce_read_packet(ts, payload_buffer); if (ret < 0) { - dev_err(&client->dev, "could not read packet, ret: %d\n", - ret); + dev_err(&client->dev, + "could not read packet, ret: %d\n", ret); break; } @@ -539,7 +544,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) payload[RESPONSE_DATA + 4]; ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) | payload[RESPONSE_DATA + 6]; - dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n", + dev_dbg(&ts->client->dev, + "Firmware Version %04x:%04x %04x:%04x\n", ts->version_major, ts->version_minor, ts->version_build, ts->version_rev); @@ -552,7 +558,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) break; default: - dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n", + dev_err(&ts->client->dev, + "unrecognized response id: 0x%x\n", payload[RESPONSE_ID]); break; } @@ -618,7 +625,8 @@ static int zforce_suspend(struct device *dev) enable_irq_wake(client->irq); } else if (input->users) { - dev_dbg(&client->dev, "suspend without being a wakeup source\n"); + dev_dbg(&client->dev, + "suspend without being a wakeup source\n"); ret = zforce_stop(ts); if (ret) @@ -684,6 +692,45 @@ static void zforce_reset(void *data) gpio_set_value(ts->pdata->gpio_rst, 0); } +static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev) +{ + struct zforce_ts_platdata *pdata; + struct device_node *np = dev->of_node; + + if (!np) + return ERR_PTR(-ENOENT); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "failed to allocate platform data\n"); + return ERR_PTR(-ENOMEM); + } + + pdata->gpio_int = of_get_gpio(np, 0); + if (!gpio_is_valid(pdata->gpio_int)) { + dev_err(dev, "failed to get interrupt gpio\n"); + return ERR_PTR(-EINVAL); + } + + pdata->gpio_rst = of_get_gpio(np, 1); + if (!gpio_is_valid(pdata->gpio_rst)) { + dev_err(dev, "failed to get reset gpio\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(np, "x-size", &pdata->x_max)) { + dev_err(dev, "failed to get x-size property\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(np, "y-size", &pdata->y_max)) { + dev_err(dev, "failed to get y-size property\n"); + return ERR_PTR(-EINVAL); + } + + return pdata; +} + static int zforce_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -692,8 +739,11 @@ static int zforce_probe(struct i2c_client *client, struct input_dev *input_dev; int ret; - if (!pdata) - return -EINVAL; + if (!pdata) { + pdata = zforce_parse_dt(&client->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); if (!ts) @@ -798,7 +848,7 @@ static int zforce_probe(struct i2c_client *client, return ret; } - /* this gets the firmware version among other informations */ + /* this gets the firmware version among other information */ ret = zforce_command_wait(ts, COMMAND_STATUS); if (ret < 0) { dev_err(&client->dev, "couldn't get status, %d\n", ret); @@ -829,11 +879,20 @@ static struct i2c_device_id zforce_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, zforce_idtable); +#ifdef CONFIG_OF +static struct of_device_id zforce_dt_idtable[] = { + { .compatible = "neonode,zforce" }, + {}, +}; +MODULE_DEVICE_TABLE(of, zforce_dt_idtable); +#endif + static struct i2c_driver zforce_driver = { .driver = { .owner = THIS_MODULE, .name = "zforce-ts", .pm = &zforce_pm_ops, + .of_match_table = of_match_ptr(zforce_dt_idtable), }, .probe = zforce_probe, .id_table = zforce_idtable, |