Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/touchscreen/touchwin.c
15109 views
1
/*
2
* Touchwindow serial touchscreen driver
3
*
4
* Copyright (c) 2006 Rick Koch <[email protected]>
5
*
6
* Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)
7
* Copyright (c) 2004 Vojtech Pavlik
8
* and Dan Streetman <[email protected]>
9
*/
10
11
/*
12
* This program is free software; you can redistribute it and/or modify it
13
* under the terms of the GNU General Public License version 2 as published
14
* by the Free Software Foundation.
15
*/
16
17
/*
18
* 2005/02/19 Rick Koch:
19
* The Touchwindow I used is made by Edmark Corp. and
20
* constantly outputs a stream of 0's unless it is touched.
21
* It then outputs 3 bytes: X, Y, and a copy of Y.
22
*/
23
24
#include <linux/errno.h>
25
#include <linux/kernel.h>
26
#include <linux/module.h>
27
#include <linux/slab.h>
28
#include <linux/input.h>
29
#include <linux/serio.h>
30
#include <linux/init.h>
31
32
#define DRIVER_DESC "Touchwindow serial touchscreen driver"
33
34
MODULE_AUTHOR("Rick Koch <[email protected]>");
35
MODULE_DESCRIPTION(DRIVER_DESC);
36
MODULE_LICENSE("GPL");
37
38
/*
39
* Definitions & global arrays.
40
*/
41
42
#define TW_LENGTH 3
43
44
#define TW_MIN_XC 0
45
#define TW_MAX_XC 0xff
46
#define TW_MIN_YC 0
47
#define TW_MAX_YC 0xff
48
49
/*
50
* Per-touchscreen data.
51
*/
52
53
struct tw {
54
struct input_dev *dev;
55
struct serio *serio;
56
int idx;
57
int touched;
58
unsigned char data[TW_LENGTH];
59
char phys[32];
60
};
61
62
static irqreturn_t tw_interrupt(struct serio *serio,
63
unsigned char data, unsigned int flags)
64
{
65
struct tw *tw = serio_get_drvdata(serio);
66
struct input_dev *dev = tw->dev;
67
68
if (data) { /* touch */
69
tw->touched = 1;
70
tw->data[tw->idx++] = data;
71
/* verify length and that the two Y's are the same */
72
if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
73
input_report_abs(dev, ABS_X, tw->data[0]);
74
input_report_abs(dev, ABS_Y, tw->data[1]);
75
input_report_key(dev, BTN_TOUCH, 1);
76
input_sync(dev);
77
tw->idx = 0;
78
}
79
} else if (tw->touched) { /* untouch */
80
input_report_key(dev, BTN_TOUCH, 0);
81
input_sync(dev);
82
tw->idx = 0;
83
tw->touched = 0;
84
}
85
86
return IRQ_HANDLED;
87
}
88
89
/*
90
* tw_disconnect() is the opposite of tw_connect()
91
*/
92
93
static void tw_disconnect(struct serio *serio)
94
{
95
struct tw *tw = serio_get_drvdata(serio);
96
97
input_get_device(tw->dev);
98
input_unregister_device(tw->dev);
99
serio_close(serio);
100
serio_set_drvdata(serio, NULL);
101
input_put_device(tw->dev);
102
kfree(tw);
103
}
104
105
/*
106
* tw_connect() is the routine that is called when someone adds a
107
* new serio device that supports the Touchwin protocol and registers it as
108
* an input device.
109
*/
110
111
static int tw_connect(struct serio *serio, struct serio_driver *drv)
112
{
113
struct tw *tw;
114
struct input_dev *input_dev;
115
int err;
116
117
tw = kzalloc(sizeof(struct tw), GFP_KERNEL);
118
input_dev = input_allocate_device();
119
if (!tw || !input_dev) {
120
err = -ENOMEM;
121
goto fail1;
122
}
123
124
tw->serio = serio;
125
tw->dev = input_dev;
126
snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
127
128
input_dev->name = "Touchwindow Serial TouchScreen";
129
input_dev->phys = tw->phys;
130
input_dev->id.bustype = BUS_RS232;
131
input_dev->id.vendor = SERIO_TOUCHWIN;
132
input_dev->id.product = 0;
133
input_dev->id.version = 0x0100;
134
input_dev->dev.parent = &serio->dev;
135
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
136
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
137
input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
138
input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);
139
140
serio_set_drvdata(serio, tw);
141
142
err = serio_open(serio, drv);
143
if (err)
144
goto fail2;
145
146
err = input_register_device(tw->dev);
147
if (err)
148
goto fail3;
149
150
return 0;
151
152
fail3: serio_close(serio);
153
fail2: serio_set_drvdata(serio, NULL);
154
fail1: input_free_device(input_dev);
155
kfree(tw);
156
return err;
157
}
158
159
/*
160
* The serio driver structure.
161
*/
162
163
static struct serio_device_id tw_serio_ids[] = {
164
{
165
.type = SERIO_RS232,
166
.proto = SERIO_TOUCHWIN,
167
.id = SERIO_ANY,
168
.extra = SERIO_ANY,
169
},
170
{ 0 }
171
};
172
173
MODULE_DEVICE_TABLE(serio, tw_serio_ids);
174
175
static struct serio_driver tw_drv = {
176
.driver = {
177
.name = "touchwin",
178
},
179
.description = DRIVER_DESC,
180
.id_table = tw_serio_ids,
181
.interrupt = tw_interrupt,
182
.connect = tw_connect,
183
.disconnect = tw_disconnect,
184
};
185
186
/*
187
* The functions for inserting/removing us as a module.
188
*/
189
190
static int __init tw_init(void)
191
{
192
return serio_register_driver(&tw_drv);
193
}
194
195
static void __exit tw_exit(void)
196
{
197
serio_unregister_driver(&tw_drv);
198
}
199
200
module_init(tw_init);
201
module_exit(tw_exit);
202
203