diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2998a6ac9ae4..bda873393b0d 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -96,14 +96,15 @@ struct bt_data { | |||
96 | u8 rel_y; /* relative y coordinate */ | 96 | u8 rel_y; /* relative y coordinate */ |
97 | }; | 97 | }; |
98 | 98 | ||
99 | /* trackpad header structure */ | 99 | /* trackpad header types */ |
100 | struct tp_header { | 100 | enum tp_type { |
101 | u8 unknown1[16]; /* constants, timers, etc */ | 101 | TYPE1 /* plain trackpad */ |
102 | u8 fingers; /* number of fingers on trackpad */ | ||
103 | u8 unknown2[9]; /* constants, timers, etc */ | ||
104 | }; | 102 | }; |
105 | 103 | ||
106 | /* trackpad finger structure */ | 104 | /* trackpad finger data offsets, le16-aligned */ |
105 | #define FINGER_TYPE1 (13 * sizeof(__le16)) | ||
106 | |||
107 | /* trackpad finger structure, le16-aligned */ | ||
107 | struct tp_finger { | 108 | struct tp_finger { |
108 | __le16 origin; /* zero when switching track finger */ | 109 | __le16 origin; /* zero when switching track finger */ |
109 | __le16 abs_x; /* absolute x coodinate */ | 110 | __le16 abs_x; /* absolute x coodinate */ |
@@ -117,13 +118,11 @@ struct tp_finger { | |||
117 | __le16 force_minor; /* trackpad force, minor axis? */ | 118 | __le16 force_minor; /* trackpad force, minor axis? */ |
118 | __le16 unused[3]; /* zeros */ | 119 | __le16 unused[3]; /* zeros */ |
119 | __le16 multi; /* one finger: varies, more fingers: constant */ | 120 | __le16 multi; /* one finger: varies, more fingers: constant */ |
120 | }; | 121 | } __attribute__((packed,aligned(2))); |
121 | 122 | ||
122 | /* trackpad data structure, empirically at least ten fingers */ | 123 | /* trackpad finger data size, empirically at least ten fingers */ |
123 | struct tp_data { | 124 | #define SIZEOF_FINGER sizeof(struct tp_finger) |
124 | struct tp_header header; | 125 | #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) |
125 | struct tp_finger finger[16]; | ||
126 | }; | ||
127 | 126 | ||
128 | /* device-specific parameters */ | 127 | /* device-specific parameters */ |
129 | struct bcm5974_param { | 128 | struct bcm5974_param { |
@@ -139,6 +138,8 @@ struct bcm5974_config { | |||
139 | int bt_ep; /* the endpoint of the button interface */ | 138 | int bt_ep; /* the endpoint of the button interface */ |
140 | int bt_datalen; /* data length of the button interface */ | 139 | int bt_datalen; /* data length of the button interface */ |
141 | int tp_ep; /* the endpoint of the trackpad interface */ | 140 | int tp_ep; /* the endpoint of the trackpad interface */ |
141 | enum tp_type tp_type; /* type of trackpad interface */ | ||
142 | int tp_offset; /* offset to trackpad finger data */ | ||
142 | int tp_datalen; /* data length of the trackpad interface */ | 143 | int tp_datalen; /* data length of the trackpad interface */ |
143 | struct bcm5974_param p; /* finger pressure limits */ | 144 | struct bcm5974_param p; /* finger pressure limits */ |
144 | struct bcm5974_param w; /* finger width limits */ | 145 | struct bcm5974_param w; /* finger width limits */ |
@@ -158,7 +159,7 @@ struct bcm5974 { | |||
158 | struct urb *bt_urb; /* button usb request block */ | 159 | struct urb *bt_urb; /* button usb request block */ |
159 | struct bt_data *bt_data; /* button transferred data */ | 160 | struct bt_data *bt_data; /* button transferred data */ |
160 | struct urb *tp_urb; /* trackpad usb request block */ | 161 | struct urb *tp_urb; /* trackpad usb request block */ |
161 | struct tp_data *tp_data; /* trackpad transferred data */ | 162 | u8 *tp_data; /* trackpad transferred data */ |
162 | int fingers; /* number of fingers on trackpad */ | 163 | int fingers; /* number of fingers on trackpad */ |
163 | }; | 164 | }; |
164 | 165 | ||
@@ -184,7 +185,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
184 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, | 185 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, |
185 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, | 186 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, |
186 | 0x84, sizeof(struct bt_data), | 187 | 0x84, sizeof(struct bt_data), |
187 | 0x81, sizeof(struct tp_data), | 188 | 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, |
188 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | 189 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
189 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | 190 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
190 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, | 191 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, |
@@ -195,7 +196,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
195 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, | 196 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, |
196 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, | 197 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, |
197 | 0x84, sizeof(struct bt_data), | 198 | 0x84, sizeof(struct bt_data), |
198 | 0x81, sizeof(struct tp_data), | 199 | 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, |
199 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | 200 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
200 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | 201 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
201 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, | 202 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, |
@@ -276,18 +277,21 @@ static int report_bt_state(struct bcm5974 *dev, int size) | |||
276 | static int report_tp_state(struct bcm5974 *dev, int size) | 277 | static int report_tp_state(struct bcm5974 *dev, int size) |
277 | { | 278 | { |
278 | const struct bcm5974_config *c = &dev->cfg; | 279 | const struct bcm5974_config *c = &dev->cfg; |
279 | const struct tp_finger *f = dev->tp_data->finger; | 280 | const struct tp_finger *f; |
280 | struct input_dev *input = dev->input; | 281 | struct input_dev *input = dev->input; |
281 | const int fingers = (size - 26) / 28; | 282 | int raw_p, raw_w, raw_x, raw_y, raw_n; |
282 | int raw_p, raw_w, raw_x, raw_y; | ||
283 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; | 283 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; |
284 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | 284 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; |
285 | 285 | ||
286 | if (size < 26 || (size - 26) % 28 != 0) | 286 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
287 | return -EIO; | 287 | return -EIO; |
288 | 288 | ||
289 | /* finger data, le16-aligned */ | ||
290 | f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); | ||
291 | raw_n = (size - c->tp_offset) / SIZEOF_FINGER; | ||
292 | |||
289 | /* always track the first finger; when detached, start over */ | 293 | /* always track the first finger; when detached, start over */ |
290 | if (fingers) { | 294 | if (raw_n) { |
291 | raw_p = raw2int(f->force_major); | 295 | raw_p = raw2int(f->force_major); |
292 | raw_w = raw2int(f->size_major); | 296 | raw_w = raw2int(f->size_major); |
293 | raw_x = raw2int(f->abs_x); | 297 | raw_x = raw2int(f->abs_x); |
@@ -307,12 +311,13 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
307 | abs_w = int2bound(&c->w, raw_w); | 311 | abs_w = int2bound(&c->w, raw_w); |
308 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | 312 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); |
309 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | 313 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); |
310 | for (; f != dev->tp_data->finger + fingers; f++) { | 314 | while (raw_n--) { |
311 | ptest = int2bound(&c->p, raw2int(f->force_major)); | 315 | ptest = int2bound(&c->p, raw2int(f->force_major)); |
312 | if (ptest > PRESSURE_LOW) | 316 | if (ptest > PRESSURE_LOW) |
313 | nmax++; | 317 | nmax++; |
314 | if (ptest > PRESSURE_HIGH) | 318 | if (ptest > PRESSURE_HIGH) |
315 | nmin++; | 319 | nmin++; |
320 | f++; | ||
316 | } | 321 | } |
317 | } | 322 | } |
318 | 323 | ||