Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/touchscreen/dynapro.c
15109 views
1
/*
2
* Dynapro serial touchscreen driver
3
*
4
* Copyright (c) 2009 Tias Guns
5
* Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and
6
* Richard Lemon
7
*
8
*/
9
10
/*
11
* This program is free software; you can redistribute it and/or modify it
12
* under the terms of the GNU General Public License version 2 as published by
13
* the Free Software Foundation.
14
*/
15
16
/*
17
* 2009/09/19 Tias Guns <[email protected]>
18
* Copied inexio.c and edited for Dynapro protocol (from retired Xorg module)
19
*/
20
21
#include <linux/errno.h>
22
#include <linux/kernel.h>
23
#include <linux/module.h>
24
#include <linux/slab.h>
25
#include <linux/input.h>
26
#include <linux/serio.h>
27
#include <linux/init.h>
28
29
#define DRIVER_DESC "Dynapro serial touchscreen driver"
30
31
MODULE_AUTHOR("Tias Guns <[email protected]>");
32
MODULE_DESCRIPTION(DRIVER_DESC);
33
MODULE_LICENSE("GPL");
34
35
/*
36
* Definitions & global arrays.
37
*/
38
39
#define DYNAPRO_FORMAT_TOUCH_BIT 0x40
40
#define DYNAPRO_FORMAT_LENGTH 3
41
#define DYNAPRO_RESPONSE_BEGIN_BYTE 0x80
42
43
#define DYNAPRO_MIN_XC 0
44
#define DYNAPRO_MAX_XC 0x3ff
45
#define DYNAPRO_MIN_YC 0
46
#define DYNAPRO_MAX_YC 0x3ff
47
48
#define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4))
49
#define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7))
50
#define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0])
51
52
/*
53
* Per-touchscreen data.
54
*/
55
56
struct dynapro {
57
struct input_dev *dev;
58
struct serio *serio;
59
int idx;
60
unsigned char data[DYNAPRO_FORMAT_LENGTH];
61
char phys[32];
62
};
63
64
static void dynapro_process_data(struct dynapro *pdynapro)
65
{
66
struct input_dev *dev = pdynapro->dev;
67
68
if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) {
69
input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data));
70
input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data));
71
input_report_key(dev, BTN_TOUCH,
72
DYNAPRO_GET_TOUCHED(pdynapro->data));
73
input_sync(dev);
74
75
pdynapro->idx = 0;
76
}
77
}
78
79
static irqreturn_t dynapro_interrupt(struct serio *serio,
80
unsigned char data, unsigned int flags)
81
{
82
struct dynapro *pdynapro = serio_get_drvdata(serio);
83
84
pdynapro->data[pdynapro->idx] = data;
85
86
if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0])
87
dynapro_process_data(pdynapro);
88
else
89
dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n",
90
pdynapro->data[0]);
91
92
return IRQ_HANDLED;
93
}
94
95
static void dynapro_disconnect(struct serio *serio)
96
{
97
struct dynapro *pdynapro = serio_get_drvdata(serio);
98
99
input_get_device(pdynapro->dev);
100
input_unregister_device(pdynapro->dev);
101
serio_close(serio);
102
serio_set_drvdata(serio, NULL);
103
input_put_device(pdynapro->dev);
104
kfree(pdynapro);
105
}
106
107
/*
108
* dynapro_connect() is the routine that is called when someone adds a
109
* new serio device that supports dynapro protocol and registers it as
110
* an input device. This is usually accomplished using inputattach.
111
*/
112
113
static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
114
{
115
struct dynapro *pdynapro;
116
struct input_dev *input_dev;
117
int err;
118
119
pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL);
120
input_dev = input_allocate_device();
121
if (!pdynapro || !input_dev) {
122
err = -ENOMEM;
123
goto fail1;
124
}
125
126
pdynapro->serio = serio;
127
pdynapro->dev = input_dev;
128
snprintf(pdynapro->phys, sizeof(pdynapro->phys),
129
"%s/input0", serio->phys);
130
131
input_dev->name = "Dynapro Serial TouchScreen";
132
input_dev->phys = pdynapro->phys;
133
input_dev->id.bustype = BUS_RS232;
134
input_dev->id.vendor = SERIO_DYNAPRO;
135
input_dev->id.product = 0;
136
input_dev->id.version = 0x0001;
137
input_dev->dev.parent = &serio->dev;
138
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
139
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
140
input_set_abs_params(pdynapro->dev, ABS_X,
141
DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0);
142
input_set_abs_params(pdynapro->dev, ABS_Y,
143
DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0);
144
145
serio_set_drvdata(serio, pdynapro);
146
147
err = serio_open(serio, drv);
148
if (err)
149
goto fail2;
150
151
err = input_register_device(pdynapro->dev);
152
if (err)
153
goto fail3;
154
155
return 0;
156
157
fail3: serio_close(serio);
158
fail2: serio_set_drvdata(serio, NULL);
159
fail1: input_free_device(input_dev);
160
kfree(pdynapro);
161
return err;
162
}
163
164
/*
165
* The serio driver structure.
166
*/
167
168
static struct serio_device_id dynapro_serio_ids[] = {
169
{
170
.type = SERIO_RS232,
171
.proto = SERIO_DYNAPRO,
172
.id = SERIO_ANY,
173
.extra = SERIO_ANY,
174
},
175
{ 0 }
176
};
177
178
MODULE_DEVICE_TABLE(serio, dynapro_serio_ids);
179
180
static struct serio_driver dynapro_drv = {
181
.driver = {
182
.name = "dynapro",
183
},
184
.description = DRIVER_DESC,
185
.id_table = dynapro_serio_ids,
186
.interrupt = dynapro_interrupt,
187
.connect = dynapro_connect,
188
.disconnect = dynapro_disconnect,
189
};
190
191
/*
192
* The functions for inserting/removing us as a module.
193
*/
194
195
static int __init dynapro_init(void)
196
{
197
return serio_register_driver(&dynapro_drv);
198
}
199
200
static void __exit dynapro_exit(void)
201
{
202
serio_unregister_driver(&dynapro_drv);
203
}
204
205
module_init(dynapro_init);
206
module_exit(dynapro_exit);
207
208