linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Liyitec PS/2 touch panel driver [PATCH]
@ 2006-01-31 22:59 Shaun Jackman
  2006-02-01  0:22 ` Alexey Dobriyan
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Shaun Jackman @ 2006-01-31 22:59 UTC (permalink / raw)
  To: lkml

I've written an input driver for the Liyitec PS/2 touch panel. The
patch follows. As this is my first input driver, I'd appreciate any
feedback.

Please cc me in your reply. Cheers,
Shaun

2006-01-31  Shaun Jackman  <sjackman@gmail.com>

	* drivers/input/touchscreen/Kconfig (TOUCHSCREEN_LIYITEC): New item.
	* drivers/input/touchscreen/Makefile: Add liyitec driver.
	* drivers/input/touchscreen/liyitec.c: New file.
	* include/linux/serio.h (SERIO_LIYITEC): New constant.

--- linux-2.6.15.orig/drivers/input/touchscreen/Kconfig	2006-01-02
20:21:10.000000000 -0700
+++ linux-2.6.15/drivers/input/touchscreen/Kconfig	2006-01-31
15:56:36.000000000 -0700
@@ -60,6 +60,19 @@
 	  To compile this driver as a module, choose M here: the
  	  module will be called elo.

+config TOUCHSCREEN_LIYITEC
+	tristate "Lyitec PS/2 touchscreen"
+	select SERIO
+	select SERIO_I8042 if X86_PC
+	help
+	  Say Y here if you have a Liyitec PS/2 touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called liyitec.
+
  config TOUCHSCREEN_MTOUCH
  	tristate "MicroTouch serial touchscreens"
  	select SERIO
--- linux-2.6.15.orig/drivers/input/touchscreen/Makefile	2006-01-02
20:21:10.000000000 -0700
+++ linux-2.6.15/drivers/input/touchscreen/Makefile	2006-01-27
16:01:39.000000000 -0700
@@ -8,6 +8,7 @@
 obj-$(CONFIG_TOUCHSCREEN_CORGI)	+= corgi_ts.o
  obj-$(CONFIG_TOUCHSCREEN_GUNZE)	+= gunze.o
  obj-$(CONFIG_TOUCHSCREEN_ELO)	+= elo.o
+obj-$(CONFIG_TOUCHSCREEN_LIYITEC) += liyitec.o
  obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)	+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)	+= hp680_ts_input.o
--- linux-2.6.15.orig/drivers/input/touchscreen/liyitec.c	1969-12-31
17:00:00.000000000 -0700
+++ linux-2.6.15/drivers/input/touchscreen/liyitec.c	2006-01-31
15:06:49.000000000 -0700
@@ -0,0 +1,188 @@
+/* Liyitec PS/2 touch panel driver
+ * Written by Shaun Jackman <sjackman@gmail.com>.
+ * Copyright 2006 Pathway Connectivity
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This driver was derived from mtouch.c.
+ */
+
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+
+#define DRIVER_DESC "Liyitec PS/2 touch panel driver"
+
+MODULE_AUTHOR("Shaun Jackman <sjackman@gmail.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define LIYITEC_MAX_X 0x3ff
+#define LIYITEC_MAX_Y 0x3ff
+
+#define LIYITEC_Y9    0x80
+#define LIYITEC_X9    0x40
+#define LIYITEC_Y8    0x20
+#define LIYITEC_X8    0x10
+#define LIYITEC_SYNC  0x08
+#define LIYITEC_ABS   0x04
+#define LIYITEC_RIGHT 0x02
+#define LIYITEC_TOUCH 0x01
+
+#define LIYITEC_PACKET_SIZE 3
+#define LIYITEC_CMD_ENABLE    0xf4
+#define LIYITEC_CMD_SETSTREAM 0xea
+#define LIYITEC_RET_ACK       0xfa
+
+struct liyitec {
+	struct input_dev *dev;
+	struct serio *serio;
+	char phys[32];
+	signed char count;
+	unsigned char data[LIYITEC_PACKET_SIZE];
+};
+
+static irqreturn_t liyitec_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct liyitec *liyitec = serio_get_drvdata(serio);
+
+	if (liyitec->count < 0) {
+		if (data != LIYITEC_RET_ACK)
+			printk(KERN_DEBUG "liyitec: expected ACK: 0x%02x\n", data);
+	} else
+		liyitec->data[liyitec->count] = data;
+	liyitec->count++;
+
+	if (liyitec->count == 1 && !(data & LIYITEC_SYNC)) {
+		printk(KERN_DEBUG "liyitec: unsynchronized data: 0x%02x\n", data);
+		liyitec->count = 0;
+	}
+	else if (liyitec->count == LIYITEC_PACKET_SIZE) {
+		struct input_dev *dev = liyitec->dev;
+		input_regs(dev, regs);
+		if (liyitec->data[0] & LIYITEC_ABS) {
+			unsigned x = liyitec->data[1] +
+				(liyitec->data[0] & LIYITEC_X8 ? 0x100 : 0) +
+				(liyitec->data[0] & LIYITEC_X9 ? 0x200 : 0);
+			unsigned y = liyitec->data[2] +
+				(liyitec->data[0] & LIYITEC_Y8 ? 0x100 : 0) +
+				(liyitec->data[0] & LIYITEC_Y9 ? 0x200 : 0);
+			input_report_abs(dev, ABS_X, x);
+			input_report_abs(dev, ABS_Y, y);
+			printk(KERN_DEBUG "liyitec: (%d,%d)\n", x, y); //xxx
+		}
+		input_report_key(dev, BTN_TOUCH, liyitec->data[0] & LIYITEC_TOUCH);
+		input_report_key(dev, BTN_RIGHT, liyitec->data[0] & LIYITEC_RIGHT);
+		printk(KERN_DEBUG "liyitec: %02x\n", liyitec->data[0]); //xxx
+		input_sync(dev);
+		liyitec->count = 0;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int liyitec_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct liyitec *liyitec;
+	struct input_dev *input_dev;
+	int retval;
+
+	liyitec = kzalloc(sizeof *liyitec, GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (liyitec == NULL || input_dev == NULL) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	liyitec->serio = serio;
+	liyitec->dev = input_dev;
+	sprintf(liyitec->phys, "%s/input0", serio->phys);
+
+	input_dev->private = liyitec;
+	input_dev->name = "Liyitec PS/2 touch screen";
+	input_dev->phys = liyitec->phys;
+	input_dev->id.bustype = BUS_I8042;
+	input_dev->id.vendor = SERIO_LIYITEC;
+	input_dev->id.product = 0;
+	input_dev->id.version = 0x0100;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_RIGHT);
+	input_set_abs_params(liyitec->dev, ABS_X, 0, LIYITEC_MAX_X, 0, 0);
+	input_set_abs_params(liyitec->dev, ABS_Y, 0, LIYITEC_MAX_Y, 0, 0);
+
+	serio_set_drvdata(serio, liyitec);
+	retval = serio_open(serio, drv);
+	if (retval)
+		goto out;
+	input_register_device(liyitec->dev);
+
+	liyitec->count = -2;
+	retval = serio_write(serio, LIYITEC_CMD_SETSTREAM);
+	if (retval)
+		goto out;
+	retval = serio_write(serio, LIYITEC_CMD_ENABLE);
+
+out:
+	if (retval) {
+		serio_set_drvdata(serio, NULL);
+		input_free_device(input_dev);
+		kfree(liyitec);
+	}
+	return retval;
+}
+
+static void liyitec_disconnect(struct serio *serio)
+{
+	struct liyitec *liyitec = serio_get_drvdata(serio);
+
+	input_get_device(liyitec->dev);
+	input_unregister_device(liyitec->dev);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	input_put_device(liyitec->dev);
+	kfree(liyitec);
+}
+
+static struct serio_device_id liyitec_serio_ids[] = {
+	{
+		.type  = SERIO_8042,
+		.proto = SERIO_ANY,
+		.id    = SERIO_ANY,
+		.extra = SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, liyitec_serio_ids);
+
+static struct serio_driver liyitec_drv = {
+	.driver = {
+		.name = "liyitec",
+	},
+	.description = DRIVER_DESC,
+	.id_table    = liyitec_serio_ids,
+	.interrupt   = liyitec_interrupt,
+	.connect     = liyitec_connect,
+	.disconnect  = liyitec_disconnect,
+};
+
+static int __init liyitec_init(void)
+{
+	printk(KERN_INFO "liyitec: %s\n", DRIVER_DESC);
+	serio_register_driver(&liyitec_drv);
+	return 0;
+}
+
+static void __exit liyitec_exit(void)
+{
+	printk(KERN_INFO "liyitec: %s\n", __func__);
+	serio_unregister_driver(&liyitec_drv);
+}
+
+module_init(liyitec_init);
+module_exit(liyitec_exit);
--- linux-2.6.15.orig/include/linux/serio.h	2006-01-02 20:21:10.000000000 -0700
+++ linux-2.6.15/include/linux/serio.h	2006-01-27 16:57:57.000000000 -0700
@@ -216,5 +216,6 @@
 #define SERIO_LKKBD	0x28
 #define SERIO_ELO	0x29
 #define SERIO_MICROTOUCH	0x30
+#define SERIO_LIYITEC	0x31

  #endif

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-01-31 22:59 Liyitec PS/2 touch panel driver [PATCH] Shaun Jackman
@ 2006-02-01  0:22 ` Alexey Dobriyan
  2006-02-02  0:50   ` Shaun Jackman
  2006-02-01  1:03 ` Jiri Slaby
  2006-02-01  4:20 ` Dmitry Torokhov
  2 siblings, 1 reply; 8+ messages in thread
From: Alexey Dobriyan @ 2006-02-01  0:22 UTC (permalink / raw)
  To: Shaun Jackman; +Cc: linux-kernel

On Tue, Jan 31, 2006 at 03:59:20PM -0700, Shaun Jackman wrote:
> I've written an input driver for the Liyitec PS/2 touch panel. The
> patch follows. As this is my first input driver, I'd appreciate any
> feedback.

> 2006-01-31  Shaun Jackman  <sjackman@gmail.com>
>
> 	* drivers/input/touchscreen/Kconfig (TOUCHSCREEN_LIYITEC): New item.
> 	* drivers/input/touchscreen/Makefile: Add liyitec driver.
> 	* drivers/input/touchscreen/liyitec.c: New file.
> 	* include/linux/serio.h (SERIO_LIYITEC): New constant.

This is not ChangeLog style Linux is using.

> +static void liyitec_disconnect(struct serio *serio)
> +{
> +	struct liyitec *liyitec = serio_get_drvdata(serio);
> +
> +	input_get_device(liyitec->dev);

What do you want to do with return value?

> +	input_unregister_device(liyitec->dev);
> +	serio_close(serio);
> +	serio_set_drvdata(serio, NULL);
> +	input_put_device(liyitec->dev);
> +	kfree(liyitec);
> +}

> +static void __exit liyitec_exit(void)
> +{
> +	printk(KERN_INFO "liyitec: %s\n", __func__);

I suggest to drop this line.

> +	serio_unregister_driver(&liyitec_drv);
> +}


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-01-31 22:59 Liyitec PS/2 touch panel driver [PATCH] Shaun Jackman
  2006-02-01  0:22 ` Alexey Dobriyan
