From 221a27c240343b39052c05baa64deace845801ff Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 16 Sep 2013 08:32:54 -0700 Subject: Input: cypress_ps2 - remove casting the return value which is a void pointer Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cypress_ps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index f51765fff054..ef651ccf130f 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -679,7 +679,7 @@ int cypress_init(struct psmouse *psmouse) { struct cytp_data *cytp; - cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL); + cytp = kzalloc(sizeof(struct cytp_data), GFP_KERNEL); psmouse->private = (void *)cytp; if (cytp == NULL) return -ENOMEM; -- cgit v1.2.1 From 5d67e4c6f50d2706ef9cca522a093b30c8cba66a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 18 Sep 2013 07:45:27 -0700 Subject: Input: cobalt_btns - remove redundant dev_set_drvdata Driver core sets the data to NULL upon release or probe failure. Hence explicit setting is not necessary. Signed-off-by: Sachin Kamat Cc: Yoichi Yuasa Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cobalt_btns.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 4f77f87847e8..b5d71d245854 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -131,7 +131,6 @@ static int cobalt_buttons_probe(struct platform_device *pdev) err_free_mem: input_free_polled_device(poll_dev); kfree(bdev); - dev_set_drvdata(&pdev->dev, NULL); return error; } @@ -144,7 +143,6 @@ static int cobalt_buttons_remove(struct platform_device *pdev) input_free_polled_device(bdev->poll_dev); iounmap(bdev->reg); kfree(bdev); - dev_set_drvdata(dev, NULL); return 0; } -- cgit v1.2.1 From 4906a31b4c60b2499e63737f3194c596d4f86482 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 18 Sep 2013 07:47:53 -0700 Subject: Input: htcpen - remove redundant dev_set_drvdata Driver core sets the data to NULL upon release or probe failure. Hence explicit setting is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/htcpen.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 66500852341b..92e2243fb77d 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c @@ -186,8 +186,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id) release_region(HTCPEN_PORT_INIT, 1); release_region(HTCPEN_PORT_IRQ_CLEAR, 1); - dev_set_drvdata(dev, NULL); - return 0; } -- cgit v1.2.1 From 390de835b61228abf6646f2b14530edca8d7512f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 18 Sep 2013 07:48:18 -0700 Subject: Input: rb532_button - remove redundant dev_set_drvdata Driver core sets the data to NULL upon release or probe failure. Hence explicit setting is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rb532_button.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index fb4f8ac3343b..83fff38b86b3 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -87,7 +87,6 @@ static int rb532_button_remove(struct platform_device *pdev) input_unregister_polled_device(poll_dev); input_free_polled_device(poll_dev); - dev_set_drvdata(&pdev->dev, NULL); return 0; } -- cgit v1.2.1 From 8474caddccedcbf6da59f3ed3bc5c4d9442f8e5d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 18 Sep 2013 07:45:57 -0700 Subject: Input: cyttsp4_core - remove redundant dev_set_drvdata Driver core sets the data to NULL upon release or probe failure. Hence explicit setting is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp4_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index d038575f49db..42d830efa316 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -2113,7 +2113,6 @@ error_startup: error_request_irq: if (cd->cpdata->init) cd->cpdata->init(cd->cpdata, 0, dev); - dev_set_drvdata(dev, NULL); error_free_xfer: kfree(cd->xfer_buf); error_free_cd: @@ -2151,7 +2150,6 @@ int cyttsp4_remove(struct cyttsp4 *cd) free_irq(cd->irq, cd); if (cd->cpdata->init) cd->cpdata->init(cd->cpdata, 0, dev); - dev_set_drvdata(dev, NULL); cyttsp4_free_si_ptrs(cd); kfree(cd); return 0; -- cgit v1.2.1 From cbf0541374e2fcfdfdcaf8365c957a137eb9feea Mon Sep 17 00:00:00 2001 From: Ryan Mallon Date: Wed, 18 Sep 2013 12:40:47 -0700 Subject: Input: uinput - support injecting multiple events in one write() call Rework the code in uinput_inject_event so that it matches the code in evdev_write and allows injecting more than one event, or zero events. Signed-off-by: Ryan Mallon Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index a0a4bbaef02c..772835938a52 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -430,20 +430,30 @@ static int uinput_setup_device(struct uinput_device *udev, return retval; } -static ssize_t uinput_inject_event(struct uinput_device *udev, - const char __user *buffer, size_t count) +static ssize_t uinput_inject_events(struct uinput_device *udev, + const char __user *buffer, size_t count) { struct input_event ev; + size_t bytes = 0; - if (count < input_event_size()) + if (count != 0 && count < input_event_size()) return -EINVAL; - if (input_event_from_user(buffer, &ev)) - return -EFAULT; + while (bytes + input_event_size() <= count) { + /* + * Note that even if some events were fetched successfully + * we are still going to return EFAULT instead of partial + * count to let userspace know that it got it's buffers + * all wrong. + */ + if (input_event_from_user(buffer + bytes, &ev)) + return -EFAULT; - input_event(udev->dev, ev.type, ev.code, ev.value); + input_event(udev->dev, ev.type, ev.code, ev.value); + bytes += input_event_size(); + } - return input_event_size(); + return bytes; } static ssize_t uinput_write(struct file *file, const char __user *buffer, @@ -460,7 +470,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, return retval; retval = udev->state == UIST_CREATED ? - uinput_inject_event(udev, buffer, count) : + uinput_inject_events(udev, buffer, count) : uinput_setup_device(udev, buffer, count); mutex_unlock(&udev->mutex); -- cgit v1.2.1 From aed06b9cfcabf8644ac5f6f108c0b3d01522f88b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 18 Sep 2013 12:50:42 -0700 Subject: Input: add a driver to support Hyper-V synthetic keyboard Add a new driver to support synthetic keyboard. On the next generation Hyper-V guest firmware, many legacy devices will not be emulated and this driver will be required. I would like to thank Vojtech Pavlik for helping me with the details of the AT keyboard driver. I would also like to thank Dan Carpenter and Dmitry Torokhov for their detailed review of this driver. Signed-off-by: K. Y. Srinivasan Signed-off-by: Dmitry Torokhov --- drivers/input/serio/Kconfig | 10 + drivers/input/serio/Makefile | 1 + drivers/input/serio/hyperv-keyboard.c | 437 ++++++++++++++++++++++++++++++++++ 3 files changed, 448 insertions(+) create mode 100644 drivers/input/serio/hyperv-keyboard.c diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 1e691a3a79cb..a5f342e7ea91 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -267,4 +267,14 @@ config SERIO_OLPC_APSP To compile this driver as a module, choose M here: the module will be called olpc_apsp. +config HYPERV_KEYBOARD + tristate "Microsoft Synthetic Keyboard driver" + depends on HYPERV + default HYPERV + help + Select this option to enable the Hyper-V Keyboard driver. + + To compile this driver as a module, choose M here: the module will + be called hyperv_keyboard. + endif diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 12298b1c0e71..815d874fe724 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o obj-$(CONFIG_SERIO_APBPS2) += apbps2.o obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o +obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c new file mode 100644 index 000000000000..3a83c3c14b23 --- /dev/null +++ b/drivers/input/serio/hyperv-keyboard.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2013, Microsoft Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Current version 1.0 + * + */ +#define SYNTH_KBD_VERSION_MAJOR 1 +#define SYNTH_KBD_VERSION_MINOR 0 +#define SYNTH_KBD_VERSION (SYNTH_KBD_VERSION_MINOR | \ + (SYNTH_KBD_VERSION_MAJOR << 16)) + + +/* + * Message types in the synthetic input protocol + */ +enum synth_kbd_msg_type { + SYNTH_KBD_PROTOCOL_REQUEST = 1, + SYNTH_KBD_PROTOCOL_RESPONSE = 2, + SYNTH_KBD_EVENT = 3, + SYNTH_KBD_LED_INDICATORS = 4, +}; + +/* + * Basic message structures. + */ +struct synth_kbd_msg_hdr { + __le32 type; +}; + +struct synth_kbd_msg { + struct synth_kbd_msg_hdr header; + char data[]; /* Enclosed message */ +}; + +union synth_kbd_version { + __le32 version; +}; + +/* + * Protocol messages + */ +struct synth_kbd_protocol_request { + struct synth_kbd_msg_hdr header; + union synth_kbd_version version_requested; +}; + +#define PROTOCOL_ACCEPTED BIT(0) +struct synth_kbd_protocol_response { + struct synth_kbd_msg_hdr header; + __le32 proto_status; +}; + +#define IS_UNICODE BIT(0) +#define IS_BREAK BIT(1) +#define IS_E0 BIT(2) +#define IS_E1 BIT(3) +struct synth_kbd_keystroke { + struct synth_kbd_msg_hdr header; + __le16 make_code; + __le16 reserved0; + __le32 info; /* Additional information */ +}; + + +#define HK_MAXIMUM_MESSAGE_SIZE 256 + +#define KBD_VSC_SEND_RING_BUFFER_SIZE (10 * PAGE_SIZE) +#define KBD_VSC_RECV_RING_BUFFER_SIZE (10 * PAGE_SIZE) + +#define XTKBD_EMUL0 0xe0 +#define XTKBD_EMUL1 0xe1 +#define XTKBD_RELEASE 0x80 + + +/* + * Represents a keyboard device + */ +struct hv_kbd_dev { + struct hv_device *hv_dev; + struct serio *hv_serio; + struct synth_kbd_protocol_request protocol_req; + struct synth_kbd_protocol_response protocol_resp; + /* Synchronize the request/response if needed */ + struct completion wait_event; + spinlock_t lock; /* protects 'started' field */ + bool started; +}; + +static void hv_kbd_on_receive(struct hv_device *hv_dev, + struct synth_kbd_msg *msg, u32 msg_length) +{ + struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev); + struct synth_kbd_keystroke *ks_msg; + unsigned long flags; + u32 msg_type = __le32_to_cpu(msg->header.type); + u32 info; + u16 scan_code; + + switch (msg_type) { + case SYNTH_KBD_PROTOCOL_RESPONSE: + /* + * Validate the information provided by the host. + * If the host is giving us a bogus packet, + * drop the packet (hoping the problem + * goes away). + */ + if (msg_length < sizeof(struct synth_kbd_protocol_response)) { + dev_err(&hv_dev->device, + "Illegal protocol response packet (len: %d)\n", + msg_length); + break; + } + + memcpy(&kbd_dev->protocol_resp, msg, + sizeof(struct synth_kbd_protocol_response)); + complete(&kbd_dev->wait_event); + break; + + case SYNTH_KBD_EVENT: + /* + * Validate the information provided by the host. + * If the host is giving us a bogus packet, + * drop the packet (hoping the problem + * goes away). + */ + if (msg_length < sizeof(struct synth_kbd_keystroke)) { + dev_err(&hv_dev->device, + "Illegal keyboard event packet (len: %d)\n", + msg_length); + break; + } + + ks_msg = (struct synth_kbd_keystroke *)msg; + info = __le32_to_cpu(ks_msg->info); + + /* + * Inject the information through the serio interrupt. + */ + spin_lock_irqsave(&kbd_dev->lock, flags); + if (kbd_dev->started) { + if (info & IS_E0) + serio_interrupt(kbd_dev->hv_serio, + XTKBD_EMUL0, 0); + + scan_code = __le16_to_cpu(ks_msg->make_code); + if (info & IS_BREAK) + scan_code |= XTKBD_RELEASE; + + serio_interrupt(kbd_dev->hv_serio, scan_code, 0); + } + spin_unlock_irqrestore(&kbd_dev->lock, flags); + break; + + default: + dev_err(&hv_dev->device, + "unhandled message type %d\n", msg_type); + } +} + +static void hv_kbd_handle_received_packet(struct hv_device *hv_dev, + struct vmpacket_descriptor *desc, + u32 bytes_recvd, + u64 req_id) +{ + struct synth_kbd_msg *msg; + u32 msg_sz; + + switch (desc->type) { + case VM_PKT_COMP: + break; + + case VM_PKT_DATA_INBAND: + /* + * We have a packet that has "inband" data. The API used + * for retrieving the packet guarantees that the complete + * packet is read. So, minimally, we should be able to + * parse the payload header safely (assuming that the host + * can be trusted. Trusting the host seems to be a + * reasonable assumption because in a virtualized + * environment there is not whole lot you can do if you + * don't trust the host. + * + * Nonetheless, let us validate if the host can be trusted + * (in a trivial way). The interesting aspect of this + * validation is how do you recover if we discover that the + * host is not to be trusted? Simply dropping the packet, I + * don't think is an appropriate recovery. In the interest + * of failing fast, it may be better to crash the guest. + * For now, I will just drop the packet! + */ + + msg_sz = bytes_recvd - (desc->offset8 << 3); + if (msg_sz <= sizeof(struct synth_kbd_msg_hdr)) { + /* + * Drop the packet and hope + * the problem magically goes away. + */ + dev_err(&hv_dev->device, + "Illegal packet (type: %d, tid: %llx, size: %d)\n", + desc->type, req_id, msg_sz); + break; + } + + msg = (void *)desc + (desc->offset8 << 3); + hv_kbd_on_receive(hv_dev, msg, msg_sz); + break; + + default: + dev_err(&hv_dev->device, + "unhandled packet type %d, tid %llx len %d\n", + desc->type, req_id, bytes_recvd); + break; + } +} + +static void hv_kbd_on_channel_callback(void *context) +{ + struct hv_device *hv_dev = context; + void *buffer; + int bufferlen = 0x100; /* Start with sensible size */ + u32 bytes_recvd; + u64 req_id; + int error; + + buffer = kmalloc(bufferlen, GFP_ATOMIC); + if (!buffer) + return; + + while (1) { + error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen, + &bytes_recvd, &req_id); + switch (error) { + case 0: + if (bytes_recvd == 0) { + kfree(buffer); + return; + } + + hv_kbd_handle_received_packet(hv_dev, buffer, + bytes_recvd, req_id); + break; + + case -ENOBUFS: + kfree(buffer); + /* Handle large packet */ + bufferlen = bytes_recvd; + buffer = kmalloc(bytes_recvd, GFP_ATOMIC); + if (!buffer) + return; + break; + } + } +} + +static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev) +{ + struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev); + struct synth_kbd_protocol_request *request; + struct synth_kbd_protocol_response *response; + u32 proto_status; + int error; + + request = &kbd_dev->protocol_req; + memset(request, 0, sizeof(struct synth_kbd_protocol_request)); + request->header.type = __cpu_to_le32(SYNTH_KBD_PROTOCOL_REQUEST); + request->version_requested.version = __cpu_to_le32(SYNTH_KBD_VERSION); + + error = vmbus_sendpacket(hv_dev->channel, request, + sizeof(struct synth_kbd_protocol_request), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (error) + return error; + + if (!wait_for_completion_timeout(&kbd_dev->wait_event, 10 * HZ)) + return -ETIMEDOUT; + + response = &kbd_dev->protocol_resp; + proto_status = __le32_to_cpu(response->proto_status); + if (!(proto_status & PROTOCOL_ACCEPTED)) { + dev_err(&hv_dev->device, + "synth_kbd protocol request failed (version %d)\n", + SYNTH_KBD_VERSION); + return -ENODEV; + } + + return 0; +} + +static int hv_kbd_start(struct serio *serio) +{ + struct hv_kbd_dev *kbd_dev = serio->port_data; + unsigned long flags; + + spin_lock_irqsave(&kbd_dev->lock, flags); + kbd_dev->started = true; + spin_unlock_irqrestore(&kbd_dev->lock, flags); + + return 0; +} + +static void hv_kbd_stop(struct serio *serio) +{ + struct hv_kbd_dev *kbd_dev = serio->port_data; + unsigned long flags; + + spin_lock_irqsave(&kbd_dev->lock, flags); + kbd_dev->started = false; + spin_unlock_irqrestore(&kbd_dev->lock, flags); +} + +static int hv_kbd_probe(struct hv_device *hv_dev, + const struct hv_vmbus_device_id *dev_id) +{ + struct hv_kbd_dev *kbd_dev; + struct serio *hv_serio; + int error; + + kbd_dev = kzalloc(sizeof(struct hv_kbd_dev), GFP_KERNEL); + hv_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!kbd_dev || !hv_serio) { + error = -ENOMEM; + goto err_free_mem; + } + + kbd_dev->hv_dev = hv_dev; + kbd_dev->hv_serio = hv_serio; + spin_lock_init(&kbd_dev->lock); + init_completion(&kbd_dev->wait_event); + hv_set_drvdata(hv_dev, kbd_dev); + + hv_serio->dev.parent = &hv_dev->device; + hv_serio->id.type = SERIO_8042_XL; + hv_serio->port_data = kbd_dev; + strlcpy(hv_serio->name, dev_name(&hv_dev->device), + sizeof(hv_serio->name)); + strlcpy(hv_serio->phys, dev_name(&hv_dev->device), + sizeof(hv_serio->phys)); + + hv_serio->start = hv_kbd_start; + hv_serio->stop = hv_kbd_stop; + + error = vmbus_open(hv_dev->channel, + KBD_VSC_SEND_RING_BUFFER_SIZE, + KBD_VSC_RECV_RING_BUFFER_SIZE, + NULL, 0, + hv_kbd_on_channel_callback, + hv_dev); + if (error) + goto err_free_mem; + + error = hv_kbd_connect_to_vsp(hv_dev); + if (error) + goto err_close_vmbus; + + serio_register_port(kbd_dev->hv_serio); + return 0; + +err_close_vmbus: + vmbus_close(hv_dev->channel); +err_free_mem: + kfree(hv_serio); + kfree(kbd_dev); + return error; +} + +static int hv_kbd_remove(struct hv_device *hv_dev) +{ + struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev); + + serio_unregister_port(kbd_dev->hv_serio); + vmbus_close(hv_dev->channel); + kfree(kbd_dev); + + hv_set_drvdata(hv_dev, NULL); + + return 0; +} + +/* + * Keyboard GUID + * {f912ad6d-2b17-48ea-bd65-f927a61c7684} + */ +#define HV_KBD_GUID \ + .guid = { \ + 0x6d, 0xad, 0x12, 0xf9, 0x17, 0x2b, 0xea, 0x48, \ + 0xbd, 0x65, 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84 \ + } + +static const struct hv_vmbus_device_id id_table[] = { + /* Keyboard guid */ + { HV_KBD_GUID, }, + { }, +}; + +MODULE_DEVICE_TABLE(vmbus, id_table); + +static struct hv_driver hv_kbd_drv = { + .name = KBUILD_MODNAME, + .id_table = id_table, + .probe = hv_kbd_probe, + .remove = hv_kbd_remove, +}; + +static int __init hv_kbd_init(void) +{ + return vmbus_driver_register(&hv_kbd_drv); +} + +static void __exit hv_kbd_exit(void) +{ + vmbus_driver_unregister(&hv_kbd_drv); +} + +MODULE_LICENSE("GPL"); +module_init(hv_kbd_init); +module_exit(hv_kbd_exit); -- cgit v1.2.1 From 49e6c574508efc9c0914077af164245163ce1638 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 20 Sep 2013 09:12:52 -0700 Subject: Input: ad714x-spi - remove redundant spi_set_drvdata Driver core sets driver data to NULL upon failure or remove. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ad714x-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 61891486067c..3a90b710e309 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c @@ -108,7 +108,6 @@ static int ad714x_spi_remove(struct spi_device *spi) struct ad714x_chip *chip = spi_get_drvdata(spi); ad714x_remove(chip); - spi_set_drvdata(spi, NULL); return 0; } -- cgit v1.2.1 From 993c379219c0aa069ab046305b6b6a87a29c1d88 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 20 Sep 2013 09:38:05 -0700 Subject: Input: ad7877 - remove redundant spi_set_drvdata Driver core sets driver data to NULL upon failure or remove. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7877.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index f3a174a83c82..69834dd3c313 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -806,7 +806,6 @@ err_free_irq: err_free_mem: input_free_device(input_dev); kfree(ts); - spi_set_drvdata(spi, NULL); return err; } @@ -823,7 +822,6 @@ static int ad7877_remove(struct spi_device *spi) kfree(ts); dev_dbg(&spi->dev, "unregistered touchscreen\n"); - spi_set_drvdata(spi, NULL); return 0; } -- cgit v1.2.1 From 3a229b70d6fdd2aebf750997a5ca4e6b8885e7f6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 20 Sep 2013 09:38:28 -0700 Subject: Input: ad7879-spi - remove redundant spi_set_drvdata Driver core sets driver data to NULL upon failure or remove. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ad7879-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 606da5bd6115..1a7b1143536e 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -142,7 +142,6 @@ static int ad7879_spi_remove(struct spi_device *spi) struct ad7879 *ts = spi_get_drvdata(spi); ad7879_remove(ts); - spi_set_drvdata(spi, NULL); return 0; } -- cgit v1.2.1 From c7c8b533c7be077acf6cfee6d0f83ca57b55a19a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 20 Sep 2013 09:38:46 -0700 Subject: Input: tsc2005 - remove redundant spi_set_drvdata Driver core sets driver data to NULL upon failure or remove. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc2005.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 7213e8b07e79..811353353917 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -678,7 +678,6 @@ static int tsc2005_probe(struct spi_device *spi) err_remove_sysfs: sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); err_clear_drvdata: - spi_set_drvdata(spi, NULL); free_irq(spi->irq, ts); err_free_mem: input_free_device(input_dev); @@ -696,7 +695,6 @@ static int tsc2005_remove(struct spi_device *spi) input_unregister_device(ts->idev); kfree(ts); - spi_set_drvdata(spi, NULL); return 0; } -- cgit v1.2.1 From 36d3c510e6f0a05d6aec6bc54eb708bc6f01c3b4 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 20 Sep 2013 09:47:35 -0700 Subject: Input: wacom - support EMR and MFT sensors of Cintiq Companion Hybrid Adds support for the sensors integrated in to the Cintiq Companion Hybrid. These sensors use by-and-large the same protocol as the Cintiq 24HD touch. NOTE: The ExpressKeys on the Cintiq Companion Hybrid are wired to both the EMR controller and CPU GPIO pins. It may be necessary to disable their functionality in this driver if building a custom Android kernel for this device (lest two events be sent to userspace for every button press). Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 2 +- drivers/input/tablet/wacom_wac.c | 46 +++++++++++++++++++++++++++++++++++++++- drivers/input/tablet/wacom_wac.h | 1 + 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 79b69ea47f74..7e4cc2fd83e4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -548,7 +548,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* MT Tablet PC touch */ return wacom_set_device_mode(intf, 3, 4, 4); } - else if (features->type == WACOM_24HDT) { + else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { return wacom_set_device_mode(intf, 18, 3, 2); } } else if (features->device_type == BTN_TOOL_PEN) { diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b2aa503c16b1..45984afb040d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -477,7 +477,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (features->type >= INTUOS4S && features->type <= WACOM_24HD) { + if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) { t = (t << 1) | (data[1] & 1); } input_report_abs(input, ABS_PRESSURE, t); @@ -621,6 +621,22 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } else { input_report_abs(input, ABS_MISC, 0); } + } else if (features->type == CINTIQ_HYBRID) { + /* + * Do not send hardware buttons under Android. They + * are already sent to the system through GPIO (and + * have different meaning). + */ + input_report_key(input, BTN_1, (data[4] & 0x01)); + input_report_key(input, BTN_2, (data[4] & 0x02)); + input_report_key(input, BTN_3, (data[4] & 0x04)); + input_report_key(input, BTN_4, (data[4] & 0x08)); + + input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */ + input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */ + input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ + input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ + input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { int i; @@ -1327,6 +1343,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case WACOM_22HD: case WACOM_24HD: case DTK: + case CINTIQ_HYBRID: sync = wacom_intuos_irq(wacom_wac); break; @@ -1765,6 +1782,24 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, 0, 0); } break; + + case CINTIQ_HYBRID: + __set_bit(BTN_1, input_dev->keybit); + __set_bit(BTN_2, input_dev->keybit); + __set_bit(BTN_3, input_dev->keybit); + __set_bit(BTN_4, input_dev->keybit); + + __set_bit(BTN_5, input_dev->keybit); + __set_bit(BTN_6, input_dev->keybit); + __set_bit(BTN_7, input_dev->keybit); + __set_bit(BTN_8, input_dev->keybit); + __set_bit(BTN_0, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + wacom_setup_cintiq(wacom_wac); + break; } return 0; } @@ -2125,6 +2160,13 @@ static const struct wacom_features wacom_features_0x301 = static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x0307 = + { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59552, 33848, 2047, + 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; +static const struct wacom_features wacom_features_0x0309 = + { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 }; #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ @@ -2257,6 +2299,8 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0xFA) }, + { USB_DEVICE_WACOM(0x0307) }, + { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index dfc9e08e7f70..90ce10dadb33 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -80,6 +80,7 @@ enum { WACOM_22HD, DTK, WACOM_24HD, + CINTIQ_HYBRID, CINTIQ, WACOM_BEE, WACOM_13HD, -- cgit v1.2.1 From 4eb1830b492842023b4529bec901f576a4d9ed19 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Fri, 20 Sep 2013 09:48:46 -0700 Subject: Input: wacom - send proper tablet state info when pen leaves proximity The EMR sensor of Intuos4 and newer devices can send a packet with 0x20 in its second byte which contains only location information. This packet is sent when the pen is too far away to reliably obtain other information. Because only the location is updated userspace will continue to see stale information for other values, most notably TOUCH, PRESSURE, and DISTANCE. This patch ensures userspace is not left with stale device state information when the pen re-enters proximity (possibly leading to the assumption the pen is still in contact even though it is actually hovering). Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 45984afb040d..102480621079 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -427,6 +427,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) (features->type == WACOM_21UX2)) return 1; + /* Range Report */ + if ((data[1] & 0xfe) == 0x20) { + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); + } + /* Exit report */ if ((data[1] & 0xfe) == 0x80) { if (features->quirks == WACOM_QUIRK_MULTI_INPUT) -- cgit v1.2.1 From 1b2faaf7e219fc2905d75afcd4c815e5d39eda80 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 20 Sep 2013 09:49:46 -0700 Subject: Input: wacom - testing result shows get_report is unnecessary. Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 7e4cc2fd83e4..f8b30d0cb210 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -524,9 +524,6 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, report_id, rep_data, length, 1); - if (error >= 0) - error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, - report_id, rep_data, length, 1); } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); kfree(rep_data); -- cgit v1.2.1 From c2b0c273e59f66ded73fe04a9460fa1bcd494aa5 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 20 Sep 2013 09:50:14 -0700 Subject: Input: wacom - LED is only supported through digitizer interface Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f8b30d0cb210..e21197be6a5a 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -978,14 +978,17 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - wacom->led.select[0] = 0; - wacom->led.select[1] = 0; - wacom->led.llv = 32; - wacom->led.hlv = 0; - wacom->led.img_lum = 0; - - error = sysfs_create_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) { + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; + wacom->led.llv = 32; + wacom->led.hlv = 0; + wacom->led.img_lum = 0; + + error = sysfs_create_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); + } else + return 0; break; default: @@ -1021,8 +1024,9 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: - sysfs_remove_group(&wacom->intf->dev.kobj, - &intuos5_led_attr_group); + if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) + sysfs_remove_group(&wacom->intf->dev.kobj, + &intuos5_led_attr_group); break; } } -- cgit v1.2.1 From 9a35c411f904a662d3a39edea406d95ead8acea6 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 20 Sep 2013 09:51:56 -0700 Subject: Input: wacom - add support for three new Intuos Pro devices Acked-by: Chris Bagwell Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 10 +++++-- drivers/input/tablet/wacom_wac.c | 61 +++++++++++++++++++++++++++++++--------- drivers/input/tablet/wacom_wac.h | 3 ++ 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index e21197be6a5a..63971b8188b0 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -716,7 +716,7 @@ static int wacom_led_control(struct wacom *wacom) return -ENOMEM; if (wacom->wacom_wac.features.type >= INTUOS5S && - wacom->wacom_wac.features.type <= INTUOS5L) { + wacom->wacom_wac.features.type <= INTUOSPL) { /* * Touch Ring and crop mark LED luminance may take on * one of four values: @@ -978,6 +978,9 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) { wacom->led.select[0] = 0; wacom->led.select[1] = 0; @@ -1024,6 +1027,9 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOS5S: case INTUOS5: case INTUOS5L: + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) sysfs_remove_group(&wacom->intf->dev.kobj, &intuos5_led_attr_group); @@ -1299,7 +1305,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i * HID descriptor. If this is the touch interface (wMaxPacketSize * of WACOM_PKGLEN_BBTOUCH3), override the table values. */ - if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + if (features->type >= INTUOS5S && features->type <= INTUOSPL) { if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { features->device_type = BTN_TOOL_FINGER; features->pktlen = WACOM_PKGLEN_BBTOUCH3; diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 102480621079..9c8eded2e504 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -644,14 +644,14 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ - } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { int i; /* Touch ring mode switch has no capacitive sensor */ input_report_key(input, BTN_0, (data[3] & 0x01)); /* - * ExpressKeys on Intuos5 have a capacitive sensor in + * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in * addition to the mechanical switch. Switch data is * stored in data[4], capacitive data in data[5]. */ @@ -739,7 +739,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) features->type == INTUOS4 || features->type == INTUOS4S || features->type == INTUOS5 || - features->type == INTUOS5S)) { + features->type == INTUOS5S || + features->type == INTUOSPM || + features->type == INTUOSPS)) { return 0; } @@ -792,8 +794,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ - if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || - (features->type >= INTUOS5S && features->type <= INTUOS5L)) { + if (features->type >= INTUOS4S && features->type <= INTUOSPL) { input_report_key(input, BTN_LEFT, data[6] & 0x01); input_report_key(input, BTN_MIDDLE, data[6] & 0x02); input_report_key(input, BTN_RIGHT, data[6] & 0x04); @@ -820,7 +821,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) } } } else if ((features->type < INTUOS3S || features->type == INTUOS3L || - features->type == INTUOS4L || features->type == INTUOS5L) && + features->type == INTUOS4L || features->type == INTUOS5L || + features->type == INTUOSPL) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ input_report_key(input, BTN_LEFT, data[8] & 0x01); @@ -1130,6 +1132,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) { + struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->input; bool touch = data[1] & 0x80; int slot = input_mt_get_slot_by_key(input, data[0]); @@ -1145,14 +1148,23 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) if (touch) { int x = (data[2] << 4) | (data[4] >> 4); int y = (data[3] << 4) | (data[4] & 0x0f); - int a = data[5]; + int width, height; - // "a" is a scaled-down area which we assume is roughly - // circular and which can be described as: a=(pi*r^2)/C. - int x_res = input_abs_get_res(input, ABS_X); - int y_res = input_abs_get_res(input, ABS_Y); - int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); - int height = width * y_res / x_res; + if (features->type >= INTUOSPS && features->type <= INTUOSPL) { + width = data[5]; + height = data[6]; + } else { + /* + * "a" is a scaled-down area which we assume is + * roughly circular and which can be described as: + * a=(pi*r^2)/C. + */ + int a = data[5]; + int x_res = input_abs_get_res(input, ABS_X); + int y_res = input_abs_get_res(input, ABS_Y); + width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); + height = width * y_res / x_res; + } input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); @@ -1361,6 +1373,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case INTUOS5S: case INTUOS5: case INTUOS5L: + case INTUOSPS: + case INTUOSPM: + case INTUOSPL: if (len == WACOM_PKGLEN_BBTOUCH3) sync = wacom_bpt3_touch(wacom_wac); else @@ -1444,7 +1459,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->type >= INTUOS5S && features->type <= INTUOSPL) || (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; @@ -1651,6 +1666,8 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS5: case INTUOS5L: + case INTUOSPM: + case INTUOSPL: if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_7, input_dev->keybit); __set_bit(BTN_8, input_dev->keybit); @@ -1658,6 +1675,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case INTUOS5S: + case INTUOSPS: __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (features->device_type == BTN_TOOL_PEN) { @@ -1994,6 +2012,18 @@ static const struct wacom_features wacom_features_0x29 = static const struct wacom_features wacom_features_0x2A = { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0x314 = + { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, + 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x315 = + { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, + 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; +static const struct wacom_features wacom_features_0x317 = + { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, + 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .touch_max = 16 }; static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2300,6 +2330,9 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x300) }, { USB_DEVICE_WACOM(0x301) }, { USB_DEVICE_WACOM(0x304) }, + { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 90ce10dadb33..2a432e688e51 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -76,6 +76,9 @@ enum { INTUOS5S, INTUOS5, INTUOS5L, + INTUOSPS, + INTUOSPM, + INTUOSPL, WACOM_21UX2, WACOM_22HD, DTK, -- cgit v1.2.1 From 39116e26eb27dc051977b27ef4b2e90cd4993f86 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:47:35 -0700 Subject: Input: lpc32xx-keys - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lpc32xx-keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index 42181435fe67..8b1b01361ec6 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -383,7 +383,7 @@ static struct platform_driver lpc32xx_kscan_driver = { .name = DRV_NAME, .owner = THIS_MODULE, .pm = &lpc32xx_kscan_pm_ops, - .of_match_table = of_match_ptr(lpc32xx_kscan_match), + .of_match_table = lpc32xx_kscan_match, } }; -- cgit v1.2.1 From 4c93ca5ff29a9228e9799f64287d540e6c5b6e32 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:49:32 -0700 Subject: Input: nspire-keypad - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/nspire-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index b3e3edab6d9f..9981928234cd 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -267,7 +267,7 @@ static struct platform_driver nspire_keypad_driver = { .driver = { .name = "nspire-keypad", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(nspire_keypad_dt_match), + .of_match_table = nspire_keypad_dt_match, }, .probe = nspire_keypad_probe, }; -- cgit v1.2.1 From 3cbd04f856467d8e3b2cb15194508f38c507047a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:50:31 -0700 Subject: Input: tegra-kbc - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 9cd20e6905a0..8508879f6faf 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -614,7 +614,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) unsigned int keymap_rows; const struct of_device_id *match; - match = of_match_device(of_match_ptr(tegra_kbc_of_match), &pdev->dev); + match = of_match_device(tegra_kbc_of_match, &pdev->dev); kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); if (!kbc) { -- cgit v1.2.1 From dee964c0b82230c6fc291514b925f030e6f72a4c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:51:28 -0700 Subject: Input: sirfsoc-onkey - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/misc/sirfsoc-onkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index 0621c367049a..7b8b03e0d0be 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c @@ -153,7 +153,7 @@ static struct platform_driver sirfsoc_pwrc_driver = { .name = "sirfsoc-pwrc", .owner = THIS_MODULE, .pm = &sirfsoc_pwrc_pm_ops, - .of_match_table = of_match_ptr(sirfsoc_pwrc_of_match), + .of_match_table = sirfsoc_pwrc_of_match, } }; -- cgit v1.2.1 From 085f17c6542c089e094633070d0e2e466f6da80b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:52:12 -0700 Subject: Input: egalax_ts - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/egalax_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index ef5fcb0945e9..054d22583248 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -273,7 +273,7 @@ static struct i2c_driver egalax_ts_driver = { .name = "egalax_ts", .owner = THIS_MODULE, .pm = &egalax_ts_pm_ops, - .of_match_table = of_match_ptr(egalax_ts_dt_ids), + .of_match_table = egalax_ts_dt_ids, }, .id_table = egalax_ts_id, .probe = egalax_ts_probe, -- cgit v1.2.1 From 8e6146bf5b779dd8c78df625549d1f92beaa23e7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:53:52 -0700 Subject: Input: ti_am335x_tsc - remove redundant of_match_ptr The data structure of_match_ptr() protects is always compiled in. Hence of_match_ptr() is not needed. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ti_am335x_tsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index e1c5300cacfc..df9b24f7e2cb 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -505,7 +505,7 @@ static struct platform_driver ti_tsc_driver = { .name = "TI-am335x-tsc", .owner = THIS_MODULE, .pm = TITSC_PM_OPS, - .of_match_table = of_match_ptr(ti_tsc_dt_ids), + .of_match_table = ti_tsc_dt_ids, }, }; module_platform_driver(ti_tsc_driver); -- cgit v1.2.1 From 415a4caae91c42fa1f6b79f8b503e0814d847b69 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:55:14 -0700 Subject: Input: gpio_keys - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 440ce32462ba..2db13246eb8e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 278017030db78799055f5459ed9722568c9cf9e7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:55:33 -0700 Subject: Input: gpio_keys_polled - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys_polled.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index cd5ed9e22168..4e428199e580 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include -- cgit v1.2.1 From 95ba7407e29292eda2ca211845347ad2ccff2842 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:55:51 -0700 Subject: Input: pxa27x_keypad - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/pxa27x_keypad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 134c3b404a54..5446ad4e4aeb 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include -- cgit v1.2.1 From 9dbe4c326ecae28b5b917d21eeeef57251a9d1aa Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:56:09 -0700 Subject: Input: pwm-beeper - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pwm-beeper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 2ff4d1c78ab8..940566e7be13 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 2e45e539a90afbfe572edc0f34ae367a080de360 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:56:24 -0700 Subject: Input: rotary_encoder - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 5b1aff825138..f920ba7ab51f 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include -- cgit v1.2.1 From 4d6e482675f13e33599fc3d18fc723959be0a9b6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sun, 6 Oct 2013 00:56:40 -0700 Subject: Input: st1232 - include linux/of.h header 'of_match_ptr' is defined in linux/of.h. Include it explicitly. Signed-off-by: Sachin Kamat Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 1740a2496371..2f03b2f289dd 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 1ccd33b8f69f9df7f11b0ec08259058164831ca5 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 8 Oct 2013 22:48:33 -0700 Subject: Input: clarify gamepad API ABS values It wasn't really clear from the gamepad-API description how ABS values are mapped exactly. Clarify that negative is left/up and positive is right/down. Unfortunately, this means I screwed up the Wii U ProController ABI. Anyhow, this just means we continue to have 0 compatible gamepad drivers in the kernel. User-space needs to fix them up, anyway, as all other gamepads are also incompatible. Signed-off-by: David Herrmann Signed-off-by: Dmitry Torokhov --- Documentation/input/gamepad.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt index 8002c894c6b0..31bb6a4029ef 100644 --- a/Documentation/input/gamepad.txt +++ b/Documentation/input/gamepad.txt @@ -122,12 +122,14 @@ D-Pad: BTN_DPAD_* Analog buttons are reported as: ABS_HAT0X and ABS_HAT0Y + (for ABS values negative is left/up, positive is right/down) Analog-Sticks: The left analog-stick is reported as ABS_X, ABS_Y. The right analog stick is reported as ABS_RX, ABS_RY. Zero, one or two sticks may be present. If analog-sticks provide digital buttons, they are mapped accordingly as BTN_THUMBL (first/left) and BTN_THUMBR (second/right). + (for ABS values negative is left/up, positive is right/down) Triggers: Trigger buttons can be available as digital or analog buttons or both. User- @@ -138,6 +140,7 @@ Triggers: ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL). If only one trigger-button combination is present (upper+lower), they are reported as "right" triggers (BTN_TR/ABS_HAT1X). + (ABS trigger values start at 0, pressure is reported as positive values) Menu-Pad: Menu buttons are always digital and are mapped according to their location -- cgit v1.2.1 From a4da47527d9f2e19a66527379418a5d13de9fff1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 15 Oct 2013 23:37:44 -0700 Subject: Input: nspire-keypad - add missing clk_disable_unprepare() on error path Add the missing clk_disable_unprepare() before return from nspire_keypad_open() in the error handling case. Signed-off-by: Wei Yongjun Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/nspire-keypad.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index 9981928234cd..b31064981e96 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -143,8 +143,10 @@ static int nspire_keypad_open(struct input_dev *input) return error; error = nspire_keypad_chip_init(keypad); - if (error) + if (error) { + clk_disable_unprepare(keypad->clk); return error; + } return 0; } -- cgit v1.2.1 From 57bcfce377d26f84d7b135512a4599f88b85ac52 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 15 Oct 2013 23:44:00 -0700 Subject: Input: wacom - not all multi-interface devices support touch Some multi-interface devices support expresskeys on a separate interface, such as Bamboo; some multi-interface devices do not support touch at all, such as Pen only Intuos5. Make sure we report the right device names. Tested-by: Jason Gerecke Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 57 +++++++++++++++++++++++++--------------- drivers/input/tablet/wacom_wac.h | 4 ++- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 63971b8188b0..8a90da11365f 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -1188,34 +1188,47 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features = *((struct wacom_features *)id->driver_info); wacom_wac1->features.device_type = BTN_TOOL_PEN; + snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", + wacom_wac1->features.name); error = wacom_register_input(wacom1); if (error) - goto fail1; + goto fail; /* Touch interface */ - wacom_wac2->features = - *((struct wacom_features *)id->driver_info); - wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac2->features.device_type = BTN_TOOL_FINGER; - wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; - error = wacom_register_input(wacom2); - if (error) - goto fail2; + if (wacom_wac1->features.touch_max) { + wacom_wac2->features = + *((struct wacom_features *)id->driver_info); + wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; + wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; + if (wacom_wac2->features.touch_max) + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Finger",wacom_wac2->features.name); + else + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Pad",wacom_wac2->features.name); + error = wacom_register_input(wacom2); + if (error) + goto fail; + } error = wacom_initialize_battery(wacom); if (error) - goto fail3; + goto fail; } return; -fail3: - input_unregister_device(wacom_wac2->input); - wacom_wac2->input = NULL; -fail2: - input_unregister_device(wacom_wac1->input); - wacom_wac1->input = NULL; -fail1: +fail: + if (wacom_wac2->input) { + input_unregister_device(wacom_wac2->input); + wacom_wac2->input = NULL; + } + + if (wacom_wac1->input) { + input_unregister_device(wacom_wac1->input); + wacom_wac1->input = NULL; + } return; } @@ -1332,10 +1345,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_device *other_dev; /* Append the device type to the name */ - strlcat(wacom_wac->name, - features->device_type == BTN_TOOL_PEN ? - " Pen" : " Finger", - sizeof(wacom_wac->name)); + if (features->device_type != BTN_TOOL_FINGER) + strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); + else if (features->touch_max) + strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + else + strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 2a432e688e51..fd23a3790605 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -14,6 +14,8 @@ /* maximum packet length for USB devices */ #define WACOM_PKGLEN_MAX 64 +#define WACOM_NAME_MAX 64 + /* packet length for individual models */ #define WACOM_PKGLEN_PENPRTN 7 #define WACOM_PKGLEN_GRAPHIRE 8 @@ -130,7 +132,7 @@ struct wacom_shared { }; struct wacom_wac { - char name[64]; + char name[WACOM_NAME_MAX]; unsigned char *data; int tool[2]; int id[2]; -- cgit v1.2.1 From 9354f263383975ed5e11eb5a9cf21f2596f95be2 Mon Sep 17 00:00:00 2001 From: Yunkang Tang Date: Tue, 15 Oct 2013 23:50:38 -0700 Subject: Input: ALPS - change secondary device's name Change the dev2's name from "PS/2 Mouse" to "ALPS PS/2 Device". Signed-off-by: Yunkang Tang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7c5d72a6a26a..ca7a26f1dce8 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1792,7 +1792,7 @@ int alps_init(struct psmouse *psmouse) snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); dev2->phys = priv->phys; dev2->name = (priv->flags & ALPS_DUALPOINT) ? - "DualPoint Stick" : "PS/2 Mouse"; + "DualPoint Stick" : "ALPS PS/2 Device"; dev2->id.bustype = BUS_I8042; dev2->id.vendor = 0x0002; dev2->id.product = PSMOUSE_ALPS; -- cgit v1.2.1 From 33777f34b5cc16a9fb2cd480e7db84c8de631fde Mon Sep 17 00:00:00 2001 From: Majunath Goudar Date: Tue, 22 Oct 2013 16:00:27 -0700 Subject: Input: fix PWM-related undefined reference errors This patch adds a PWM dependency to configure the INPUT_MAX8997_HAPTIC and INPUT_PWM_BEEPER. Without this patch, build system can lead to build failure. This was observed during randconfig testing, in which INPUT_MAX8997_HAPTIC or INPUT_PWM_BEEPER was enabled w/o PWM being enabled, leading to the following errors: init/built-in.o drivers/built-in.o: In function `max8997_haptic_disable': :(.text+0x1073a0): undefined reference to `pwm_disable' drivers/built-in.o: In function `max8997_haptic_remove': :(.text+0x1073fc): undefined reference to `pwm_free' drivers/built-in.o: In function `max8997_haptic_play_effect_work': :(.text+0x1074f0): undefined reference to `pwm_config' :(.text+0x1075b0): undefined reference to `pwm_enable' drivers/built-in.o: In function `max8997_haptic_probe': :(.text+0x1076f8): undefined reference to `pwm_request' :(.text+0x1077e8): undefined reference to `pwm_free' drivers/built-in.o: In function `pwm_beeper_resume': :(.text+0x1081a4): undefined reference to `pwm_config' make: *** [vmlinux] Error 1 Signed-off-by: Manjunath Goudar Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index aa51baaa9b1e..5f4967d01bc3 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -156,7 +156,7 @@ config INPUT_MAX8925_ONKEY config INPUT_MAX8997_HAPTIC tristate "MAXIM MAX8997 haptic controller support" - depends on HAVE_PWM && MFD_MAX8997 + depends on PWM && HAVE_PWM && MFD_MAX8997 select INPUT_FF_MEMLESS help This option enables device driver support for the haptic controller @@ -461,7 +461,7 @@ config INPUT_PCF8574 config INPUT_PWM_BEEPER tristate "PWM beeper support" - depends on HAVE_PWM || PWM + depends on PWM && HAVE_PWM help Say Y here to get support for PWM based beeper devices. -- cgit v1.2.1 From c2e609599a57926f20b324d05b164aabe9e372ed Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Wed, 16 Oct 2013 16:52:14 -0700 Subject: Input: cypress_ps2 - remove useless cast Get rid of unnecessary (void *) casting in 'cypress_init' function. Signed-off-by: Geyslan G. Bem Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cypress_ps2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index ef651ccf130f..1d81a7467501 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -680,14 +680,14 @@ int cypress_init(struct psmouse *psmouse) struct cytp_data *cytp; cytp = kzalloc(sizeof(struct cytp_data), GFP_KERNEL); - psmouse->private = (void *)cytp; - if (cytp == NULL) + if (!cytp) return -ENOMEM; - cypress_reset(psmouse); - + psmouse->private = cytp; psmouse->pktsize = 8; + cypress_reset(psmouse); + if (cypress_query_hardware(psmouse)) { psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); goto err_exit; -- cgit v1.2.1 From 5df682b297f6b23ec35615ed7bb50cbb25d25869 Mon Sep 17 00:00:00 2001 From: Joseph Salisbury Date: Wed, 16 Oct 2013 09:19:40 -0700 Subject: Input: cypress_ps2 - do not consider data bad if palm is detected If hardware (or firmware) detects palm on the surface of the device it does not mean that the data packet is bad from the protocol standpoint. Instead of reporting PSMOUSE_BAD_DATA in this case simply threat it as if nothing touches the surface. BugLink: http://bugs.launchpad.net/bugs/1229361 Signed-off-by: Joseph Salisbury Tested-by: Kamal Mostafa Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cypress_ps2.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index 1d81a7467501..a5869a856ea5 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -439,7 +439,7 @@ static int cypress_get_finger_count(unsigned char header_byte) case 2: return 5; default: /* Invalid contact (e.g. palm). Ignore it. */ - return -1; + return 0; } } @@ -452,17 +452,10 @@ static int cypress_parse_packet(struct psmouse *psmouse, { unsigned char *packet = psmouse->packet; unsigned char header_byte = packet[0]; - int contact_cnt; memset(report_data, 0, sizeof(struct cytp_report_data)); - contact_cnt = cypress_get_finger_count(header_byte); - - if (contact_cnt < 0) /* e.g. palm detect */ - return -EINVAL; - - report_data->contact_cnt = contact_cnt; - + report_data->contact_cnt = cypress_get_finger_count(header_byte); report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; if (report_data->contact_cnt == 1) { @@ -535,11 +528,9 @@ static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) int slots[CYTP_MAX_MT_SLOTS]; int n; - if (cypress_parse_packet(psmouse, cytp, &report_data)) - return; + cypress_parse_packet(psmouse, cytp, &report_data); n = report_data.contact_cnt; - if (n > CYTP_MAX_MT_SLOTS) n = CYTP_MAX_MT_SLOTS; @@ -605,10 +596,6 @@ static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; contact_cnt = cypress_get_finger_count(packet[0]); - - if (contact_cnt < 0) - return PSMOUSE_BAD_DATA; - if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); else -- cgit v1.2.1 From 92eb77d0ffbaa71b501a0a8dabf09a351bf4267f Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 31 Oct 2013 00:25:34 -0700 Subject: Input: evdev - fall back to vmalloc for client event buffer evdev always tries to allocate the event buffer for clients using kzalloc rather than vmalloc, presumably to avoid mapping overhead where possible. However, drivers like bcm5974, which claims support for reporting 16 fingers simultaneously, can have an extraordinarily large buffer. The resultant contiguous order-4 allocation attempt fails due to fragmentation, and the device is thus unusable until reboot. Try kzalloc if we can to avoid the mapping overhead, but if that fails, fall back to vzalloc. Signed-off-by: Daniel Stone Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index b6ded17b3be3..a06e12552886 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -369,7 +371,11 @@ static int evdev_release(struct inode *inode, struct file *file) mutex_unlock(&evdev->mutex); evdev_detach_client(evdev, client); - kfree(client); + + if (is_vmalloc_addr(client)) + vfree(client); + else + kfree(client); evdev_close_device(evdev); @@ -389,12 +395,14 @@ static int evdev_open(struct inode *inode, struct file *file) { struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); + unsigned int size = sizeof(struct evdev_client) + + bufsize * sizeof(struct input_event); struct evdev_client *client; int error; - client = kzalloc(sizeof(struct evdev_client) + - bufsize * sizeof(struct input_event), - GFP_KERNEL); + client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!client) + client = vzalloc(size); if (!client) return -ENOMEM; -- cgit v1.2.1 From 78551277e4df57864b0b0e7f85c23ede2be2edb8 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 31 Oct 2013 00:33:54 -0700 Subject: Input: i8042 - add PNP modaliases This allows the module to be autoloaded in the common case. In order to work on non-PnP systems the module should be compiled in or loaded unconditionally at boot (c.f. modules-load.d(5)), as before. Signed-off-by: Tom Gundersen Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5f306f79da0c..0ec9abbe31fe 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -765,6 +765,7 @@ static struct pnp_device_id pnp_kbd_devids[] = { { .id = "CPQA0D7", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_kbd_devids); static struct pnp_driver i8042_pnp_kbd_driver = { .name = "i8042 kbd", @@ -786,6 +787,7 @@ static struct pnp_device_id pnp_aux_devids[] = { { .id = "SYN0801", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_aux_devids); static struct pnp_driver i8042_pnp_aux_driver = { .name = "i8042 aux", -- cgit v1.2.1 From bcd2623073e98f69f84720308db0b142c4da0bd6 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 31 Oct 2013 00:38:30 -0700 Subject: Input: allow deselecting serio drivers even without CONFIG_EXPERT There is plenty of consumer hardware (e.g., mac books) that does not use AT keyboards or PS/2 mice. It therefore makes sense for distro kernels to build the related drivers as modules to avoid loading them on hardware that does not need them. As such, these options should no longer be protected by EXPERT. Moreover, building these drivers as modules gets rid of the following ugly error during boot: [ 2.337745] i8042: PNP: No PS/2 controller found. Probing ports directly. [ 3.439537] i8042: No controller found Signed-off-by: Tom Gundersen Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 4 ++-- drivers/input/serio/Kconfig | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c1edd39bc5ba..1fa37e6d004e 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -2,7 +2,7 @@ # Input core configuration # menuconfig INPUT_KEYBOARD - bool "Keyboards" if EXPERT || !X86 + bool "Keyboards" default y help Say Y here, and a list of supported keyboards will be displayed. @@ -67,7 +67,7 @@ config KEYBOARD_ATARI module will be called atakbd. config KEYBOARD_ATKBD - tristate "AT keyboard" if EXPERT || !X86 + tristate "AT keyboard" default y select SERIO select SERIO_LIBPS2 diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 296cb88d7008..5a96acb667ea 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -2,7 +2,7 @@ # Input core configuration # config SERIO - tristate "Serial I/O support" if EXPERT || !X86 + tristate "Serial I/O support" default y help Say Yes here if you have any input device that uses serial I/O to @@ -19,7 +19,7 @@ config SERIO if SERIO config SERIO_I8042 - tristate "i8042 PC Keyboard controller" if EXPERT || !X86 + tristate "i8042 PC Keyboard controller" default y depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \ @@ -170,7 +170,7 @@ config SERIO_MACEPS2 module will be called maceps2. config SERIO_LIBPS2 - tristate "PS/2 driver library" if EXPERT + tristate "PS/2 driver library" depends on SERIO_I8042 || SERIO_I8042=n help Say Y here if you are using a driver for device connected -- cgit v1.2.1 From dfaaed08ecc01bd513248ba7999daf50ce028352 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 31 Oct 2013 00:44:49 -0700 Subject: Input: mousedev - allow disabling even without CONFIG_EXPERT Moust (if not all) modern software, including X, uses /dev/eventX rather than the legacy /dev/mouseX devices. It therefore makes sense for general-purpose (distro) kernels to use MOUSEDV=m (or even n), so let's drop the EXPERT=y requirement. Signed-off-by: Tom Gundersen Signed-off-by: Dmitry Torokhov --- drivers/input/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 38b523a1ece0..a11ff74a5127 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -80,7 +80,7 @@ config INPUT_MATRIXKMAP comment "Userland interfaces" config INPUT_MOUSEDEV - tristate "Mouse interface" if EXPERT + tristate "Mouse interface" default y help Say Y here if you want your mouse to be accessible as char devices -- cgit v1.2.1 From 95079b8aa84015dc9032e42a1844dd78f76c3d2f Mon Sep 17 00:00:00 2001 From: Kang Hu Date: Thu, 31 Oct 2013 00:47:53 -0700 Subject: Input: remove a redundant max() call dev->hint_events_per_packet is guaranteed to be >= packet_size. so an extra max() call is not needed. Signed-off-by: Kang Hu Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index c04469928925..fb513daa40f7 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2048,7 +2048,7 @@ int input_register_device(struct input_dev *dev) if (dev->hint_events_per_packet < packet_size) dev->hint_events_per_packet = packet_size; - dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; + dev->max_vals = dev->hint_events_per_packet + 2; dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); if (!dev->vals) { error = -ENOMEM; -- cgit v1.2.1 From e4a42f655fdbfadc41f8b2f95dca5e5d395015f5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 31 Oct 2013 00:48:28 -0700 Subject: Input: sh_keysc - enable the driver on all ARM platforms Renesas ARM platforms are transitioning from single-platform to multi-platform kernels using the new ARCH_SHMOBILE_MULTI. Make the driver available on all ARM platforms to enable it on both ARCH_SHMOBILE and ARCH_SHMOBILE_MULTI, and increase build testing coverage with COMPILE_TEST. Signed-off-by: Laurent Pinchart Acked-by: Simon Horman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1fa37e6d004e..bb174c1a9886 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -525,7 +525,7 @@ config KEYBOARD_SUNKBD config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" - depends on SUPERH || ARCH_SHMOBILE + depends on SUPERH || ARM || COMPILE_TEST help Say Y here if you want to use a keypad attached to the KEYSC block on SuperH processors such as sh7722 and sh7343. -- cgit v1.2.1 From c6d81bd7237b5785080087bcf796ce456ef69557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Thu, 31 Oct 2013 01:25:32 -0700 Subject: Input: add driver for Neonode zForce based touchscreens This adds a driver for touchscreens using the zforce infrared technology from Neonode connected via i2c to the host system. It supports multitouch with up to two fingers and tracking of the contacts in hardware. Signed-off-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 13 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/zforce_ts.c | 836 ++++++++++++++++++++++++++++++++ include/linux/platform_data/zforce_ts.h | 26 + 4 files changed, 876 insertions(+) create mode 100644 drivers/input/touchscreen/zforce_ts.c create mode 100644 include/linux/platform_data/zforce_ts.h diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e09ec67957a3..00d1e547b211 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -919,4 +919,17 @@ config TOUCHSCREEN_TPS6507X To compile this driver as a module, choose M here: the module will be called tps6507x_ts. +config TOUCHSCREEN_ZFORCE + tristate "Neonode zForce infrared touchscreens" + depends on I2C + depends on GPIOLIB + help + Say Y here if you have a touchscreen using the zforce + infraread technology from Neonode. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called zforce_ts. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f5216c1bf53e..7587883b8d38 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -75,3 +75,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o +obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c new file mode 100644 index 000000000000..75762d6ff3ba --- /dev/null +++ b/drivers/input/touchscreen/zforce_ts.c @@ -0,0 +1,836 @@ +/* + * Copyright (C) 2012-2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * based in parts on Nook zforce driver + * + * Copyright (C) 2010 Barnes & Noble, Inc. + * Author: Pieter Truter + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WAIT_TIMEOUT msecs_to_jiffies(1000) + +#define FRAME_START 0xee + +/* Offsets of the different parts of the payload the controller sends */ +#define PAYLOAD_HEADER 0 +#define PAYLOAD_LENGTH 1 +#define PAYLOAD_BODY 2 + +/* Response offsets */ +#define RESPONSE_ID 0 +#define RESPONSE_DATA 1 + +/* Commands */ +#define COMMAND_DEACTIVATE 0x00 +#define COMMAND_INITIALIZE 0x01 +#define COMMAND_RESOLUTION 0x02 +#define COMMAND_SETCONFIG 0x03 +#define COMMAND_DATAREQUEST 0x04 +#define COMMAND_SCANFREQ 0x08 +#define COMMAND_STATUS 0X1e + +/* + * Responses the controller sends as a result of + * command requests + */ +#define RESPONSE_DEACTIVATE 0x00 +#define RESPONSE_INITIALIZE 0x01 +#define RESPONSE_RESOLUTION 0x02 +#define RESPONSE_SETCONFIG 0x03 +#define RESPONSE_SCANFREQ 0x08 +#define RESPONSE_STATUS 0X1e + +/* + * Notifications are send by the touch controller without + * being requested by the driver and include for example + * touch indications + */ +#define NOTIFICATION_TOUCH 0x04 +#define NOTIFICATION_BOOTCOMPLETE 0x07 +#define NOTIFICATION_OVERRUN 0x25 +#define NOTIFICATION_PROXIMITY 0x26 +#define NOTIFICATION_INVALID_COMMAND 0xfe + +#define ZFORCE_REPORT_POINTS 2 +#define ZFORCE_MAX_AREA 0xff + +#define STATE_DOWN 0 +#define STATE_MOVE 1 +#define STATE_UP 2 + +#define SETCONFIG_DUALTOUCH (1 << 0) + +struct zforce_point { + int coord_x; + int coord_y; + int state; + int id; + int area_major; + int area_minor; + int orientation; + int pressure; + int prblty; +}; + +/* + * @client the i2c_client + * @input the input device + * @suspending in the process of going to suspend (don't emit wakeup + * events for commands executed to suspend the device) + * @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 + * for a result + * @command_result returned result of the command + */ +struct zforce_ts { + struct i2c_client *client; + struct input_dev *input; + const struct zforce_ts_platdata *pdata; + char phys[32]; + + bool suspending; + bool suspended; + bool boot_complete; + + /* Firmware version information */ + u16 version_major; + u16 version_minor; + u16 version_build; + u16 version_rev; + + struct mutex access_mutex; + + struct completion command_done; + struct mutex command_mutex; + int command_waiting; + int command_result; +}; + +static int zforce_command(struct zforce_ts *ts, u8 cmd) +{ + struct i2c_client *client = ts->client; + char buf[3]; + int ret; + + dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd); + + buf[0] = FRAME_START; + buf[1] = 1; /* data size, command only */ + buf[2] = cmd; + + mutex_lock(&ts->access_mutex); + ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf)); + mutex_unlock(&ts->access_mutex); + if (ret < 0) { + dev_err(&client->dev, "i2c send data request error: %d\n", ret); + return ret; + } + + return 0; +} + +static int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len) +{ + struct i2c_client *client = ts->client; + int ret; + + ret = mutex_trylock(&ts->command_mutex); + if (!ret) { + dev_err(&client->dev, "already waiting for a command\n"); + return -EBUSY; + } + + dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n", + buf[1], buf[2]); + + ts->command_waiting = buf[2]; + + mutex_lock(&ts->access_mutex); + ret = i2c_master_send(client, buf, len); + mutex_unlock(&ts->access_mutex); + if (ret < 0) { + dev_err(&client->dev, "i2c send data request error: %d\n", ret); + goto unlock; + } + + dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]); + + if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) { + ret = -ETIME; + goto unlock; + } + + ret = ts->command_result; + +unlock: + mutex_unlock(&ts->command_mutex); + return ret; +} + +static int zforce_command_wait(struct zforce_ts *ts, u8 cmd) +{ + struct i2c_client *client = ts->client; + char buf[3]; + int ret; + + dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd); + + buf[0] = FRAME_START; + buf[1] = 1; /* data size, command only */ + buf[2] = cmd; + + ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); + if (ret < 0) { + dev_err(&client->dev, "i2c send data request error: %d\n", ret); + return ret; + } + + return 0; +} + +static int zforce_resolution(struct zforce_ts *ts, u16 x, u16 y) +{ + struct i2c_client *client = ts->client; + char buf[7] = { FRAME_START, 5, COMMAND_RESOLUTION, + (x & 0xff), ((x >> 8) & 0xff), + (y & 0xff), ((y >> 8) & 0xff) }; + + dev_dbg(&client->dev, "set resolution to (%d,%d)\n", x, y); + + return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); +} + +static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger, + u16 stylus) +{ + struct i2c_client *client = ts->client; + char buf[9] = { FRAME_START, 7, COMMAND_SCANFREQ, + (idle & 0xff), ((idle >> 8) & 0xff), + (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", + idle, finger, stylus); + + return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); +} + +static int zforce_setconfig(struct zforce_ts *ts, char b1) +{ + struct i2c_client *client = ts->client; + char buf[7] = { FRAME_START, 5, COMMAND_SETCONFIG, + b1, 0, 0, 0 }; + + dev_dbg(&client->dev, "set config to (%d)\n", b1); + + return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); +} + +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); + int ret; + + dev_dbg(&client->dev, "starting device\n"); + + ret = zforce_command_wait(ts, COMMAND_INITIALIZE); + if (ret) { + dev_err(&client->dev, "Unable to initialize, %d\n", ret); + return ret; + } + + ret = zforce_resolution(ts, pdata->x_max, pdata->y_max); + if (ret) { + dev_err(&client->dev, "Unable to set resolution, %d\n", ret); + goto error; + } + + ret = zforce_scan_frequency(ts, 10, 50, 50); + if (ret) { + dev_err(&client->dev, "Unable to set scan frequency, %d\n", + ret); + goto error; + } + + if (zforce_setconfig(ts, SETCONFIG_DUALTOUCH)) { + dev_err(&client->dev, "Unable to set config\n"); + goto error; + } + + /* start sending touch events */ + ret = zforce_command(ts, COMMAND_DATAREQUEST); + if (ret) { + dev_err(&client->dev, "Unable to request data\n"); + goto error; + } + + /* + * Per NN, initial cal. take max. of 200msec. + * Allow time to complete this calibration + */ + msleep(200); + + return 0; + +error: + zforce_command_wait(ts, COMMAND_DEACTIVATE); + return ret; +} + +static int zforce_stop(struct zforce_ts *ts) +{ + struct i2c_client *client = ts->client; + int ret; + + dev_dbg(&client->dev, "stopping device\n"); + + /* Deactivates touch sensing and puts the device into sleep. */ + ret = zforce_command_wait(ts, COMMAND_DEACTIVATE); + if (ret != 0) { + dev_err(&client->dev, "could not deactivate device, %d\n", + ret); + return ret; + } + + return 0; +} + +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); + 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", + count, ZFORCE_REPORT_POINTS); + count = ZFORCE_REPORT_POINTS; + } + + for (i = 0; i < count; i++) { + point.coord_x = + payload[9 * i + 2] << 8 | payload[9 * i + 1]; + point.coord_y = + payload[9 * i + 4] << 8 | payload[9 * i + 3]; + + if (point.coord_x > pdata->x_max || + point.coord_y > pdata->y_max) { + dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", + point.coord_x, point.coord_y); + point.coord_x = point.coord_y = 0; + } + + point.state = payload[9 * i + 5] & 0x03; + point.id = (payload[9 * i + 5] & 0xfc) >> 2; + + /* determine touch major, minor and orientation */ + point.area_major = max(payload[9 * i + 6], + payload[9 * i + 7]); + point.area_minor = min(payload[9 * i + 6], + payload[9 * i + 7]); + point.orientation = payload[9 * i + 6] > payload[9 * i + 7]; + + point.pressure = payload[9 * i + 8]; + point.prblty = payload[9 * i + 9]; + + dev_dbg(&client->dev, + "point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n", + i, count, point.state, point.id, + point.pressure, point.prblty, + point.coord_x, point.coord_y, + point.area_major, point.area_minor, + point.orientation); + + /* the zforce id starts with "1", so needs to be decreased */ + input_mt_slot(ts->input, point.id - 1); + + input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, + point.state != STATE_UP); + + if (point.state != STATE_UP) { + input_report_abs(ts->input, ABS_MT_POSITION_X, + point.coord_x); + input_report_abs(ts->input, ABS_MT_POSITION_Y, + point.coord_y); + input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, + point.area_major); + input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, + point.area_minor); + input_report_abs(ts->input, ABS_MT_ORIENTATION, + point.orientation); + num++; + } + } + + input_mt_sync_frame(ts->input); + + input_mt_report_finger_count(ts->input, num); + + input_sync(ts->input); + + return 0; +} + +static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) +{ + struct i2c_client *client = ts->client; + int ret; + + mutex_lock(&ts->access_mutex); + + /* read 2 byte message header */ + ret = i2c_master_recv(client, buf, 2); + if (ret < 0) { + dev_err(&client->dev, "error reading header: %d\n", ret); + goto unlock; + } + + if (buf[PAYLOAD_HEADER] != FRAME_START) { + dev_err(&client->dev, "invalid frame start: %d\n", buf[0]); + ret = -EIO; + goto unlock; + } + + if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) { + dev_err(&client->dev, "invalid payload length: %d\n", + buf[PAYLOAD_LENGTH]); + ret = -EIO; + goto unlock; + } + + /* read the message */ + ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]); + if (ret < 0) { + dev_err(&client->dev, "error reading payload: %d\n", ret); + goto unlock; + } + + dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n", + buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]); + +unlock: + mutex_unlock(&ts->access_mutex); + return ret; +} + +static void zforce_complete(struct zforce_ts *ts, int cmd, int result) +{ + struct i2c_client *client = ts->client; + + if (ts->command_waiting == cmd) { + dev_dbg(&client->dev, "completing command 0x%x\n", cmd); + ts->command_result = result; + complete(&ts->command_done); + } else { + dev_dbg(&client->dev, "command %d not for us\n", cmd); + } +} + +static irqreturn_t zforce_interrupt(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); + int ret; + u8 payload_buffer[512]; + u8 *payload; + + /* + * When suspended, emit a wakeup signal if necessary and return. + * Due to the level-interrupt we will get re-triggered later. + */ + if (ts->suspended) { + if (device_may_wakeup(&client->dev)) + pm_wakeup_event(&client->dev, 500); + msleep(20); + return IRQ_HANDLED; + } + + dev_dbg(&client->dev, "handling interrupt\n"); + + /* Don't emit wakeup events from commands run by zforce_suspend */ + if (!ts->suspending && device_may_wakeup(&client->dev)) + pm_stay_awake(&client->dev); + + 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); + break; + } + + payload = &payload_buffer[PAYLOAD_BODY]; + + switch (payload[RESPONSE_ID]) { + case NOTIFICATION_TOUCH: + /* + * Always report touch-events received while + * suspending, when being a wakeup source + */ + if (ts->suspending && device_may_wakeup(&client->dev)) + pm_wakeup_event(&client->dev, 500); + zforce_touch_event(ts, &payload[RESPONSE_DATA]); + break; + + case NOTIFICATION_BOOTCOMPLETE: + ts->boot_complete = payload[RESPONSE_DATA]; + zforce_complete(ts, payload[RESPONSE_ID], 0); + break; + + case RESPONSE_INITIALIZE: + case RESPONSE_DEACTIVATE: + case RESPONSE_SETCONFIG: + case RESPONSE_RESOLUTION: + case RESPONSE_SCANFREQ: + zforce_complete(ts, payload[RESPONSE_ID], + payload[RESPONSE_DATA]); + break; + + case RESPONSE_STATUS: + /* + * Version Payload Results + * [2:major] [2:minor] [2:build] [2:rev] + */ + ts->version_major = (payload[RESPONSE_DATA + 1] << 8) | + payload[RESPONSE_DATA]; + ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) | + payload[RESPONSE_DATA + 2]; + ts->version_build = (payload[RESPONSE_DATA + 5] << 8) | + 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", + ts->version_major, ts->version_minor, + ts->version_build, ts->version_rev); + + zforce_complete(ts, payload[RESPONSE_ID], 0); + break; + + case NOTIFICATION_INVALID_COMMAND: + dev_err(&ts->client->dev, "invalid command: 0x%x\n", + payload[RESPONSE_DATA]); + break; + + default: + dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n", + payload[RESPONSE_ID]); + break; + } + } + + if (!ts->suspending && device_may_wakeup(&client->dev)) + pm_relax(&client->dev); + + dev_dbg(&client->dev, "finished interrupt\n"); + + return IRQ_HANDLED; +} + +static int zforce_input_open(struct input_dev *dev) +{ + struct zforce_ts *ts = input_get_drvdata(dev); + int ret; + + ret = zforce_start(ts); + if (ret) + return ret; + + return 0; +} + +static void zforce_input_close(struct input_dev *dev) +{ + struct zforce_ts *ts = input_get_drvdata(dev); + struct i2c_client *client = ts->client; + int ret; + + ret = zforce_stop(ts); + if (ret) + dev_warn(&client->dev, "stopping zforce failed\n"); + + return; +} + +#ifdef CONFIG_PM_SLEEP +static int zforce_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct zforce_ts *ts = i2c_get_clientdata(client); + struct input_dev *input = ts->input; + int ret = 0; + + mutex_lock(&input->mutex); + ts->suspending = true; + + /* + * When configured as a wakeup source device should always wake + * the system, therefore start device if necessary. + */ + if (device_may_wakeup(&client->dev)) { + dev_dbg(&client->dev, "suspend while being a wakeup source\n"); + + /* Need to start device, if not open, to be a wakeup source. */ + if (!input->users) { + ret = zforce_start(ts); + if (ret) + goto unlock; + } + + enable_irq_wake(client->irq); + } else if (input->users) { + dev_dbg(&client->dev, "suspend without being a wakeup source\n"); + + ret = zforce_stop(ts); + if (ret) + goto unlock; + + disable_irq(client->irq); + } + + ts->suspended = true; + +unlock: + ts->suspending = false; + mutex_unlock(&input->mutex); + + return ret; +} + +static int zforce_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct zforce_ts *ts = i2c_get_clientdata(client); + struct input_dev *input = ts->input; + int ret = 0; + + mutex_lock(&input->mutex); + + ts->suspended = false; + + if (device_may_wakeup(&client->dev)) { + dev_dbg(&client->dev, "resume from being a wakeup source\n"); + + disable_irq_wake(client->irq); + + /* need to stop device if it was not open on suspend */ + if (!input->users) { + ret = zforce_stop(ts); + if (ret) + goto unlock; + } + } else if (input->users) { + dev_dbg(&client->dev, "resume without being a wakeup source\n"); + + enable_irq(client->irq); + + ret = zforce_start(ts); + if (ret < 0) + goto unlock; + } + +unlock: + mutex_unlock(&input->mutex); + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume); + +static void zforce_reset(void *data) +{ + struct zforce_ts *ts = data; + + gpio_set_value(ts->pdata->gpio_rst, 0); +} + +static int zforce_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); + struct zforce_ts *ts; + struct input_dev *input_dev; + int ret; + + if (!pdata) + return -EINVAL; + + ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + ret = devm_gpio_request_one(&client->dev, pdata->gpio_int, GPIOF_IN, + "zforce_ts_int"); + if (ret) { + dev_err(&client->dev, "request of gpio %d failed, %d\n", + pdata->gpio_int, ret); + return ret; + } + + ret = devm_gpio_request_one(&client->dev, pdata->gpio_rst, + GPIOF_OUT_INIT_LOW, "zforce_ts_rst"); + if (ret) { + dev_err(&client->dev, "request of gpio %d failed, %d\n", + pdata->gpio_rst, ret); + return ret; + } + + ret = devm_add_action(&client->dev, zforce_reset, ts); + if (ret) { + dev_err(&client->dev, "failed to register reset action, %d\n", + ret); + return ret; + } + + snprintf(ts->phys, sizeof(ts->phys), + "%s/input0", dev_name(&client->dev)); + + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) { + dev_err(&client->dev, "could not allocate input device\n"); + return -ENOMEM; + } + + mutex_init(&ts->access_mutex); + mutex_init(&ts->command_mutex); + + ts->pdata = pdata; + ts->client = client; + ts->input = input_dev; + + input_dev->name = "Neonode zForce touchscreen"; + input_dev->phys = ts->phys; + input_dev->id.bustype = BUS_I2C; + + input_dev->open = zforce_input_open; + input_dev->close = zforce_input_close; + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_SYN, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + + /* For multi touch */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + pdata->y_max, 0, 0); + + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, + ZFORCE_MAX_AREA, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, + ZFORCE_MAX_AREA, 0, 0); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT); + + input_set_drvdata(ts->input, ts); + + init_completion(&ts->command_done); + + /* + * The zforce pulls the interrupt low when it has data ready. + * After it is triggered the isr thread runs until all the available + * packets have been read and the interrupt is high again. + * Therefore we can trigger the interrupt anytime it is low and do + * not need to limit it to the interrupt edge. + */ + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + zforce_interrupt, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + input_dev->name, ts); + if (ret) { + dev_err(&client->dev, "irq %d request failed\n", client->irq); + return ret; + } + + i2c_set_clientdata(client, ts); + + /* let the controller boot */ + gpio_set_value(pdata->gpio_rst, 1); + + ts->command_waiting = NOTIFICATION_BOOTCOMPLETE; + if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) + dev_warn(&client->dev, "bootcomplete timed out\n"); + + /* need to start device to get version information */ + ret = zforce_command_wait(ts, COMMAND_INITIALIZE); + if (ret) { + dev_err(&client->dev, "unable to initialize, %d\n", ret); + return ret; + } + + /* this gets the firmware version among other informations */ + ret = zforce_command_wait(ts, COMMAND_STATUS); + if (ret < 0) { + dev_err(&client->dev, "couldn't get status, %d\n", ret); + zforce_stop(ts); + return ret; + } + + /* stop device and put it into sleep until it is opened */ + ret = zforce_stop(ts); + if (ret < 0) + return ret; + + device_set_wakeup_capable(&client->dev, true); + + ret = input_register_device(input_dev); + if (ret) { + dev_err(&client->dev, "could not register input device, %d\n", + ret); + return ret; + } + + return 0; +} + +static struct i2c_device_id zforce_idtable[] = { + { "zforce-ts", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, zforce_idtable); + +static struct i2c_driver zforce_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "zforce-ts", + .pm = &zforce_pm_ops, + }, + .probe = zforce_probe, + .id_table = zforce_idtable, +}; + +module_i2c_driver(zforce_driver); + +MODULE_AUTHOR("Heiko Stuebner "); +MODULE_DESCRIPTION("zForce TouchScreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/zforce_ts.h b/include/linux/platform_data/zforce_ts.h new file mode 100644 index 000000000000..0472ab2f6ede --- /dev/null +++ b/include/linux/platform_data/zforce_ts.h @@ -0,0 +1,26 @@ +/* drivers/input/touchscreen/zforce.c + * + * Copyright (C) 2012-2013 MundoReader S.L. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _LINUX_INPUT_ZFORCE_TS_H +#define _LINUX_INPUT_ZFORCE_TS_H + +struct zforce_ts_platdata { + int gpio_int; + int gpio_rst; + + unsigned int x_max; + unsigned int y_max; +}; + +#endif /* _LINUX_INPUT_ZFORCE_TS_H */ -- cgit v1.2.1 From a108193cf9685061660e111f985594d6a344abfb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 10 Nov 2013 23:31:17 -0800 Subject: Input: tnetv107x-keypad - make irqs signed for error handling There is a bug in keypad_probe() where we do: kp->irq_press = platform_get_irq_byname(pdev, "press"); kp->irq_release = platform_get_irq_byname(pdev, "release"); if (kp->irq_press < 0 || kp->irq_release < 0) { The problem is that these irq variables are unsigned so the error handling doesn't work. I've changed them to signed values. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tnetv107x-keypad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index 5f7b427dd7ed..8bd24d52bf1b 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -60,8 +60,8 @@ struct keypad_data { struct clk *clk; struct device *dev; spinlock_t lock; - u32 irq_press; - u32 irq_release; + int irq_press; + int irq_release; int rows, cols, row_shift; int debounce_ms, active_low; u32 prev_keys[3]; -- cgit v1.2.1 From 158baef35129e46e3eb15838092e91b94f0181e0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 10 Nov 2013 23:34:05 -0800 Subject: Input: mpu3050 - add missing i2c_set_clientdata() in mpu3050_probe() Add missing i2c_set_clientdata() in mpu3050_probe(), otherwise calling i2c_get_clientdata() in mpu3050_remove() returns NULL. Signed-off-by: Wei Yongjun Signed-off-by: Dmitry Torokhov --- drivers/input/misc/mpu3050.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index dce0d95943c5..6983ffbbfb94 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c @@ -383,6 +383,7 @@ static int mpu3050_probe(struct i2c_client *client, pm_runtime_enable(&client->dev); pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY); + i2c_set_clientdata(client, sensor); return 0; -- cgit v1.2.1 From acc84667c533eddc6c84f5986860b7d8b2b9ee0d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 10 Nov 2013 23:35:45 -0800 Subject: Input: mma8450 - add missing i2c_set_clientdata() in mma8450_probe() Add missing i2c_set_clientdata() in mma8450_probe(), otherwise calling i2c_get_clientdata() in mma8450_remove() returns NULL. Signed-off-by: Wei Yongjun Signed-off-by: Dmitry Torokhov --- drivers/input/misc/mma8450.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index f3309696d053..59d4dcddf6de 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -168,7 +168,7 @@ static void mma8450_close(struct input_polled_dev *dev) * I2C init/probing/exit functions */ static int mma8450_probe(struct i2c_client *c, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct input_polled_dev *idev; struct mma8450 *m; @@ -204,6 +204,8 @@ static int mma8450_probe(struct i2c_client *c, goto err_free_mem; } + i2c_set_clientdata(c, m); + return 0; err_free_mem: -- cgit v1.2.1 From a0137817476ce9dc8c5cfd8078862796bbb8c70c Mon Sep 17 00:00:00 2001 From: Duan Jiong Date: Sun, 10 Nov 2013 23:41:46 -0800 Subject: Input: cyttsp4 - replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO This patch fixes coccinelle error regarding usage of IS_ERR and PTR_ERR instead of PTR_ERR_OR_ZERO. Signed-off-by: Duan Jiong Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp4_spi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c index a71e1141d638..b19434cebbf6 100644 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ b/drivers/input/touchscreen/cyttsp4_spi.c @@ -171,10 +171,7 @@ static int cyttsp4_spi_probe(struct spi_device *spi) ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, CY_SPI_DATA_BUF_SIZE); - if (IS_ERR(ts)) - return PTR_ERR(ts); - - return 0; + return PTR_ERR_OR_ZERO(ts); } static int cyttsp4_spi_remove(struct spi_device *spi) -- cgit v1.2.1 From c9aeb249bf72edcf1ca28fe301fb3cbb53cb23d8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 10 Nov 2013 23:56:43 -0800 Subject: Input: ti_am335x_tsc - fix spelling mistake in TSC/ADC DT binding There was a spelling mistake on TSC/ADC binding where "coordinate" was spelled as "coordiante". We can't simply fix the error due to DT being an ABI, the approach taken was to first use correct spelling and if that fails, fall back to miss-spelled version. It's unfortunate that has creeped into the tree. Signed-off-by: Felipe Balbi Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/touchscreen/ti-tsc-adc.txt | 2 +- arch/arm/boot/dts/am335x-evm.dts | 2 +- drivers/input/touchscreen/ti_am335x_tsc.c | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt index 491c97b78384..878549ba814d 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt @@ -6,7 +6,7 @@ Required properties: ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen support on the platform. ti,x-plate-resistance: X plate resistance - ti,coordiante-readouts: The sequencer supports a total of 16 + ti,coordinate-readouts: The sequencer supports a total of 16 programmable steps each step is used to read a single coordinate. A single readout is enough but multiple reads can diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index e8ec8756e498..c5b73bcd3686 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -509,7 +509,7 @@ tsc { ti,wires = <4>; ti,x-plate-resistance = <200>; - ti,coordiante-readouts = <5>; + ti,coordinate-readouts = <5>; ti,wire-config = <0x00 0x11 0x22 0x33>; }; diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index df9b24f7e2cb..ad7564296ddf 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -348,8 +348,15 @@ static int titsc_parse_dt(struct platform_device *pdev, if (err < 0) return err; - err = of_property_read_u32(node, "ti,coordiante-readouts", + /* + * Try with the new binding first. If it fails, try again with + * bogus, miss-spelled version. + */ + err = of_property_read_u32(node, "ti,coordinate-readouts", &ts_dev->coordinate_readouts); + if (err < 0) + err = of_property_read_u32(node, "ti,coordiante-readouts", + &ts_dev->coordinate_readouts); if (err < 0) return err; -- cgit v1.2.1 From 2c027b7c48a888ab173ba45babb4525e278375d9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 10 Nov 2013 23:58:31 -0800 Subject: arm: dts: am335x sk: add touchscreen support Add missing nodes for the touchscreen available on AM335x EVM SK. Signed-off-by: Felipe Balbi Signed-off-by: Dmitry Torokhov --- arch/arm/boot/dts/am335x-evmsk.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index 4f339fa91c57..d7c2c0c58437 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -419,3 +419,13 @@ phy_id = <&davinci_mdio>, <1>; phy-mode = "rgmii-txid"; }; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; +}; -- cgit v1.2.1 From 936816161978ca716a56c5e553c68f25972b1e3a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 14 Nov 2013 17:36:42 -0800 Subject: Revert "Input: ALPS - add support for model found on Dell XT2" This reverts commit 5beea882e64121dfe3b33145767d3302afa784d5 as it breaks trackpoint operation on XT2. --- drivers/input/mouse/alps.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 83658472ad25..7c5d72a6a26a 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -103,7 +103,6 @@ static const struct alps_model_info alps_model_data[] = { /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, - { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_DUALPOINT }, /* Dell XT2 */ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -- cgit v1.2.1