2 * HID driver for 3M PCT multitouch panels
4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
5 * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
6 * Copyright (c) 2010 Canonical, Ltd.
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
17 #include <linux/device.h>
18 #include <linux/hid.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/usb.h>
23 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
24 MODULE_DESCRIPTION("3M PCT multitouch panels");
25 MODULE_LICENSE("GPL");
30 #define MAX_TRKID USHRT_MAX
31 #define MAX_EVENTS 360
33 /* estimated signal-to-noise ratios */
45 struct mmm_finger f
[MAX_SLOTS
];
52 static int mmm_input_mapping(struct hid_device
*hdev
, struct hid_input
*hi
,
53 struct hid_field
*field
, struct hid_usage
*usage
,
54 unsigned long **bit
, int *max
)
56 int f1
= field
->logical_minimum
;
57 int f2
= field
->logical_maximum
;
60 switch (usage
->hid
& HID_USAGE_PAGE
) {
68 hid_map_usage(hi
, usage
, bit
, max
,
69 EV_ABS
, ABS_MT_POSITION_X
);
70 input_set_abs_params(hi
->input
, ABS_MT_POSITION_X
,
71 f1
, f2
, df
/ SN_MOVE
, 0);
72 /* touchscreen emulation */
73 input_set_abs_params(hi
->input
, ABS_X
,
74 f1
, f2
, df
/ SN_MOVE
, 0);
77 hid_map_usage(hi
, usage
, bit
, max
,
78 EV_ABS
, ABS_MT_POSITION_Y
);
79 input_set_abs_params(hi
->input
, ABS_MT_POSITION_Y
,
80 f1
, f2
, df
/ SN_MOVE
, 0);
81 /* touchscreen emulation */
82 input_set_abs_params(hi
->input
, ABS_Y
,
83 f1
, f2
, df
/ SN_MOVE
, 0);
88 case HID_UP_DIGITIZER
:
90 /* we do not want to map these: no input-oriented meaning */
93 case HID_DG_INPUTMODE
:
94 case HID_DG_DEVICEINDEX
:
95 case HID_DG_CONTACTCOUNT
:
96 case HID_DG_CONTACTMAX
:
98 case HID_DG_CONFIDENCE
:
100 case HID_DG_TIPSWITCH
:
101 /* touchscreen emulation */
102 hid_map_usage(hi
, usage
, bit
, max
, EV_KEY
, BTN_TOUCH
);
103 input_set_capability(hi
->input
, EV_KEY
, BTN_TOUCH
);
106 hid_map_usage(hi
, usage
, bit
, max
,
107 EV_ABS
, ABS_MT_TOUCH_MAJOR
);
108 input_set_abs_params(hi
->input
, ABS_MT_TOUCH_MAJOR
,
109 f1
, f2
, df
/ SN_WIDTH
, 0);
112 hid_map_usage(hi
, usage
, bit
, max
,
113 EV_ABS
, ABS_MT_TOUCH_MINOR
);
114 input_set_abs_params(hi
->input
, ABS_MT_TOUCH_MINOR
,
115 f1
, f2
, df
/ SN_WIDTH
, 0);
116 input_set_abs_params(hi
->input
, ABS_MT_ORIENTATION
,
119 case HID_DG_CONTACTID
:
120 field
->logical_maximum
= MAX_TRKID
;
121 hid_map_usage(hi
, usage
, bit
, max
,
122 EV_ABS
, ABS_MT_TRACKING_ID
);
123 input_set_abs_params(hi
->input
, ABS_MT_TRACKING_ID
,
126 input_mt_create_slots(hi
->input
, MAX_SLOTS
);
127 input_set_events_per_packet(hi
->input
, MAX_EVENTS
);
130 /* let hid-input decide for the others */
134 /* we do not want to map these: no input-oriented meaning */
141 static int mmm_input_mapped(struct hid_device
*hdev
, struct hid_input
*hi
,
142 struct hid_field
*field
, struct hid_usage
*usage
,
143 unsigned long **bit
, int *max
)
145 /* tell hid-input to skip setup of these event types */
146 if (usage
->type
== EV_KEY
|| usage
->type
== EV_ABS
)
147 set_bit(usage
->type
, hi
->input
->evbit
);
152 * this function is called when a whole packet has been received and processed,
153 * so that it can decide what to send to the input layer.
155 static void mmm_filter_event(struct mmm_data
*md
, struct input_dev
*input
)
157 struct mmm_finger
*oldest
= 0;
159 for (i
= 0; i
< MAX_SLOTS
; ++i
) {
160 struct mmm_finger
*f
= &md
->f
[i
];
162 /* this finger is just placeholder data, ignore */
165 input_mt_slot(input
, i
);
167 /* this finger is on the screen */
168 int wide
= (f
->w
> f
->h
);
169 /* divided by two to match visual scale of touch */
170 int major
= max(f
->w
, f
->h
) >> 1;
171 int minor
= min(f
->w
, f
->h
) >> 1;
175 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, f
->id
);
176 input_event(input
, EV_ABS
, ABS_MT_POSITION_X
, f
->x
);
177 input_event(input
, EV_ABS
, ABS_MT_POSITION_Y
, f
->y
);
178 input_event(input
, EV_ABS
, ABS_MT_ORIENTATION
, wide
);
179 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MAJOR
, major
);
180 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MINOR
, minor
);
181 /* touchscreen emulation: pick the oldest contact */
182 if (!oldest
|| ((f
->id
- oldest
->id
) & (SHRT_MAX
+ 1)))
185 /* this finger took off the screen */
186 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, -1);
188 f
->prev_touch
= f
->touch
;
192 /* touchscreen emulation */
194 input_event(input
, EV_KEY
, BTN_TOUCH
, 1);
195 input_event(input
, EV_ABS
, ABS_X
, oldest
->x
);
196 input_event(input
, EV_ABS
, ABS_Y
, oldest
->y
);
198 input_event(input
, EV_KEY
, BTN_TOUCH
, 0);
204 * this function is called upon all reports
205 * so that we can accumulate contact point information,
206 * and call input_mt_sync after each point.
208 static int mmm_event(struct hid_device
*hid
, struct hid_field
*field
,
209 struct hid_usage
*usage
, __s32 value
)
211 struct mmm_data
*md
= hid_get_drvdata(hid
);
213 * strangely, this function can be called before
214 * field->hidinput is initialized!
216 if (hid
->claimed
& HID_CLAIMED_INPUT
) {
217 struct input_dev
*input
= field
->hidinput
->input
;
218 switch (usage
->hid
) {
219 case HID_DG_TIPSWITCH
:
222 case HID_DG_CONFIDENCE
:
227 md
->f
[md
->curid
].w
= value
;
231 md
->f
[md
->curid
].h
= value
;
233 case HID_DG_CONTACTID
:
234 value
= clamp_val(value
, 0, MAX_SLOTS
- 1);
237 md
->f
[value
].touch
= md
->touch
;
238 md
->f
[value
].valid
= 1;
244 md
->f
[md
->curid
].x
= value
;
248 md
->f
[md
->curid
].y
= value
;
250 case HID_DG_CONTACTCOUNT
:
253 if (md
->nreal
>= md
->nexp
) {
254 mmm_filter_event(md
, input
);
261 /* we have handled the hidinput part, now remains hiddev */
262 if (hid
->claimed
& HID_CLAIMED_HIDDEV
&& hid
->hiddev_hid_event
)
263 hid
->hiddev_hid_event(hid
, field
, usage
, value
);
268 static int mmm_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
273 hdev
->quirks
|= HID_QUIRK_NO_INPUT_SYNC
;
275 md
= kzalloc(sizeof(struct mmm_data
), GFP_KERNEL
);
277 dev_err(&hdev
->dev
, "cannot allocate 3M data\n");
280 hid_set_drvdata(hdev
, md
);
282 ret
= hid_parse(hdev
);
284 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
291 static void mmm_remove(struct hid_device
*hdev
)
294 kfree(hid_get_drvdata(hdev
));
295 hid_set_drvdata(hdev
, NULL
);
298 static const struct hid_device_id mmm_devices
[] = {
299 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M1968
) },
300 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M2256
) },
303 MODULE_DEVICE_TABLE(hid
, mmm_devices
);
305 static const struct hid_usage_id mmm_grabbed_usages
[] = {
306 { HID_ANY_ID
, HID_ANY_ID
, HID_ANY_ID
},
307 { HID_ANY_ID
- 1, HID_ANY_ID
- 1, HID_ANY_ID
- 1}
310 static struct hid_driver mmm_driver
= {
312 .id_table
= mmm_devices
,
314 .remove
= mmm_remove
,
315 .input_mapping
= mmm_input_mapping
,
316 .input_mapped
= mmm_input_mapped
,
317 .usage_table
= mmm_grabbed_usages
,
321 static int __init
mmm_init(void)
323 return hid_register_driver(&mmm_driver
);
326 static void __exit
mmm_exit(void)
328 hid_unregister_driver(&mmm_driver
);
331 module_init(mmm_init
);
332 module_exit(mmm_exit
);