@ 2006-02-01  1:03 ` Jiri Slaby
  2006-02-02  0:52   ` Shaun Jackman
  2006-02-01  4:20 ` Dmitry Torokhov
  2 siblings, 1 reply; 8+ messages in thread
From: Jiri Slaby @ 2006-02-01  1:03 UTC (permalink / raw)
  To: Shaun Jackman; +Cc: lkml

>Shaun Jackman wrote:
>I've written an input driver for the Liyitec PS/2 touch panel. The
>patch follows. As this is my first input driver, I'd appreciate any
>feedback.
>
>Please cc me in your reply. Cheers,
>Shaun
[snip]
>+static irqreturn_t liyitec_interrupt(struct serio *serio,
>+		unsigned char data, unsigned int flags, struct pt_regs *regs)
>+{
>+	struct liyitec *liyitec = serio_get_drvdata(serio);
>+
>+	if (liyitec->count < 0) {
>+		if (data != LIYITEC_RET_ACK)
>+			printk(KERN_DEBUG "liyitec: expected ACK: 0x%02x\n", data);
>+	} else
>+		liyitec->data[liyitec->count] = data;
>+	liyitec->count++;
>+
>+	if (liyitec->count == 1 && !(data & LIYITEC_SYNC)) {
>+		printk(KERN_DEBUG "liyitec: unsynchronized data: 0x%02x\n", data);
It would be great to use dev_*() rather than printks.
dev_dbg(&serio->dev, "unsynchronized data: 0x%02x\n", data);
for instance.

regards,
--
Jiri Slaby         www.fi.muni.cz/~xslaby
~\-/~      jirislaby@gmail.com      ~\-/~
B67499670407CE62ACC8 22A032CC55C339D47A7E

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-01-31 22:59 Liyitec PS/2 touch panel driver [PATCH] Shaun Jackman
  2006-02-01  0:22 ` Alexey Dobriyan
  2006-02-01  1:03 ` Jiri Slaby
@ 2006-02-01  4:20 ` Dmitry Torokhov
  2006-02-02  1:00   ` Shaun Jackman
  2006-02-02 23:11   ` Shaun Jackman
  2 siblings, 2 replies; 8+ messages in thread
