111ea3173SRick Koch /*
211ea3173SRick Koch  * Touchwindow serial touchscreen driver
311ea3173SRick Koch  *
411ea3173SRick Koch  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
511ea3173SRick Koch  *
611ea3173SRick Koch  * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)
711ea3173SRick Koch  * Copyright (c) 2004 Vojtech Pavlik
811ea3173SRick Koch  * and Dan Streetman <ddstreet@ieee.org>
911ea3173SRick Koch  */
1011ea3173SRick Koch 
1111ea3173SRick Koch /*
1211ea3173SRick Koch  * This program is free software; you can redistribute it and/or modify it
1311ea3173SRick Koch  * under the terms of the GNU General Public License version 2 as published
1411ea3173SRick Koch  * by the Free Software Foundation.
1511ea3173SRick Koch  */
1611ea3173SRick Koch 
1711ea3173SRick Koch /*
1811ea3173SRick Koch  * 2005/02/19 Rick Koch:
1911ea3173SRick Koch  *   The Touchwindow I used is made by Edmark Corp. and
2011ea3173SRick Koch  *   constantly outputs a stream of 0's unless it is touched.
2111ea3173SRick Koch  *   It then outputs 3 bytes: X, Y, and a copy of Y.
2211ea3173SRick Koch  */
2311ea3173SRick Koch 
2411ea3173SRick Koch #include <linux/errno.h>
2511ea3173SRick Koch #include <linux/kernel.h>
2611ea3173SRick Koch #include <linux/module.h>
2711ea3173SRick Koch #include <linux/slab.h>
2811ea3173SRick Koch #include <linux/input.h>
2911ea3173SRick Koch #include <linux/serio.h>
3011ea3173SRick Koch #include <linux/init.h>
3111ea3173SRick Koch 
3211ea3173SRick Koch #define DRIVER_DESC	"Touchwindow serial touchscreen driver"
3311ea3173SRick Koch 
3411ea3173SRick Koch MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
3511ea3173SRick Koch MODULE_DESCRIPTION(DRIVER_DESC);
3611ea3173SRick Koch MODULE_LICENSE("GPL");
3711ea3173SRick Koch 
3811ea3173SRick Koch /*
3911ea3173SRick Koch  * Definitions & global arrays.
4011ea3173SRick Koch  */
4111ea3173SRick Koch 
4211ea3173SRick Koch #define TW_LENGTH 3
4311ea3173SRick Koch 
4411ea3173SRick Koch #define TW_MIN_XC 0
4511ea3173SRick Koch #define TW_MAX_XC 0xff
4611ea3173SRick Koch #define TW_MIN_YC 0
4711ea3173SRick Koch #define TW_MAX_YC 0xff
4811ea3173SRick Koch 
4911ea3173SRick Koch /*
5011ea3173SRick Koch  * Per-touchscreen data.
5111ea3173SRick Koch  */
5211ea3173SRick Koch 
5311ea3173SRick Koch struct tw {
5411ea3173SRick Koch 	struct input_dev *dev;
5511ea3173SRick Koch 	struct serio *serio;
5611ea3173SRick Koch 	int idx;
5711ea3173SRick Koch 	int touched;
5811ea3173SRick Koch 	unsigned char data[TW_LENGTH];
5911ea3173SRick Koch 	char phys[32];
6011ea3173SRick Koch };
6111ea3173SRick Koch 
6211ea3173SRick Koch static irqreturn_t tw_interrupt(struct serio *serio,
637d12e780SDavid Howells 		unsigned char data, unsigned int flags)
6411ea3173SRick Koch {
6511ea3173SRick Koch 	struct tw *tw = serio_get_drvdata(serio);
6611ea3173SRick Koch 	struct input_dev *dev = tw->dev;
6711ea3173SRick Koch 
6811ea3173SRick Koch 	if (data) {		/* touch */
6911ea3173SRick Koch 		tw->touched = 1;
7011ea3173SRick Koch 		tw->data[tw->idx++] = data;
7111ea3173SRick Koch 		/* verify length and that the two Y's are the same */
7211ea3173SRick Koch 		if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
7311ea3173SRick Koch 			input_report_abs(dev, ABS_X, tw->data[0]);
7411ea3173SRick Koch 			input_report_abs(dev, ABS_Y, tw->data[1]);
7511ea3173SRick Koch 			input_report_key(dev, BTN_TOUCH, 1);
7611ea3173SRick Koch 			input_sync(dev);
7711ea3173SRick Koch 			tw->idx = 0;
7811ea3173SRick Koch 		}
7911ea3173SRick Koch 	} else if (tw->touched) {	/* untouch */
8011ea3173SRick Koch 		input_report_key(dev, BTN_TOUCH, 0);
8111ea3173SRick Koch 		input_sync(dev);
8211ea3173SRick Koch 		tw->idx = 0;
8311ea3173SRick Koch 		tw->touched = 0;
8411ea3173SRick Koch 	}
8511ea3173SRick Koch 
8611ea3173SRick Koch 	return IRQ_HANDLED;
8711ea3173SRick Koch }
8811ea3173SRick Koch 
8911ea3173SRick Koch /*
9011ea3173SRick Koch  * tw_disconnect() is the opposite of tw_connect()
9111ea3173SRick Koch  */
9211ea3173SRick Koch 
9311ea3173SRick Koch static void tw_disconnect(struct serio *serio)
9411ea3173SRick Koch {
9511ea3173SRick Koch 	struct tw *tw = serio_get_drvdata(serio);
9611ea3173SRick Koch 
9711ea3173SRick Koch 	input_get_device(tw->dev);
9811ea3173SRick Koch 	input_unregister_device(tw->dev);
9911ea3173SRick Koch 	serio_close(serio);
10011ea3173SRick Koch 	serio_set_drvdata(serio, NULL);
10111ea3173SRick Koch 	input_put_device(tw->dev);
10211ea3173SRick Koch 	kfree(tw);
10311ea3173SRick Koch }
10411ea3173SRick Koch 
10511ea3173SRick Koch /*
10611ea3173SRick Koch  * tw_connect() is the routine that is called when someone adds a
10711ea3173SRick Koch  * new serio device that supports the Touchwin protocol and registers it as
10811ea3173SRick Koch  * an input device.
10911ea3173SRick Koch  */
11011ea3173SRick Koch 
11111ea3173SRick Koch static int tw_connect(struct serio *serio, struct serio_driver *drv)
11211ea3173SRick Koch {
11311ea3173SRick Koch 	struct tw *tw;
11411ea3173SRick Koch 	struct input_dev *input_dev;
11511ea3173SRick Koch 	int err;
11611ea3173SRick Koch 
11711ea3173SRick Koch 	tw = kzalloc(sizeof(struct tw), GFP_KERNEL);
11811ea3173SRick Koch 	input_dev = input_allocate_device();
11911ea3173SRick Koch 	if (!tw || !input_dev) {
12011ea3173SRick Koch 		err = -ENOMEM;
12111ea3173SRick Koch 		goto fail1;
12211ea3173SRick Koch 	}
12311ea3173SRick Koch 
12411ea3173SRick Koch 	tw->serio = serio;
12511ea3173SRick Koch 	tw->dev = input_dev;
12611ea3173SRick Koch 	snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
12711ea3173SRick Koch 
12811ea3173SRick Koch 	input_dev->name = "Touchwindow Serial TouchScreen";
12911ea3173SRick Koch 	input_dev->phys = tw->phys;
13011ea3173SRick Koch 	input_dev->id.bustype = BUS_RS232;
13111ea3173SRick Koch 	input_dev->id.vendor = SERIO_TOUCHWIN;
13211ea3173SRick Koch 	input_dev->id.product = 0;
13311ea3173SRick Koch 	input_dev->id.version = 0x0100;
134a5394fb0SDmitry Torokhov 	input_dev->dev.parent = &serio->dev;
13511ea3173SRick Koch 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
13611ea3173SRick Koch 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
13711ea3173SRick Koch 	input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
13811ea3173SRick Koch 	input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);
13911ea3173SRick Koch 
14011ea3173SRick Koch 	serio_set_drvdata(serio, tw);
14111ea3173SRick Koch 
14211ea3173SRick Koch 	err = serio_open(serio, drv);
14311ea3173SRick Koch 	if (err)
14411ea3173SRick Koch 		goto fail2;
14511ea3173SRick Koch 
14611ea3173SRick Koch 	err = input_register_device(tw->dev);
14711ea3173SRick Koch 	if (err)
14811ea3173SRick Koch 		goto fail3;
14911ea3173SRick Koch 
15011ea3173SRick Koch 	return 0;
15111ea3173SRick Koch 
15211ea3173SRick Koch  fail3:	serio_close(serio);
15311ea3173SRick Koch  fail2:	serio_set_drvdata(serio, NULL);
15411ea3173SRick Koch  fail1:	input_free_device(input_dev);
15511ea3173SRick Koch 	kfree(tw);
15611ea3173SRick Koch 	return err;
15711ea3173SRick Koch }
15811ea3173SRick Koch 
15911ea3173SRick Koch /*
16011ea3173SRick Koch  * The serio driver structure.
16111ea3173SRick Koch  */
16211ea3173SRick Koch 
16311ea3173SRick Koch static struct serio_device_id tw_serio_ids[] = {
16411ea3173SRick Koch 	{
16511ea3173SRick Koch 		.type	= SERIO_RS232,
16611ea3173SRick Koch 		.proto	= SERIO_TOUCHWIN,
16711ea3173SRick Koch 		.id	= SERIO_ANY,
16811ea3173SRick Koch 		.extra	= SERIO_ANY,
16911ea3173SRick Koch 	},
17011ea3173SRick Koch 	{ 0 }
17111ea3173SRick Koch };
17211ea3173SRick Koch 
17311ea3173SRick Koch MODULE_DEVICE_TABLE(serio, tw_serio_ids);
17411ea3173SRick Koch 
17511ea3173SRick Koch static struct serio_driver tw_drv = {
17611ea3173SRick Koch 	.driver		= {
17711ea3173SRick Koch 		.name	= "touchwin",
17811ea3173SRick Koch 	},
17911ea3173SRick Koch 	.description	= DRIVER_DESC,
18011ea3173SRick Koch 	.id_table	= tw_serio_ids,
18111ea3173SRick Koch 	.interrupt	= tw_interrupt,
18211ea3173SRick Koch 	.connect	= tw_connect,
18311ea3173SRick Koch 	.disconnect	= tw_disconnect,
18411ea3173SRick Koch };
18511ea3173SRick Koch 
18611ea3173SRick Koch /*
18711ea3173SRick Koch  * The functions for inserting/removing us as a module.
18811ea3173SRick Koch  */
18911ea3173SRick Koch 
19011ea3173SRick Koch static int __init tw_init(void)
19111ea3173SRick Koch {
192153a9df0SAkinobu Mita 	return serio_register_driver(&tw_drv);
19311ea3173SRick Koch }
19411ea3173SRick Koch 
19511ea3173SRick Koch static void __exit tw_exit(void)
19611ea3173SRick Koch {
19711ea3173SRick Koch 	serio_unregister_driver(&tw_drv);
19811ea3173SRick Koch }
19911ea3173SRick Koch 
20011ea3173SRick Koch module_init(tw_init);
20111ea3173SRick Koch module_exit(tw_exit);
202