diff options
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/touchwin.c | 203 | ||||
| -rw-r--r-- | include/linux/serio.h | 1 | 
4 files changed, 217 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 216db122937..9418bbe4707 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -132,4 +132,16 @@ config TOUCHSCREEN_TOUCHRIGHT  	  To compile this driver as a module, choose M here: the  	  module will be called touchright. +config TOUCHSCREEN_TOUCHWIN +	tristate "Touchwin serial touchscreen" +	select SERIO +	help +	  Say Y here if you have a Touchwin serial touchscreen connected to +	  your system. + +	  If unsure, say N. + +	  To compile this driver as a module, choose M here: the +	  module will be called touchwin. +  endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index deda25e3680..1abb8f10d60 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_TOUCHSCREEN_MK712)	+= mk712.o  obj-$(CONFIG_TOUCHSCREEN_HP600)	+= hp680_ts_input.o  obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o  obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o +obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c new file mode 100644 index 00000000000..a7b4c755958 --- /dev/null +++ b/drivers/input/touchscreen/touchwin.c @@ -0,0 +1,203 @@ +/* + * Touchwindow serial touchscreen driver + * + * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> + * + * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c) + * Copyright (c) 2004 Vojtech Pavlik + * and Dan Streetman <ddstreet@ieee.org> + */ + +/* + * 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. + */ + +/* + * 2005/02/19 Rick Koch: + *   The Touchwindow I used is made by Edmark Corp. and + *   constantly outputs a stream of 0's unless it is touched. + *   It then outputs 3 bytes: X, Y, and a copy of Y. + */ + +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/serio.h> +#include <linux/init.h> + +#define DRIVER_DESC	"Touchwindow serial touchscreen driver" + +MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* + * Definitions & global arrays. + */ + +#define TW_LENGTH 3 + +#define TW_MIN_XC 0 +#define TW_MAX_XC 0xff +#define TW_MIN_YC 0 +#define TW_MAX_YC 0xff + +/* + * Per-touchscreen data. + */ + +struct tw { +	struct input_dev *dev; +	struct serio *serio; +	int idx; +	int touched; +	unsigned char data[TW_LENGTH]; +	char phys[32]; +}; + +static irqreturn_t tw_interrupt(struct serio *serio, +		unsigned char data, unsigned int flags, struct pt_regs *regs) +{ +	struct tw *tw = serio_get_drvdata(serio); +	struct input_dev *dev = tw->dev; + +	if (data) {		/* touch */ +		tw->touched = 1; +		tw->data[tw->idx++] = data; +		/* verify length and that the two Y's are the same */ +		if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) { +			input_regs(dev, regs); +			input_report_abs(dev, ABS_X, tw->data[0]); +			input_report_abs(dev, ABS_Y, tw->data[1]); +			input_report_key(dev, BTN_TOUCH, 1); +			input_sync(dev); +			tw->idx = 0; +		} +	} else if (tw->touched) {	/* untouch */ +		input_report_key(dev, BTN_TOUCH, 0); +		input_sync(dev); +		tw->idx = 0; +		tw->touched = 0; +	} + +	return IRQ_HANDLED; +} + +/* + * tw_disconnect() is the opposite of tw_connect() + */ + +static void tw_disconnect(struct serio *serio) +{ +	struct tw *tw = serio_get_drvdata(serio); + +	input_get_device(tw->dev); +	input_unregister_device(tw->dev); +	serio_close(serio); +	serio_set_drvdata(serio, NULL); +	input_put_device(tw->dev); +	kfree(tw); +} + +/* + * tw_connect() is the routine that is called when someone adds a + * new serio device that supports the Touchwin protocol and registers it as + * an input device. + */ + +static int tw_connect(struct serio *serio, struct serio_driver *drv) +{ +	struct tw *tw; +	struct input_dev *input_dev; +	int err; + +	tw = kzalloc(sizeof(struct tw), GFP_KERNEL); +	input_dev = input_allocate_device(); +	if (!tw || !input_dev) { +		err = -ENOMEM; +		goto fail1; +	} + +	tw->serio = serio; +	tw->dev = input_dev; +	snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys); + +	input_dev->private = tw; +	input_dev->name = "Touchwindow Serial TouchScreen"; +	input_dev->phys = tw->phys; +	input_dev->id.bustype = BUS_RS232; +	input_dev->id.vendor = SERIO_TOUCHWIN; +	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_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0); +	input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0); + +	serio_set_drvdata(serio, tw); + +	err = serio_open(serio, drv); +	if (err) +		goto fail2; + +	err = input_register_device(tw->dev); +	if (err) +		goto fail3; + +	return 0; + + fail3:	serio_close(serio); + fail2:	serio_set_drvdata(serio, NULL); + fail1:	input_free_device(input_dev); +	kfree(tw); +	return err; +} + +/* + * The serio driver structure. + */ + +static struct serio_device_id tw_serio_ids[] = { +	{ +		.type	= SERIO_RS232, +		.proto	= SERIO_TOUCHWIN, +		.id	= SERIO_ANY, +		.extra	= SERIO_ANY, +	}, +	{ 0 } +}; + +MODULE_DEVICE_TABLE(serio, tw_serio_ids); + +static struct serio_driver tw_drv = { +	.driver		= { +		.name	= "touchwin", +	}, +	.description	= DRIVER_DESC, +	.id_table	= tw_serio_ids, +	.interrupt	= tw_interrupt, +	.connect	= tw_connect, +	.disconnect	= tw_disconnect, +}; + +/* + * The functions for inserting/removing us as a module. + */ + +static int __init tw_init(void) +{ +	serio_register_driver(&tw_drv); +	return 0; +} + +static void __exit tw_exit(void) +{ +	serio_unregister_driver(&tw_drv); +} + +module_init(tw_init); +module_exit(tw_exit); diff --git a/include/linux/serio.h b/include/linux/serio.h index 15260641315..c9069310b6a 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -219,5 +219,6 @@ static inline void serio_unpin_driver(struct serio *serio)  #define SERIO_MICROTOUCH	0x30  #define SERIO_PENMOUNT	0x31  #define SERIO_TOUCHRIGHT	0x32 +#define SERIO_TOUCHWIN	0x33  #endif  |