From: Dmitry Torokhov @ 2006-02-01  4:20 UTC (permalink / raw)
  To: Shaun Jackman; +Cc: lkml

On Tuesday 31 January 2006 17:59, Shaun Jackman wrote:
> +
> +static int liyitec_connect(struct serio *serio, struct serio_driver *drv)
> +{
> +	struct liyitec *liyitec;
> +	struct input_dev *input_dev;
> +	int retval;
> +
> +	liyitec = kzalloc(sizeof *liyitec, GFP_KERNEL);
> +	input_dev = input_allocate_device();
> +	if (liyitec == NULL || input_dev == NULL) {
> +		retval = -ENOMEM;
> +		goto out;
> +	}
> +
> +	liyitec->serio = serio;
> +	liyitec->dev = input_dev;
> +	sprintf(liyitec->phys, "%s/input0", serio->phys);
> +
> +	input_dev->private = liyitec;
> +	input_dev->name = "Liyitec PS/2 touch screen";
> +	input_dev->phys = liyitec->phys;
> +	input_dev->id.bustype = BUS_I8042;
> +	input_dev->id.vendor = SERIO_LIYITEC;
> +	input_dev->id.product = 0;
> +	input_dev->id.version = 0x0100;
> +	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
> +	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
> +	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_RIGHT);
> +	input_set_abs_params(liyitec->dev, ABS_X, 0, LIYITEC_MAX_X, 0, 0);
> +	input_set_abs_params(liyitec->dev, ABS_Y, 0, LIYITEC_MAX_Y, 0, 0);
> +
> +	serio_set_drvdata(serio, liyitec);
> +	retval = serio_open(serio, drv);
> +	if (retval)
> +		goto out;
> +	input_register_device(liyitec->dev);
> +
> +	liyitec->count = -2;
> +	retval = serio_write(serio, LIYITEC_CMD_SETSTREAM);
> +	if (retval)
> +		goto out;
> +	retval = serio_write(serio, LIYITEC_CMD_ENABLE);
> +

