From: Dmitry Torokhov <dtor_core@ameritech.net>
To: "Shaun Jackman" <sjackman@gmail.com>
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] elo: Support non-pressure-sensitive ELO touchscreens
Date: Fri, 21 Jul 2006 02:10:37 -0400 [thread overview]
Message-ID: <200607210210.37923.dtor_core@ameritech.net> (raw)
In-Reply-To: <7f45d9390607191434g6261b6f8pf1c9a9688770d95f@mail.gmail.com>
On Wednesday 19 July 2006 17:34, Shaun Jackman wrote:
> On 3/28/06, Shaun Jackman <sjackman@gmail.com> wrote:
> > On 3/27/06, Dmitry Torokhov <dtor_core@ameritech.net> wrote:
> > ...
> > > No, we should not change basic input device's capabilities "on-fly" -
> > > userspace should be able to rely on what was reported to it in the first
> > > place.
> >
> > Makes sense.
> >
> > > From looking over the documentation (thank you for the link)
> > > it looks like you would need to issue 'i' command to query controller
> > > type and whether the controller supports Z-axis in elo_connect().
> >
> > This sounds like extra (not strictly necessary) functionality to me
> > though. My USB mouse, for example, reports five buttons and three
> > wheels, even though it only has three buttons and one wheel. Support
> > for the 'i' packet could be added later, if someone has a need. Can
> > this patch be applied as is?
>
> Can this patch adding support for non-pressure-sensitive ELO
> touchscreens be applied? Any comments?
>
Shaun,
I still think that we need to query the touchscreen andd act based on
its reported features. Could you please tell me if the patch below works?
Thanks!
--
Dmitry
Subject: elo - add support for non-pressure-sensitive touchscreens
From: Shaun Jackman <sjackman@gmail.com>
Input: elo - add support for non-pressure-sensitive touchscreens
- Use the touch status bit rather than the pressure bits to
distinguish a BTN_TOUCH event. Non-pressure-sensitive touchscreens
always report full pressure
- Report ABS_PRESSURE information only if the touchscreen supports it
- Implement checksum calculation correctly, and verify that the
transmitted checksum is correct
- Handle input_register_device() failures
- Use dev_dbg to log errors in the protocol
Signed-off-by: Shaun Jackman <sjackman@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/touchscreen/elo.c | 166 ++++++++++++++++++++++++++++++++--------
1 files changed, 134 insertions(+), 32 deletions(-)
Index: work/drivers/input/touchscreen/elo.c
===================================================================
--- work.orig/drivers/input/touchscreen/elo.c
+++ work/drivers/input/touchscreen/elo.c
@@ -23,6 +23,7 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
+#include <linux/ctype.h>
#define DRIVER_DESC "Elo serial touchscreen driver"
@@ -34,7 +35,19 @@ MODULE_LICENSE("GPL");
* Definitions & global arrays.
*/
-#define ELO_MAX_LENGTH 10
+#define ELO_MAX_LENGTH 10
+
+#define ELO10_PACKET_LEN 8
+#define ELO10_TOUCH 0x03
+#define ELO10_PRESSURE 0x80
+
+#define ELO10_LEAD_BYTE 'U'
+
+#define ELO10_ID_CMD 'i'
+
+#define ELO10_TOUCH_PACKET 'T'
+#define ELO10_ACK_PACKET 'A'
+#define ELI10_ID_PACKET 'I'
/*
* Per-touchscreen data.
@@ -43,51 +56,69 @@ MODULE_LICENSE("GPL");
struct elo {
struct input_dev *dev;
struct serio *serio;
+ struct mutex cmd_mutex;
+ struct completion cmd_done;
int id;
int idx;
+ unsigned char expected_packet;
unsigned char csum;
unsigned char data[ELO_MAX_LENGTH];
+ unsigned char response[ELO10_PACKET_LEN];
char phys[32];
};
-static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs)
{
struct input_dev *dev = elo->dev;
+ struct device *dbg = &elo->serio->dev;
- elo->csum += elo->data[elo->idx] = data;
-
+ elo->data[elo->idx] = data;
switch (elo->idx++) {
-
case 0:
- if (data != 'U') {
+ elo->csum = 0xaa;
+ if (data != ELO10_LEAD_BYTE) {
+ dev_dbg(dbg, "unsynchronized data: 0x%02x\n", data);
elo->idx = 0;
- elo->csum = 0;
}
break;
+ case 9:
+ elo->idx = 0;
+ if (elo->csum != elo->data[9]) {
+ dev_dbg(dbg, "bad checksum: 0x%02x, expected 0x%02x\n",
+ elo->data[9], elo->csum);
+ break;
+ }
- case 1:
- if (data != 'T') {
- elo->idx = 0;
- elo->csum = 0;
+ if (elo->data[1] != elo->expected_packet) {
+ if (elo->data[1] != ELO10_TOUCH_PACKET)
+ dev_dbg(dbg, "unexpected packet: 0x%02x\n",
+ elo->data[1]);
+ break;
}
- break;
- case 9:
- if (elo->csum) {
+ if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) {
input_regs(dev, regs);
input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
- input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
- input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]);
+ if (elo->data[2] & ELO10_PRESSURE)
+ input_report_abs(dev, ABS_PRESSURE,
+ (elo->data[8] << 8) | elo->data[7]);
+ input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH);
input_sync(dev);
+ } else if (elo->data[1] == ELO10_ACK_PACKET) {
+ if (elo->data[2] == '0')
+ elo->expected_packet = ELO10_TOUCH_PACKET;
+ complete(&elo->cmd_done);
+ } else {
+ memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN);
+ elo->expected_packet = ELO10_ACK_PACKET;
}
- elo->idx = 0;
- elo->csum = 0;
break;
}
+ elo->csum += data;
}
-static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs)
{
struct input_dev *dev = elo->dev;
@@ -135,7 +166,7 @@ static void elo_process_data_6(struct el
}
}
-static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
+static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs)
{
struct input_dev *dev = elo->dev;
@@ -181,17 +212,81 @@ static irqreturn_t elo_interrupt(struct
return IRQ_HANDLED;
}
+static int elo_command_10(struct elo *elo, unsigned char *packet)
+{
+ int rc = -1;
+ int i;
+ unsigned char csum = 0xaa + ELO10_LEAD_BYTE;
+
+ mutex_lock(&elo->cmd_mutex);
+
+ serio_pause_rx(elo->serio);
+ elo->expected_packet = toupper(packet[0]);
+ init_completion(&elo->cmd_done);
+ serio_continue_rx(elo->serio);
+
+ if (serio_write(elo->serio, ELO10_LEAD_BYTE))
+ goto out;
+
+ for (i = 0; i < ELO10_PACKET_LEN; i++) {
+ csum += packet[i];
+ if (serio_write(elo->serio, packet[i]))
+ goto out;
+ }
+
+ if (serio_write(elo->serio, csum))
+ goto out;
+
+ wait_for_completion_timeout(&elo->cmd_done, HZ);
+
+ if (elo->expected_packet == ELO10_TOUCH_PACKET) {
+ /* We are back in reportinG mode, the command was ACKed */
+ memcpy(packet, elo->response, ELO10_PACKET_LEN);
+ rc = 0;
+ }
+
+ out:
+ mutex_unlock(&elo->cmd_mutex);
+ return rc;
+}
+
+static int elo_setup_10(struct elo *elo)
+{
+ static const char *elo_types[] = { "Accu", "Dura", "Intelli", "Carroll" };
+ struct input_dev *dev = elo->dev;
+ unsigned char packet[ELO10_PACKET_LEN] = { ELO10_ID_CMD };
+
+ if (elo_command_10(elo, packet))
+ return -1;
+
+ dev->id.version = (packet[5] << 8) | packet[4];
+
+ input_set_abs_params(dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(dev, ABS_Y, 96, 4000, 0, 0);
+ if (packet[3] & ELO10_PRESSURE)
+ input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
+
+ printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, "
+ "features: %x02x, controller: 0x%02x\n",
+ elo_types[(packet[1] -'0') & 0x03],
+ packet[5], packet[4], packet[3], packet[7]);
+
+ return 0;
+}
+
/*
* elo_disconnect() is the opposite of elo_connect()
*/
static void elo_disconnect(struct serio *serio)
{
- struct elo* elo = serio_get_drvdata(serio);
+ struct elo *elo = serio_get_drvdata(serio);
+ input_get_device(elo->dev);
input_unregister_device(elo->dev);
serio_close(serio);
serio_set_drvdata(serio, NULL);
+ input_put_device(elo->dev);
kfree(elo);
}
@@ -211,12 +306,15 @@ static int elo_connect(struct serio *ser
input_dev = input_allocate_device();
if (!elo || !input_dev) {
err = -ENOMEM;
- goto fail;
+ goto fail1;
}
elo->serio = serio;
elo->id = serio->id.id;
elo->dev = input_dev;
+ elo->expected_packet = ELO10_TOUCH_PACKET;
+ mutex_init(&elo->cmd_mutex);
+ init_completion(&elo->cmd_done);
snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
input_dev->private = elo;
@@ -231,12 +329,17 @@ static int elo_connect(struct serio *ser
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ serio_set_drvdata(serio, elo);
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail2;
+
switch (elo->id) {
case 0: /* 10-byte protocol */
- input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
+ if (elo_setup_10(elo))
+ goto fail3;
+
break;
case 1: /* 6-byte protocol */
@@ -247,23 +350,22 @@ static int elo_connect(struct serio *ser
input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
break;
+
case 3: /* 3-byte protocol */
input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
break;
}
- serio_set_drvdata(serio, elo);
-
- err = serio_open(serio, drv);
+ err = input_register_device(elo->dev);
if (err)
- goto fail;
+ goto fail3;
- input_register_device(elo->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(elo);
return err;
}
next prev parent reply other threads:[~2006-07-21 6:10 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <7f45d9390602241045p45aec8auaf881a4dab00c17a@mail.gmail.com>
[not found] ` <7f45d9390603151047t7f18b3afn4fcf899ff8368aa3@mail.gmail.com>
2006-03-27 16:28 ` [PATCH] elo: Support non-pressure-sensitive ELO touchscreens Dmitry Torokhov
[not found] ` <7f45d9390603271515m17a5ee1due5bc3f9f2285ca62@mail.gmail.com>
2006-03-28 6:10 ` Dmitry Torokhov
[not found] ` <7f45d9390603280709u5eea134ejb0aaacdd49984a92@mail.gmail.com>
2006-07-19 21:34 ` Shaun Jackman
2006-07-21 6:10 ` Dmitry Torokhov [this message]
2006-07-21 20:25 ` Shaun Jackman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200607210210.37923.dtor_core@ameritech.net \
--to=dtor_core@ameritech.net \
--cc=linux-kernel@vger.kernel.org \
--cc=sjackman@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.