aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorFlorian Echtler <floe@butterbrot.org>2013-11-08 13:01:13 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-11-20 09:38:44 -0500
commitbdb5c57f209c3b78b3511476b233562496acd997 (patch)
tree81ea5b821ed139fc4a5908e004b9343cf2c6c3e0 /drivers/input/touchscreen
parent2c027b7c48a888ab173ba45babb4525e278375d9 (diff)
Input: add sur40 driver for Samsung SUR40 (aka MS Surface 2.0/Pixelsense)
This patch adds support for the built-in multitouch sensor in the Samsung SUR40 touchscreen device, also known as Microsoft Surface 2.0 or Microsoft Pixelsense. Support for raw video output from the sensor as well as the accelerometer will be added in a later patch. Signed-off-by: Florian Echtler <floe@butterbrot.org> Reviewed-by: David Herrmann <dh.herrmann@gmail.com> Reviewed-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/sur40.c466
3 files changed, 478 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 00d1e547b211..961d58d32647 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -906,6 +906,17 @@ config TOUCHSCREEN_STMPE
906 To compile this driver as a module, choose M here: the 906 To compile this driver as a module, choose M here: the
907 module will be called stmpe-ts. 907 module will be called stmpe-ts.
908 908
909config TOUCHSCREEN_SUR40
910 tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
911 depends on USB
912 select INPUT_POLLDEV
913 help
914 Say Y here if you want support for the Samsung SUR40 touchscreen
915 (also known as Microsoft Surface 2.0 or Microsoft PixelSense).
916
917 To compile this driver as a module, choose M here: the
918 module will be called sur40.
919
909config TOUCHSCREEN_TPS6507X 920config TOUCHSCREEN_TPS6507X
910 tristate "TPS6507x based touchscreens" 921 tristate "TPS6507x based touchscreens"
911 depends on I2C 922 depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7587883b8d38..62801f213346 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
54obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o 54obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
55obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o 55obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
56obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o 56obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
57obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
57obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o 58obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
58obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o 59obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
59obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o 60obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
new file mode 100644
index 000000000000..cfd1b7e8c001
--- /dev/null
+++ b/drivers/input/touchscreen/sur40.c
@@ -0,0 +1,466 @@
1/*
2 * Surface2.0/SUR40/PixelSense input driver
3 *
4 * Copyright (c) 2013 by Florian 'floe' Echtler <floe@butterbrot.org>
5 *
6 * Derived from the USB Skeleton driver 1.1,
7 * Copyright (c) 2003 Greg Kroah-Hartman (greg@kroah.com)
8 *
9 * and from the Apple USB BCM5974 multitouch driver,
10 * Copyright (c) 2008 Henrik Rydberg (rydberg@euromail.se)
11 *
12 * and from the generic hid-multitouch driver,
13 * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
19 */
20
21#include <linux/kernel.h>
22#include <linux/errno.h>
23#include <linux/delay.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/module.h>
27#include <linux/completion.h>
28#include <linux/uaccess.h>
29#include <linux/usb.h>
30#include <linux/printk.h>
31#include <linux/input-polldev.h>
32#include <linux/input/mt.h>
33#include <linux/usb/input.h>
34
35/* read 512 bytes from endpoint 0x86 -> get header + blobs */
36struct sur40_header {
37
38 __le16 type; /* always 0x0001 */
39 __le16 count; /* count of blobs (if 0: continue prev. packet) */
40
41 __le32 packet_id; /* unique ID for all packets in one frame */
42
43 __le32 timestamp; /* milliseconds (inc. by 16 or 17 each frame) */
44 __le32 unknown; /* "epoch?" always 02/03 00 00 00 */
45
46} __packed;
47
48struct sur40_blob {
49
50 __le16 blob_id;
51
52 u8 action; /* 0x02 = enter/exit, 0x03 = update (?) */
53 u8 unknown; /* always 0x01 or 0x02 (no idea what this is?) */
54
55 __le16 bb_pos_x; /* upper left corner of bounding box */
56 __le16 bb_pos_y;
57
58 __le16 bb_size_x; /* size of bounding box */
59 __le16 bb_size_y;
60
61 __le16 pos_x; /* finger tip position */
62 __le16 pos_y;
63
64 __le16 ctr_x; /* centroid position */
65 __le16 ctr_y;
66
67 __le16 axis_x; /* somehow related to major/minor axis, mostly: */
68 __le16 axis_y; /* axis_x == bb_size_y && axis_y == bb_size_x */
69
70 __le32 angle; /* orientation in radians relative to x axis -
71 actually an IEEE754 float, don't use in kernel */
72
73 __le32 area; /* size in pixels/pressure (?) */
74
75 u8 padding[32];
76
77} __packed;
78
79/* combined header/blob data */
80struct sur40_data {
81 struct sur40_header header;
82 struct sur40_blob blobs[];
83} __packed;
84
85
86/* version information */
87#define DRIVER_SHORT "sur40"
88#define DRIVER_AUTHOR "Florian 'floe' Echtler <floe@butterbrot.org>"
89#define DRIVER_DESC "Surface2.0/SUR40/PixelSense input driver"
90
91/* vendor and device IDs */
92#define ID_MICROSOFT 0x045e
93#define ID_SUR40 0x0775
94
95/* sensor resolution */
96#define SENSOR_RES_X 1920
97#define SENSOR_RES_Y 1080
98
99/* touch data endpoint */
100#define TOUCH_ENDPOINT 0x86
101
102/* polling interval (ms) */
103#define POLL_INTERVAL 10
104
105/* maximum number of contacts FIXME: this is a guess? */
106#define MAX_CONTACTS 64
107
108/* control commands */
109#define SUR40_GET_VERSION 0xb0 /* 12 bytes string */
110#define SUR40_UNKNOWN1 0xb3 /* 5 bytes */
111#define SUR40_UNKNOWN2 0xc1 /* 24 bytes */
112
113#define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */
114#define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */
115
116/*
117 * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
118 * here by mistake which is very likely to have corrupted the firmware EEPROM
119 * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
120 * Should you ever run into a similar problem, the background story to this
121 * incident and instructions on how to fix the corrupted EEPROM are available
122 * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
123*/
124
125struct sur40_state {
126
127 struct usb_device *usbdev;
128 struct device *dev;
129 struct input_polled_dev *input;
130
131 struct sur40_data *bulk_in_buffer;
132 size_t bulk_in_size;
133 u8 bulk_in_epaddr;
134
135 char phys[64];
136};
137
138static int sur40_command(struct sur40_state *dev,
139 u8 command, u16 index, void *buffer, u16 size)
140{
141 return usb_control_msg(dev->usbdev, usb_rcvctrlpipe(dev->usbdev, 0),
142 command,
143 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
144 0x00, index, buffer, size, 1000);
145}
146
147/* Initialization routine, called from sur40_open */
148static int sur40_init(struct sur40_state *dev)
149{
150 int result;
151 u8 buffer[24];
152
153 /* stupidly replay the original MS driver init sequence */
154 result = sur40_command(dev, SUR40_GET_VERSION, 0x00, buffer, 12);
155 if (result < 0)
156 return result;
157
158 result = sur40_command(dev, SUR40_GET_VERSION, 0x01, buffer, 12);
159 if (result < 0)
160 return result;
161
162 result = sur40_command(dev, SUR40_GET_VERSION, 0x02, buffer, 12);
163 if (result < 0)
164 return result;
165
166 result = sur40_command(dev, SUR40_UNKNOWN2, 0x00, buffer, 24);
167 if (result < 0)
168 return result;
169
170 result = sur40_command(dev, SUR40_UNKNOWN1, 0x00, buffer, 5);
171 if (result < 0)
172 return result;
173
174 result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12);
175
176 /*
177 * Discard the result buffer - no known data inside except
178 * some version strings, maybe extract these sometime...
179 */
180
181 return result;
182}
183
184/*
185 * Callback routines from input_polled_dev
186 */
187
188/* Enable the device, polling will now start. */
189static void sur40_open(struct input_polled_dev *polldev)
190{
191 struct sur40_state *sur40 = polldev->private;
192
193 dev_dbg(sur40->dev, "open\n");
194 sur40_init(sur40);
195}
196
197/* Disable device, polling has stopped. */
198static void sur40_close(struct input_polled_dev *polldev)
199{
200 struct sur40_state *sur40 = polldev->private;
201
202 dev_dbg(sur40->dev, "close\n");
203 /*
204 * There is no known way to stop the device, so we simply
205 * stop polling.
206 */
207}
208
209/*
210 * This function is called when a whole contact has been processed,
211 * so that it can assign it to a slot and store the data there.
212 */
213static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
214{
215 int wide, major, minor;
216
217 int bb_size_x = le16_to_cpu(blob->bb_size_x);
218 int bb_size_y = le16_to_cpu(blob->bb_size_y);
219
220 int pos_x = le16_to_cpu(blob->pos_x);
221 int pos_y = le16_to_cpu(blob->pos_y);
222
223 int ctr_x = le16_to_cpu(blob->ctr_x);
224 int ctr_y = le16_to_cpu(blob->ctr_y);
225
226 int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
227 if (slotnum < 0 || slotnum >= MAX_CONTACTS)
228 return;
229
230 input_mt_slot(input, slotnum);
231 input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
232 wide = (bb_size_x > bb_size_y);
233 major = max(bb_size_x, bb_size_y);
234 minor = min(bb_size_x, bb_size_y);
235
236 input_report_abs(input, ABS_MT_POSITION_X, pos_x);
237 input_report_abs(input, ABS_MT_POSITION_Y, pos_y);
238 input_report_abs(input, ABS_MT_TOOL_X, ctr_x);
239 input_report_abs(input, ABS_MT_TOOL_Y, ctr_y);
240
241 /* TODO: use a better orientation measure */
242 input_report_abs(input, ABS_MT_ORIENTATION, wide);
243 input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
244 input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
245}
246
247/* core function: poll for new input data */
248static void sur40_poll(struct input_polled_dev *polldev)
249{
250
251 struct sur40_state *sur40 = polldev->private;
252 struct input_dev *input = polldev->input;
253 int result, bulk_read, need_blobs, packet_blobs, i;
254 u32 packet_id;
255
256 struct sur40_header *header = &sur40->bulk_in_buffer->header;
257 struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0];
258
259 dev_dbg(sur40->dev, "poll\n");
260
261 need_blobs = -1;
262
263 do {
264
265 /* perform a blocking bulk read to get data from the device */
266 result = usb_bulk_msg(sur40->usbdev,
267 usb_rcvbulkpipe(sur40->usbdev, sur40->bulk_in_epaddr),
268 sur40->bulk_in_buffer, sur40->bulk_in_size,
269 &bulk_read, 1000);
270
271 dev_dbg(sur40->dev, "received %d bytes\n", bulk_read);
272
273 if (result < 0) {
274 dev_err(sur40->dev, "error in usb_bulk_read\n");
275 return;
276 }
277
278 result = bulk_read - sizeof(struct sur40_header);
279
280 if (result % sizeof(struct sur40_blob) != 0) {
281 dev_err(sur40->dev, "transfer size mismatch\n");
282 return;
283 }
284
285 /* first packet? */
286 if (need_blobs == -1) {
287 need_blobs = le16_to_cpu(header->count);
288 dev_dbg(sur40->dev, "need %d blobs\n", need_blobs);
289 packet_id = header->packet_id;
290 }
291
292 /*
293 * Sanity check. when video data is also being retrieved, the
294 * packet ID will usually increase in the middle of a series
295 * instead of at the end.
296 */
297 if (packet_id != header->packet_id)
298 dev_warn(sur40->dev, "packet ID mismatch\n");
299
300 packet_blobs = result / sizeof(struct sur40_blob);
301 dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
302
303 /* packets always contain at least 4 blobs, even if empty */
304 if (packet_blobs > need_blobs)
305 packet_blobs = need_blobs;
306
307 for (i = 0; i < packet_blobs; i++) {
308 need_blobs--;
309 dev_dbg(sur40->dev, "processing blob\n");
310 sur40_report_blob(&(inblob[i]), input);
311 }
312
313 } while (need_blobs > 0);
314
315 input_mt_sync_frame(input);
316 input_sync(input);
317}
318
319/* Initialize input device parameters. */
320static void sur40_input_setup(struct input_dev *input_dev)
321{
322 __set_bit(EV_KEY, input_dev->evbit);
323 __set_bit(EV_ABS, input_dev->evbit);
324
325 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
326 0, SENSOR_RES_X, 0, 0);
327 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
328 0, SENSOR_RES_Y, 0, 0);
329
330 input_set_abs_params(input_dev, ABS_MT_TOOL_X,
331 0, SENSOR_RES_X, 0, 0);
332 input_set_abs_params(input_dev, ABS_MT_TOOL_Y,
333 0, SENSOR_RES_Y, 0, 0);
334
335 /* max value unknown, but major/minor axis
336 * can never be larger than screen */
337 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
338 0, SENSOR_RES_X, 0, 0);
339 input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
340 0, SENSOR_RES_Y, 0, 0);
341
342 input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
343
344 input_mt_init_slots(input_dev, MAX_CONTACTS,
345 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
346}
347
348/* Check candidate USB interface. */
349static int sur40_probe(struct usb_interface *interface,
350 const struct usb_device_id *id)
351{
352 struct usb_device *usbdev = interface_to_usbdev(interface);
353 struct sur40_state *sur40;
354 struct usb_host_interface *iface_desc;
355 struct usb_endpoint_descriptor *endpoint;
356 struct input_polled_dev *poll_dev;
357 int error;
358
359 /* Check if we really have the right interface. */
360 iface_desc = &interface->altsetting[0];
361 if (iface_desc->desc.bInterfaceClass != 0xFF)
362 return -ENODEV;
363
364 /* Use endpoint #4 (0x86). */
365 endpoint = &iface_desc->endpoint[4].desc;
366 if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
367 return -ENODEV;
368
369 /* Allocate memory for our device state and initialize it. */
370 sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL);
371 if (!sur40)
372 return -ENOMEM;
373
374 poll_dev = input_allocate_polled_device();
375 if (!poll_dev) {
376 error = -ENOMEM;
377 goto err_free_dev;
378 }
379
380 /* Set up polled input device control structure */
381 poll_dev->private = sur40;
382 poll_dev->poll_interval = POLL_INTERVAL;
383 poll_dev->open = sur40_open;
384 poll_dev->poll = sur40_poll;
385 poll_dev->close = sur40_close;
386
387 /* Set up regular input device structure */
388 sur40_input_setup(poll_dev->input);
389
390 poll_dev->input->name = "Samsung SUR40";
391 usb_to_input_id(usbdev, &poll_dev->input->id);
392 usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
393 strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
394 poll_dev->input->phys = sur40->phys;
395 poll_dev->input->dev.parent = &interface->dev;
396
397 sur40->usbdev = usbdev;
398 sur40->dev = &interface->dev;
399 sur40->input = poll_dev;
400
401 /* use the bulk-in endpoint tested above */
402 sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
403 sur40->bulk_in_epaddr = endpoint->bEndpointAddress;
404 sur40->bulk_in_buffer = kmalloc(sur40->bulk_in_size, GFP_KERNEL);
405 if (!sur40->bulk_in_buffer) {
406 dev_err(&interface->dev, "Unable to allocate input buffer.");
407 error = -ENOMEM;
408 goto err_free_polldev;
409 }
410
411 error = input_register_polled_device(poll_dev);
412 if (error) {
413 dev_err(&interface->dev,
414 "Unable to register polled input device.");
415 goto err_free_buffer;
416 }
417
418 /* we can register the device now, as it is ready */
419 usb_set_intfdata(interface, sur40);
420 dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);
421
422 return 0;
423
424err_free_buffer:
425 kfree(sur40->bulk_in_buffer);
426err_free_polldev:
427 input_free_polled_device(sur40->input);
428err_free_dev:
429 kfree(sur40);
430
431 return error;
432}
433
434/* Unregister device & clean up. */
435static void sur40_disconnect(struct usb_interface *interface)
436{
437 struct sur40_state *sur40 = usb_get_intfdata(interface);
438
439 input_unregister_polled_device(sur40->input);
440 input_free_polled_device(sur40->input);
441 kfree(sur40->bulk_in_buffer);
442 kfree(sur40);
443
444 usb_set_intfdata(interface, NULL);
445 dev_dbg(&interface->dev, "%s is now disconnected\n", DRIVER_DESC);
446}
447
448static const struct usb_device_id sur40_table[] = {
449 { USB_DEVICE(ID_MICROSOFT, ID_SUR40) }, /* Samsung SUR40 */
450 { } /* terminating null entry */
451};
452MODULE_DEVICE_TABLE(usb, sur40_table);
453
454/* USB-specific object needed to register this driver with the USB subsystem. */
455static struct usb_driver sur40_driver = {
456 .name = DRIVER_SHORT,
457 .probe = sur40_probe,
458 .disconnect = sur40_disconnect,
459 .id_table = sur40_table,
460};
461
462module_usb_driver(sur40_driver);
463
464MODULE_AUTHOR(DRIVER_AUTHOR);
465MODULE_DESCRIPTION(DRIVER_DESC);
466MODULE_LICENSE("GPL");