Hi Shaun,

Thank you for adding support for the new touchscreen, however I have a
couple of questions:

What stops this driver form binding to serio ports that have devices other
that Liyitec touchscreen connected to them? Such as keyboard port when
keyboard works in non-translated mode or regular AUX port with standard
PS/2 mouse? Is there a way to query for presence of the touchscreen?

Moreover this driver should be integrated into psmouse so proper protocol
is selected automatically.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-02-01  0:22 ` Alexey Dobriyan
@ 2006-02-02  0:50   ` Shaun Jackman
  0 siblings, 0 replies; 8+ messages in thread
From: Shaun Jackman @ 2006-02-02  0:50 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: linux-kernel

On 1/31/06, Alexey Dobriyan <adobriyan@gmail.com> wrote:
> > +static void liyitec_disconnect(struct serio *serio)
> > +{
> > +     struct liyitec *liyitec = serio_get_drvdata(serio);
> > +
> > +     input_get_device(liyitec->dev);
>
> What do you want to do with return value?

As far as I know, input_get_device returns its argument. So, I don't
want anything with the return value. input_get_device does increment
the reference count of the underlying kobject though. Am I correct
here?

> > +static void __exit liyitec_exit(void)
> > +{
> > +     printk(KERN_INFO "liyitec: %s\n", __func__);
>
> I suggest to drop this line.

Right. Will do.

Please cc me in your reply. Cheers,
Shaun

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-02-01  1:03 ` Jiri Slaby
@ 2006-02-02  0:52   ` Shaun Jackman
  0 siblings, 0 replies; 8+ messages in thread
From: Shaun Jackman @ 2006-02-02  0:52 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: lkml

On 1/31/06, Jiri Slaby <xslaby@fi.muni.cz> wrote:
> It would be great to use dev_*() rather than printks.
> dev_dbg(&serio->dev, "unsynchronized data: 0x%02x\n", data);
> for instance.

Thanks, Jiri. Will do.

Cheers,
Shaun

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-02-01  4:20 ` Dmitry Torokhov
@ 2006-02-02  1:00   ` Shaun Jackman
  2006-02-02 23:11   ` Shaun Jackman
  1 sibling, 0 replies; 8+ messages in thread
From: Shaun Jackman @ 2006-02-02  1:00 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: lkml

On 1/31/06, Dmitry Torokhov <dtor_core@ameritech.net> wrote:
> Hi Shaun,
>
> Thank you for adding support for the new touchscreen, however I have a
> couple of questions:
>
> What stops this driver form binding to serio ports that have devices other
> that Liyitec touchscreen connected to them? Such as keyboard port when
> keyboard works in non-translated mode or regular AUX port with standard
> PS/2 mouse?

Nothing is preventing it from seizing other PS/2 ports, as far as I
know. I believe it's working for me right now because the keyboard
grabs the keyboard PS/2 port first, and then the liyitec driver grabs
the rest of the ports, which, in my case, is only the psaux port which
is connected to the liyitec screen.

> Is there a way to query for presence of the touchscreen?

I'm not sure. I'll find out what the touchscreen's response to the
PS/2 GETID command is.

> Moreover this driver should be integrated into psmouse so proper protocol
> is selected automatically.

In a private mail to me, Vojtech Pavlik pointed out that lifebook.c is
a PS/2 touch screen that does exactly this, and in only 136 lines of
code. I'll see if I can adapt my existing serio driver to be a psmouse
driver.

Thanks for your comments, Dmitry. Cheers,
Shaun

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Liyitec PS/2 touch panel driver [PATCH]
  2006-02-01  4:20 ` Dmitry Torokhov
  2006-02-02  1:00   ` Shaun Jackman
@ 2006-02-02 23:11   ` Shaun Jackman
  1 sibling, 0 replies; 8+ messages in thread
From: Shaun Jackman @ 2006-02-02 23:11 UTC (permalink / raw)
  To: lkml

On 1/31/06, Dmitry Torokhov <dtor_core@ameritech.net> wrote:
> What stops this driver form binding to serio ports that have devices other
> that Liyitec touchscreen connected to them? Such as keyboard port when
> keyboard works in non-translated mode or regular AUX port with standard
> PS/2 mouse? Is there a way to query for presence of the touchscreen?
>
> Moreover this driver should be integrated into psmouse so proper protocol
> is selected automatically.

I've just posted an updated version of my Liyitec driver that
incorporates the trivial changes suggested by others on this list.
This driver is quite useful in its current state, as it does allow a
Liyitec touch screen to be used, which currently has no support at
all. It does however have a few outstanding issues.

1. The Liyitec driver will grab all unclaimed PS/2 devices.
2. It does this because there is no probing and identification code.
3. This driver would probably be better off as a psmouse driver rather
than a serio driver, but this would first require the missing probe
code.

It should certainly be possible to detect the presence of a Liyitec
touch screen, but I haven't figured out how yet. Trivially, the
Liyitec touch screen appears to be a PS/2 mouse that happens to be
returning very unusual coordinates.

Cheers,
Shaun

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2006-02-02 23:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-31 22:59 Liyitec PS/2 touch panel driver [PATCH] Shaun Jackman
2006-02-01  0:22 ` Alexey Dobriyan
2006-02-02  0:50   ` Shaun Jackman
2006-02-01  1:03 ` Jiri Slaby
2006-02-02  0:52   ` Shaun Jackman
2006-02-01  4:20 ` Dmitry Torokhov
2006-02-02  1:00   ` Shaun Jackman
2006-02-02 23:11   ` Shaun Jackman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).