aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/bcm5974.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/bcm5974.c')
-rw-r--r--drivers/input/mouse/bcm5974.c47
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 */
100struct tp_header { 100enum 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 */
107struct tp_finger { 108struct 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 */
123struct 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 */
129struct bcm5974_param { 128struct 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)
276static int report_tp_state(struct bcm5974 *dev, int size) 277static 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