aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-3m-pct.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index d2fda7848f59..3c380e1c5b60 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -2,6 +2,8 @@
2 * HID driver for 3M PCT multitouch panels 2 * HID driver for 3M PCT multitouch panels
3 * 3 *
4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> 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.
5 * 7 *
6 */ 8 */
7 9
@@ -25,16 +27,24 @@ MODULE_LICENSE("GPL");
25#include "hid-ids.h" 27#include "hid-ids.h"
26 28
27#define MAX_SLOTS 60 29#define MAX_SLOTS 60
28#define MAX_TRKID 59 30#define MAX_TRKID USHRT_MAX
31#define MAX_EVENTS 360
32
33/* estimated signal-to-noise ratios */
34#define SN_MOVE 2048
35#define SN_WIDTH 128
29 36
30struct mmm_finger { 37struct mmm_finger {
31 __s32 x, y, w, h; 38 __s32 x, y, w, h;
39 __u16 id;
32 __u8 rank; 40 __u8 rank;
41 bool prev_touch;
33 bool touch, valid; 42 bool touch, valid;
34}; 43};
35 44
36struct mmm_data { 45struct mmm_data {
37 struct mmm_finger f[MAX_SLOTS]; 46 struct mmm_finger f[MAX_SLOTS];
47 __u16 id;
38 __u8 curid, num; 48 __u8 curid, num;
39 __u8 nexp, nreal; 49 __u8 nexp, nreal;
40 bool touch, valid; 50 bool touch, valid;
@@ -44,6 +54,10 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
44 struct hid_field *field, struct hid_usage *usage, 54 struct hid_field *field, struct hid_usage *usage,
45 unsigned long **bit, int *max) 55 unsigned long **bit, int *max)
46{ 56{
57 int f1 = field->logical_minimum;
58 int f2 = field->logical_maximum;
59 int df = f2 - f1;
60
47 switch (usage->hid & HID_USAGE_PAGE) { 61 switch (usage->hid & HID_USAGE_PAGE) {
48 62
49 case HID_UP_BUTTON: 63 case HID_UP_BUTTON:
@@ -54,18 +68,20 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54 case HID_GD_X: 68 case HID_GD_X:
55 hid_map_usage(hi, usage, bit, max, 69 hid_map_usage(hi, usage, bit, max,
56 EV_ABS, ABS_MT_POSITION_X); 70 EV_ABS, ABS_MT_POSITION_X);
71 input_set_abs_params(hi->input, ABS_MT_POSITION_X,
72 f1, f2, df / SN_MOVE, 0);
57 /* touchscreen emulation */ 73 /* touchscreen emulation */
58 input_set_abs_params(hi->input, ABS_X, 74 input_set_abs_params(hi->input, ABS_X,
59 field->logical_minimum, 75 f1, f2, df / SN_MOVE, 0);
60 field->logical_maximum, 0, 0);
61 return 1; 76 return 1;
62 case HID_GD_Y: 77 case HID_GD_Y:
63 hid_map_usage(hi, usage, bit, max, 78 hid_map_usage(hi, usage, bit, max,
64 EV_ABS, ABS_MT_POSITION_Y); 79 EV_ABS, ABS_MT_POSITION_Y);
80 input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
81 f1, f2, df / SN_MOVE, 0);
65 /* touchscreen emulation */ 82 /* touchscreen emulation */
66 input_set_abs_params(hi->input, ABS_Y, 83 input_set_abs_params(hi->input, ABS_Y,
67 field->logical_minimum, 84 f1, f2, df / SN_MOVE, 0);
68 field->logical_maximum, 0, 0);
69 return 1; 85 return 1;
70 } 86 }
71 return 0; 87 return 0;
@@ -85,14 +101,19 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
85 case HID_DG_TIPSWITCH: 101 case HID_DG_TIPSWITCH:
86 /* touchscreen emulation */ 102 /* touchscreen emulation */
87 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 103 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
104 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
88 return 1; 105 return 1;
89 case HID_DG_WIDTH: 106 case HID_DG_WIDTH:
90 hid_map_usage(hi, usage, bit, max, 107 hid_map_usage(hi, usage, bit, max,
91 EV_ABS, ABS_MT_TOUCH_MAJOR); 108 EV_ABS, ABS_MT_TOUCH_MAJOR);
109 input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
110 f1, f2, df / SN_WIDTH, 0);
92 return 1; 111 return 1;
93 case HID_DG_HEIGHT: 112 case HID_DG_HEIGHT:
94 hid_map_usage(hi, usage, bit, max, 113 hid_map_usage(hi, usage, bit, max,
95 EV_ABS, ABS_MT_TOUCH_MINOR); 114 EV_ABS, ABS_MT_TOUCH_MINOR);
115 input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
116 f1, f2, df / SN_WIDTH, 0);
96 input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 117 input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
97 0, 1, 0, 0); 118 0, 1, 0, 0);
98 return 1; 119 return 1;
@@ -100,6 +121,11 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
100 field->logical_maximum = MAX_TRKID; 121 field->logical_maximum = MAX_TRKID;
101 hid_map_usage(hi, usage, bit, max, 122 hid_map_usage(hi, usage, bit, max,
102 EV_ABS, ABS_MT_TRACKING_ID); 123 EV_ABS, ABS_MT_TRACKING_ID);
124 input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
125 0, MAX_TRKID, 0, 0);
126 if (!hi->input->mt)
127 input_mt_create_slots(hi->input, MAX_SLOTS);
128 input_set_events_per_packet(hi->input, MAX_EVENTS);
103 return 1; 129 return 1;
104 } 130 }
105 /* let hid-input decide for the others */ 131 /* let hid-input decide for the others */
@@ -117,10 +143,10 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
117 struct hid_field *field, struct hid_usage *usage, 143 struct hid_field *field, struct hid_usage *usage,
118 unsigned long **bit, int *max) 144 unsigned long **bit, int *max)
119{ 145{
146 /* tell hid-input to skip setup of these event types */
120 if (usage->type == EV_KEY || usage->type == EV_ABS) 147 if (usage->type == EV_KEY || usage->type == EV_ABS)
121 clear_bit(usage->code, *bit); 148 set_bit(usage->type, hi->input->evbit);
122 149 return -1;
123 return 0;
124} 150}
125 151
126/* 152/*
@@ -141,10 +167,15 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
141 struct mmm_finger *f = &md->f[i]; 167 struct mmm_finger *f = &md->f[i];
142 if (!f->valid) { 168 if (!f->valid) {
143 /* this finger is just placeholder data, ignore */ 169 /* this finger is just placeholder data, ignore */
144 } else if (f->touch) { 170 continue;
171 }
172 input_mt_slot(input, i);
173 if (f->touch) {
145 /* this finger is on the screen */ 174 /* this finger is on the screen */
146 int wide = (f->w > f->h); 175 int wide = (f->w > f->h);
147 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); 176 if (!f->prev_touch)
177 f->id = md->id++;
178 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
148 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); 179 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
149 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); 180 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
150 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); 181 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
@@ -152,7 +183,6 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
152 wide ? f->w : f->h); 183 wide ? f->w : f->h);
153 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, 184 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
154 wide ? f->h : f->w); 185 wide ? f->h : f->w);
155 input_mt_sync(input);
156 /* 186 /*
157 * touchscreen emulation: maintain the age rank 187 * touchscreen emulation: maintain the age rank
158 * of this finger, decide if we have a press 188 * of this finger, decide if we have a press
@@ -181,7 +211,9 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
181 --(md->num); 211 --(md->num);
182 if (md->num == 0) 212 if (md->num == 0)
183 released = true; 213 released = true;
214 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
184 } 215 }
216 f->prev_touch = f->touch;
185 f->valid = 0; 217 f->valid = 0;
186 } 218 }
187 219