Commit 422dee56b8155e4627f657ee67e962066ca7aff3
Committed by
Dmitry Torokhov
1 parent
6c04d7b3cf
Exists in
master
and in
39 other branches
Input: add driver for hampshire serial touchscreens
Adds support for Hampshire TSHARC serial touchscreens. Implements Hampshire's 4-byte communication protocol. Signed-off-by: Adam Bennett <abennett72@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Showing 4 changed files with 219 additions and 0 deletions Side-by-side Diff
drivers/input/touchscreen/Kconfig
... | ... | @@ -119,6 +119,18 @@ |
119 | 119 | To compile this driver as a module, choose M here: the |
120 | 120 | module will be called dynapro. |
121 | 121 | |
122 | +config TOUCHSCREEN_HAMPSHIRE | |
123 | + tristate "Hampshire serial touchscreen" | |
124 | + select SERIO | |
125 | + help | |
126 | + Say Y here if you have a Hampshire serial touchscreen connected to | |
127 | + your system. | |
128 | + | |
129 | + If unsure, say N. | |
130 | + | |
131 | + To compile this driver as a module, choose M here: the | |
132 | + module will be called hampshire. | |
133 | + | |
122 | 134 | config TOUCHSCREEN_EETI |
123 | 135 | tristate "EETI touchscreen panel support" |
124 | 136 | depends on I2C |
drivers/input/touchscreen/Makefile
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
14 | 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
15 | 15 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
16 | +obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | |
16 | 17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
17 | 18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
18 | 19 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
drivers/input/touchscreen/hampshire.c
1 | +/* | |
2 | + * Hampshire serial touchscreen driver | |
3 | + * | |
4 | + * Copyright (c) 2010 Adam Bennett | |
5 | + * Based on the dynapro driver (c) Tias Guns | |
6 | + * | |
7 | + */ | |
8 | + | |
9 | +/* | |
10 | + * This program is free software; you can redistribute it and/or modify it | |
11 | + * under the terms of the GNU General Public License version 2 as published by | |
12 | + * the Free Software Foundation. | |
13 | + */ | |
14 | + | |
15 | +/* | |
16 | + * 2010/04/08 Adam Bennett <abennett72@gmail.com> | |
17 | + * Copied dynapro.c and edited for Hampshire 4-byte protocol | |
18 | + */ | |
19 | + | |
20 | +#include <linux/errno.h> | |
21 | +#include <linux/kernel.h> | |
22 | +#include <linux/module.h> | |
23 | +#include <linux/slab.h> | |
24 | +#include <linux/input.h> | |
25 | +#include <linux/serio.h> | |
26 | +#include <linux/init.h> | |
27 | + | |
28 | +#define DRIVER_DESC "Hampshire serial touchscreen driver" | |
29 | + | |
30 | +MODULE_AUTHOR("Adam Bennett <abennett72@gmail.com>"); | |
31 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
32 | +MODULE_LICENSE("GPL"); | |
33 | + | |
34 | +/* | |
35 | + * Definitions & global arrays. | |
36 | + */ | |
37 | + | |
38 | +#define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40 | |
39 | +#define HAMPSHIRE_FORMAT_LENGTH 4 | |
40 | +#define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80 | |
41 | + | |
42 | +#define HAMPSHIRE_MIN_XC 0 | |
43 | +#define HAMPSHIRE_MAX_XC 0x1000 | |
44 | +#define HAMPSHIRE_MIN_YC 0 | |
45 | +#define HAMPSHIRE_MAX_YC 0x1000 | |
46 | + | |
47 | +#define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6)) | |
48 | +#define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9)) | |
49 | +#define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0]) | |
50 | + | |
51 | +/* | |
52 | + * Per-touchscreen data. | |
53 | + */ | |
54 | + | |
55 | +struct hampshire { | |
56 | + struct input_dev *dev; | |
57 | + struct serio *serio; | |
58 | + int idx; | |
59 | + unsigned char data[HAMPSHIRE_FORMAT_LENGTH]; | |
60 | + char phys[32]; | |
61 | +}; | |
62 | + | |
63 | +static void hampshire_process_data(struct hampshire *phampshire) | |
64 | +{ | |
65 | + struct input_dev *dev = phampshire->dev; | |
66 | + | |
67 | + if (HAMPSHIRE_FORMAT_LENGTH == ++phampshire->idx) { | |
68 | + input_report_abs(dev, ABS_X, HAMPSHIRE_GET_XC(phampshire->data)); | |
69 | + input_report_abs(dev, ABS_Y, HAMPSHIRE_GET_YC(phampshire->data)); | |
70 | + input_report_key(dev, BTN_TOUCH, | |
71 | + HAMPSHIRE_GET_TOUCHED(phampshire->data)); | |
72 | + input_sync(dev); | |
73 | + | |
74 | + phampshire->idx = 0; | |
75 | + } | |
76 | +} | |
77 | + | |
78 | +static irqreturn_t hampshire_interrupt(struct serio *serio, | |
79 | + unsigned char data, unsigned int flags) | |
80 | +{ | |
81 | + struct hampshire *phampshire = serio_get_drvdata(serio); | |
82 | + | |
83 | + phampshire->data[phampshire->idx] = data; | |
84 | + | |
85 | + if (HAMPSHIRE_RESPONSE_BEGIN_BYTE & phampshire->data[0]) | |
86 | + hampshire_process_data(phampshire); | |
87 | + else | |
88 | + dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", | |
89 | + phampshire->data[0]); | |
90 | + | |
91 | + return IRQ_HANDLED; | |
92 | +} | |
93 | + | |
94 | +static void hampshire_disconnect(struct serio *serio) | |
95 | +{ | |
96 | + struct hampshire *phampshire = serio_get_drvdata(serio); | |
97 | + | |
98 | + input_get_device(phampshire->dev); | |
99 | + input_unregister_device(phampshire->dev); | |
100 | + serio_close(serio); | |
101 | + serio_set_drvdata(serio, NULL); | |
102 | + input_put_device(phampshire->dev); | |
103 | + kfree(phampshire); | |
104 | +} | |
105 | + | |
106 | +/* | |
107 | + * hampshire_connect() is the routine that is called when someone adds a | |
108 | + * new serio device that supports hampshire protocol and registers it as | |
109 | + * an input device. This is usually accomplished using inputattach. | |
110 | + */ | |
111 | + | |
112 | +static int hampshire_connect(struct serio *serio, struct serio_driver *drv) | |
113 | +{ | |
114 | + struct hampshire *phampshire; | |
115 | + struct input_dev *input_dev; | |
116 | + int err; | |
117 | + | |
118 | + phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); | |
119 | + input_dev = input_allocate_device(); | |
120 | + if (!phampshire || !input_dev) { | |
121 | + err = -ENOMEM; | |
122 | + goto fail1; | |
123 | + } | |
124 | + | |
125 | + phampshire->serio = serio; | |
126 | + phampshire->dev = input_dev; | |
127 | + snprintf(phampshire->phys, sizeof(phampshire->phys), | |
128 | + "%s/input0", serio->phys); | |
129 | + | |
130 | + input_dev->name = "Hampshire Serial TouchScreen"; | |
131 | + input_dev->phys = phampshire->phys; | |
132 | + input_dev->id.bustype = BUS_RS232; | |
133 | + input_dev->id.vendor = SERIO_HAMPSHIRE; | |
134 | + input_dev->id.product = 0; | |
135 | + input_dev->id.version = 0x0001; | |
136 | + input_dev->dev.parent = &serio->dev; | |
137 | + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | |
138 | + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | |
139 | + input_set_abs_params(phampshire->dev, ABS_X, | |
140 | + HAMPSHIRE_MIN_XC, HAMPSHIRE_MAX_XC, 0, 0); | |
141 | + input_set_abs_params(phampshire->dev, ABS_Y, | |
142 | + HAMPSHIRE_MIN_YC, HAMPSHIRE_MAX_YC, 0, 0); | |
143 | + | |
144 | + serio_set_drvdata(serio, phampshire); | |
145 | + | |
146 | + err = serio_open(serio, drv); | |
147 | + if (err) | |
148 | + goto fail2; | |
149 | + | |
150 | + err = input_register_device(phampshire->dev); | |
151 | + if (err) | |
152 | + goto fail3; | |
153 | + | |
154 | + return 0; | |
155 | + | |
156 | + fail3: serio_close(serio); | |
157 | + fail2: serio_set_drvdata(serio, NULL); | |
158 | + fail1: input_free_device(input_dev); | |
159 | + kfree(phampshire); | |
160 | + return err; | |
161 | +} | |
162 | + | |
163 | +/* | |
164 | + * The serio driver structure. | |
165 | + */ | |
166 | + | |
167 | +static struct serio_device_id hampshire_serio_ids[] = { | |
168 | + { | |
169 | + .type = SERIO_RS232, | |
170 | + .proto = SERIO_HAMPSHIRE, | |
171 | + .id = SERIO_ANY, | |
172 | + .extra = SERIO_ANY, | |
173 | + }, | |
174 | + { 0 } | |
175 | +}; | |
176 | + | |
177 | +MODULE_DEVICE_TABLE(serio, hampshire_serio_ids); | |
178 | + | |
179 | +static struct serio_driver hampshire_drv = { | |
180 | + .driver = { | |
181 | + .name = "hampshire", | |
182 | + }, | |
183 | + .description = DRIVER_DESC, | |
184 | + .id_table = hampshire_serio_ids, | |
185 | + .interrupt = hampshire_interrupt, | |
186 | + .connect = hampshire_connect, | |
187 | + .disconnect = hampshire_disconnect, | |
188 | +}; | |
189 | + | |
190 | +/* | |
191 | + * The functions for inserting/removing us as a module. | |
192 | + */ | |
193 | + | |
194 | +static int __init hampshire_init(void) | |
195 | +{ | |
196 | + return serio_register_driver(&hampshire_drv); | |
197 | +} | |
198 | + | |
199 | +static void __exit hampshire_exit(void) | |
200 | +{ | |
201 | + serio_unregister_driver(&hampshire_drv); | |
202 | +} | |
203 | + | |
204 | +module_init(hampshire_init); | |
205 | +module_exit(hampshire_exit); |