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