diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2010-09-10 18:08:57 +0200 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2010-09-10 18:08:57 +0200 |
| commit | 4fe7e36aaa8465dd058287ebe0b22fa2bee55fad (patch) | |
| tree | 5e8b26b9db1d723311002d4884789126efe8344c | |
| parent | 7c626e2ea2f7978e1ad478eb891c1a18e37a2fa6 (diff) | |
Update to maverick driver version
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
| -rw-r--r-- | usr/src/dkms_source_tree/hid-ntrig.c | 339 |
1 files changed, 229 insertions, 110 deletions
diff --git a/usr/src/dkms_source_tree/hid-ntrig.c b/usr/src/dkms_source_tree/hid-ntrig.c index 70a2ccd..635b44d 100644 --- a/usr/src/dkms_source_tree/hid-ntrig.c +++ b/usr/src/dkms_source_tree/hid-ntrig.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2010 Rafi Rubin | 4 | * Copyright (c) 2008-2010 Rafi Rubin |
| 5 | * Copyright (c) 2009-2010 Stephane Chatty | 5 | * Copyright (c) 2009-2010 Stephane Chatty |
| 6 | * Copyright (c) 2010 Canonical, Ltd. | ||
| 6 | * | 7 | * |
| 7 | */ | 8 | */ |
| 8 | 9 | ||
| @@ -24,25 +25,87 @@ | |||
| 24 | void usbhid_submit_report | 25 | void usbhid_submit_report |
| 25 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); | 26 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); |
| 26 | 27 | ||
| 28 | #define hid_to_usb_dev(hid_dev) \ | ||
| 29 | container_of(hid_dev->dev.parent->parent, struct usb_device, dev) | ||
| 30 | |||
| 27 | #define NTRIG_DUPLICATE_USAGES 0x001 | 31 | #define NTRIG_DUPLICATE_USAGES 0x001 |
| 28 | 32 | ||
| 29 | struct mt_data { | 33 | #define MAX_SLOTS 20 |
| 34 | #define MAX_EVENTS 120 | ||
| 35 | |||
| 36 | #define SN_MOVE_X 128 | ||
| 37 | #define SN_MOVE_Y 92 | ||
| 38 | #define SN_MAJOR 48 | ||
| 39 | |||
| 40 | #define HOLD_MIN 3 | ||
| 41 | #define HOLD_MED 7 | ||
| 42 | #define HOLD_MAX 10 | ||
| 43 | |||
| 44 | #define DIV_MIN 8 | ||
| 45 | #define DIV_MED 40 | ||
| 46 | #define DIV_MAX 100 | ||
| 47 | |||
| 48 | struct ntrig_contact { | ||
| 30 | int x, y, w, h; | 49 | int x, y, w, h; |
| 31 | int tipswitch; | ||
| 32 | int confidence; | ||
| 33 | int in_range; | ||
| 34 | int foot[4]; | ||
| 35 | unsigned int nfoot; | ||
| 36 | }; | 50 | }; |
| 37 | 51 | ||
| 38 | struct ntrig_data { | 52 | struct ntrig_data { |
| 39 | unsigned int id; | 53 | struct ntrig_contact row[MAX_SLOTS], col[MAX_SLOTS]; |
| 40 | struct mt_data data[16]; | 54 | int dmin, dmed, dmax; |
| 41 | int contactcount; | 55 | int nrow, ncol; |
| 56 | int index, nindex; | ||
| 57 | int nhold; | ||
| 42 | }; | 58 | }; |
| 43 | 59 | ||
| 44 | #define SN_MOVE 100 | 60 | |
| 45 | #define SN_SIZE 50 | 61 | /* |
| 62 | * This function converts the 4 byte raw firmware code into | ||
| 63 | * a string containing 5 comma separated numbers. | ||
| 64 | */ | ||
| 65 | static int ntrig_version_string(unsigned char *raw, char *buf) | ||
| 66 | { | ||
| 67 | __u8 a = (raw[1] & 0x0e) >> 1; | ||
| 68 | __u8 b = (raw[0] & 0x3c) >> 2; | ||
| 69 | __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5); | ||
| 70 | __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5); | ||
| 71 | __u8 e = raw[2] & 0x07; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * As yet unmapped bits: | ||
| 75 | * 0b11000000 0b11110001 0b00011000 0b00011000 | ||
| 76 | */ | ||
| 77 | |||
| 78 | return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); | ||
| 79 | } | ||
| 80 | |||
| 81 | static void ntrig_report_version(struct hid_device *hdev) | ||
| 82 | { | ||
| 83 | int ret; | ||
| 84 | char buf[20]; | ||
| 85 | struct usb_device *usb_dev = hid_to_usb_dev(hdev); | ||
| 86 | unsigned char *data = kmalloc(8, GFP_KERNEL); | ||
| 87 | |||
| 88 | if (!data) | ||
| 89 | goto err_free; | ||
| 90 | |||
| 91 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 92 | USB_REQ_CLEAR_FEATURE, | ||
| 93 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
| 94 | USB_DIR_IN, | ||
| 95 | 0x30c, 1, data, 8, | ||
| 96 | USB_CTRL_SET_TIMEOUT); | ||
| 97 | |||
| 98 | if (ret == 8) { | ||
| 99 | ret = ntrig_version_string(&data[2], buf); | ||
| 100 | |||
| 101 | dev_info(&hdev->dev, | ||
| 102 | "Firmware version: %s (%02x%02x %02x%02x)\n", | ||
| 103 | buf, data[2], data[3], data[4], data[5]); | ||
| 104 | } | ||
| 105 | |||
| 106 | err_free: | ||
| 107 | kfree(data); | ||
| 108 | } | ||
| 46 | 109 | ||
| 47 | /* | 110 | /* |
| 48 | * this driver is aimed at two firmware versions in circulation: | 111 | * this driver is aimed at two firmware versions in circulation: |
| @@ -54,7 +117,11 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 54 | struct hid_field *field, struct hid_usage *usage, | 117 | struct hid_field *field, struct hid_usage *usage, |
| 55 | unsigned long **bit, int *max) | 118 | unsigned long **bit, int *max) |
| 56 | { | 119 | { |
| 57 | int delta = field->logical_maximum - field->logical_minimum; | 120 | struct ntrig_data *nd = hid_get_drvdata(hdev); |
| 121 | struct input_dev *input = hi->input; | ||
| 122 | int f1 = field->logical_minimum; | ||
| 123 | int f2 = field->logical_maximum; | ||
| 124 | int df = f2 - f1; | ||
| 58 | 125 | ||
| 59 | /* No special mappings needed for the pen and single touch */ | 126 | /* No special mappings needed for the pen and single touch */ |
| 60 | if (field->physical) | 127 | if (field->physical) |
| @@ -64,28 +131,21 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 64 | case HID_UP_GENDESK: | 131 | case HID_UP_GENDESK: |
| 65 | switch (usage->hid) { | 132 | switch (usage->hid) { |
| 66 | case HID_GD_X: | 133 | case HID_GD_X: |
| 67 | hid_map_usage(hi, usage, bit, max, | 134 | hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_X); |
| 68 | EV_ABS, ABS_MT_POSITION_X); | 135 | input_set_abs_params(input, ABS_X, |
| 69 | input_set_abs_params(hi->input, ABS_MT_POSITION_X, | 136 | f1, f2, df / SN_MOVE_X, 0); |
| 70 | field->logical_minimum, | 137 | input_set_abs_params(input, ABS_MT_POSITION_X, |
| 71 | field->logical_maximum, | 138 | f1, f2, df / SN_MOVE_X, 0); |
| 72 | delta / SN_MOVE, 0); | 139 | nd->dmin = df / DIV_MIN; |
| 73 | input_set_abs_params(hi->input, ABS_X, | 140 | nd->dmed = df / DIV_MED; |
| 74 | field->logical_minimum, | 141 | nd->dmax = df / DIV_MAX; |
| 75 | field->logical_maximum, | ||
| 76 | delta / SN_MOVE, 0); | ||
| 77 | return 1; | 142 | return 1; |
| 78 | case HID_GD_Y: | 143 | case HID_GD_Y: |
| 79 | hid_map_usage(hi, usage, bit, max, | 144 | hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_Y); |
| 80 | EV_ABS, ABS_MT_POSITION_Y); | 145 | input_set_abs_params(input, ABS_Y, |
| 81 | input_set_abs_params(hi->input, ABS_MT_POSITION_Y, | 146 | f1, f2, df / SN_MOVE_Y, 0); |
| 82 | field->logical_minimum, | 147 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
| 83 | field->logical_maximum, | 148 | f1, f2, df / SN_MOVE_Y, 0); |
| 84 | delta / SN_MOVE, 0); | ||
| 85 | input_set_abs_params(hi->input, ABS_Y, | ||
| 86 | field->logical_minimum, | ||
| 87 | field->logical_maximum, | ||
| 88 | delta / SN_MOVE, 0); | ||
| 89 | return 1; | 149 | return 1; |
| 90 | } | 150 | } |
| 91 | return 0; | 151 | return 0; |
| @@ -97,26 +157,31 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 97 | case HID_DG_INPUTMODE: | 157 | case HID_DG_INPUTMODE: |
| 98 | case HID_DG_DEVICEINDEX: | 158 | case HID_DG_DEVICEINDEX: |
| 99 | case HID_DG_CONTACTMAX: | 159 | case HID_DG_CONTACTMAX: |
| 160 | case HID_DG_CONTACTCOUNT: | ||
| 161 | case HID_DG_INRANGE: | ||
| 162 | case HID_DG_CONFIDENCE: | ||
| 100 | return -1; | 163 | return -1; |
| 101 | 164 | ||
| 165 | case HID_DG_TIPSWITCH: | ||
| 166 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
| 167 | input_set_capability(input, EV_KEY, BTN_TOUCH); | ||
| 168 | return 1; | ||
| 169 | |||
| 102 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ | 170 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ |
| 103 | case HID_DG_WIDTH: | 171 | case HID_DG_WIDTH: |
| 104 | hid_map_usage(hi, usage, bit, max, | 172 | hid_map_usage(hi, usage, bit, max, |
| 105 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 173 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
| 106 | input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, | 174 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, |
| 107 | field->logical_minimum, | 175 | f1, f2, df / SN_MAJOR, 0); |
| 108 | field->logical_maximum, | ||
| 109 | delta / SN_SIZE, 0); | ||
| 110 | return 1; | 176 | return 1; |
| 111 | case HID_DG_HEIGHT: | 177 | case HID_DG_HEIGHT: |
| 112 | hid_map_usage(hi, usage, bit, max, | 178 | hid_map_usage(hi, usage, bit, max, |
| 113 | EV_ABS, ABS_MT_TOUCH_MINOR); | 179 | EV_ABS, ABS_MT_TOUCH_MINOR); |
| 114 | input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, | 180 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, |
| 115 | field->logical_minimum, | 181 | f1, f2, df / SN_MAJOR, 0); |
| 116 | field->logical_maximum, | 182 | input_set_abs_params(input, ABS_MT_ORIENTATION, |
| 117 | delta / SN_SIZE, 0); | 183 | 0, 1, 0, 0); |
| 118 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | 184 | input_set_events_per_packet(input, MAX_EVENTS); |
| 119 | 0, 1, 0, 0); | ||
| 120 | return 1; | 185 | return 1; |
| 121 | } | 186 | } |
| 122 | return 0; | 187 | return 0; |
| @@ -137,34 +202,123 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 137 | if (field->physical) | 202 | if (field->physical) |
| 138 | return 0; | 203 | return 0; |
| 139 | 204 | ||
| 140 | if (usage->type == EV_KEY || usage->type == EV_REL | 205 | /* tell hid-input to skip setup of these event types */ |
| 141 | || usage->type == EV_ABS) | 206 | if (usage->type == EV_KEY || usage->type == EV_ABS) |
| 142 | clear_bit(usage->code, *bit); | 207 | set_bit(usage->type, hi->input->evbit); |
| 208 | return -1; | ||
| 209 | } | ||
| 143 | 210 | ||
| 144 | return 0; | 211 | static bool copy_best_column(struct ntrig_data *nd, unsigned *used, int i) |
| 212 | { | ||
| 213 | int j, jbest = -1, d, dbest; | ||
| 214 | for (j = 0; j < nd->ncol; ++j) { | ||
| 215 | if (*used & (1 << j)) | ||
| 216 | continue; | ||
| 217 | d = abs(nd->row[i].x - nd->col[j].x) + | ||
| 218 | abs(nd->row[i].y - nd->col[j].y); | ||
| 219 | if (jbest < 0 || d < dbest) { | ||
| 220 | jbest = j; | ||
| 221 | dbest = d; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | if (jbest < 0) | ||
| 225 | return false; | ||
| 226 | *used |= (1 << jbest); | ||
| 227 | if (nd->nrow > 2) | ||
| 228 | nd->col[jbest].y = (nd->row[i].y + nd->col[jbest].y) >> 1; | ||
| 229 | nd->row[i] = nd->col[jbest]; | ||
| 230 | return true; | ||
| 231 | } | ||
| 232 | |||
| 233 | static bool copy_next_column(struct ntrig_data *nd, unsigned *used, int i) | ||
| 234 | { | ||
| 235 | int j; | ||
| 236 | for (j = 0; j < nd->ncol; ++j) { | ||
| 237 | if (*used & (1 << j)) | ||
| 238 | continue; | ||
| 239 | *used |= (1 << j); | ||
| 240 | nd->row[i] = nd->col[j]; | ||
| 241 | return true; | ||
| 242 | } | ||
| 243 | return false; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int ghost_distance(const struct ntrig_data *nd, int j) | ||
| 247 | { | ||
| 248 | int i, d, dbest = INT_MAX; | ||
| 249 | for (i = 0; i < nd->nrow; ++i) { | ||
| 250 | d = abs(nd->row[i].x - nd->col[j].x); | ||
| 251 | dbest = min(dbest, d); | ||
| 252 | d = abs(nd->row[i].y - nd->col[j].y); | ||
| 253 | dbest = min(dbest, d); | ||
| 254 | } | ||
| 255 | return dbest; | ||
| 256 | } | ||
| 257 | |||
| 258 | static void discard_ghosts(struct ntrig_data *nd, unsigned *used) | ||
| 259 | { | ||
| 260 | int j, d; | ||
| 261 | for (j = 0; j < nd->ncol; ++j) { | ||
| 262 | if (*used & (1 << j)) | ||
| 263 | continue; | ||
| 264 | d = ghost_distance(nd, j); | ||
| 265 | if ((nd->nhold < HOLD_MIN && d < nd->dmin) || | ||
| 266 | (nd->nhold < HOLD_MED && d < nd->dmed) || | ||
| 267 | (nd->nhold < HOLD_MAX && d < nd->dmax)) | ||
| 268 | *used |= (1 << j); | ||
| 269 | } | ||
| 145 | } | 270 | } |
| 146 | 271 | ||
| 147 | static void report_frame(struct input_dev *input, struct ntrig_data *nd) | 272 | static void report_frame(struct input_dev *input, struct ntrig_data *nd) |
| 148 | { | 273 | { |
| 149 | int i, count = nd->contactcount; | 274 | struct ntrig_contact *oldest = 0; |
| 150 | for (i = 0; i < count; i++) { | 275 | unsigned used = 0; |
| 151 | struct mt_data *p = &nd->data[i]; | 276 | int i; |
| 152 | if (i == 0) { | 277 | |
| 153 | input_report_key(input, BTN_TOUCH, 1); | 278 | if (nd->nrow < nd->ncol) { |
| 154 | input_report_abs(input, ABS_X, p->x); | 279 | for (i = 0; i < nd->nrow; ++i) |
| 155 | input_report_abs(input, ABS_Y, p->y); | 280 | copy_best_column(nd, &used, i); |
| 156 | } | 281 | if (nd->ncol > 2) |
| 157 | input_report_abs(input, ABS_MT_POSITION_X, p->x); | 282 | discard_ghosts(nd, &used); |
| 158 | input_report_abs(input, ABS_MT_POSITION_Y, p->y); | 283 | while (copy_next_column(nd, &used, i)) |
| 159 | input_report_abs(input, ABS_MT_TOUCH_MINOR, p->h); | 284 | i++; |
| 160 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, p->w); | 285 | nd->nrow = i; |
| 161 | input_report_abs(input, ABS_MT_ORIENTATION, p->w > p->h); | 286 | nd->nhold++; |
| 287 | } else if (nd->nrow > nd->ncol) { | ||
| 288 | for (i = 0; i < nd->ncol; ++i) | ||
| 289 | nd->row[i] = nd->col[i]; | ||
| 290 | nd->nrow = nd->ncol; | ||
| 291 | nd->nhold = 0; | ||
| 292 | } else { | ||
| 293 | unsigned used = 0; | ||
| 294 | for (i = 0; i < nd->nrow; ++i) | ||
| 295 | copy_best_column(nd, &used, i); | ||
| 296 | nd->nhold = 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | for (i = 0; i < nd->nrow; ++i) { | ||
| 300 | struct ntrig_contact *f = &nd->row[i]; | ||
| 301 | int wide = (f->w > f->h); | ||
| 302 | int major = max(f->w, f->h); | ||
| 303 | int minor = min(f->w, f->h); | ||
| 304 | if (!oldest) | ||
| 305 | oldest = f; | ||
| 306 | input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); | ||
| 307 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); | ||
| 308 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
| 309 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); | ||
| 310 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); | ||
| 162 | input_mt_sync(input); | 311 | input_mt_sync(input); |
| 163 | } | 312 | } |
| 164 | if (!count) { | 313 | |
| 165 | input_report_key(input, BTN_TOUCH, 0); | 314 | /* touchscreen emulation */ |
| 315 | if (oldest) { | ||
| 316 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
| 317 | input_event(input, EV_ABS, ABS_X, oldest->x); | ||
| 318 | input_event(input, EV_ABS, ABS_Y, oldest->y); | ||
| 319 | } else { | ||
| 320 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
| 166 | } | 321 | } |
| 167 | input_sync(input); | ||
| 168 | } | 322 | } |
| 169 | 323 | ||
| 170 | /* | 324 | /* |
| @@ -178,7 +332,6 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 178 | { | 332 | { |
| 179 | struct input_dev *input = field->hidinput->input; | 333 | struct input_dev *input = field->hidinput->input; |
| 180 | struct ntrig_data *nd = hid_get_drvdata(hid); | 334 | struct ntrig_data *nd = hid_get_drvdata(hid); |
| 181 | struct mt_data *p = &nd->data[nd->id]; | ||
| 182 | 335 | ||
| 183 | /* No special handling needed for the pen */ | 336 | /* No special handling needed for the pen */ |
| 184 | if (field->application == HID_DG_PEN) | 337 | if (field->application == HID_DG_PEN) |
| @@ -186,49 +339,26 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 186 | 339 | ||
| 187 | if (hid->claimed & HID_CLAIMED_INPUT) { | 340 | if (hid->claimed & HID_CLAIMED_INPUT) { |
| 188 | switch (usage->hid) { | 341 | switch (usage->hid) { |
| 189 | case HID_DG_INRANGE: | ||
| 190 | p->in_range = value; | ||
| 191 | break; | ||
| 192 | /* new mt packet */ | ||
| 193 | case 0xff000001: | ||
| 194 | p = &nd->data[nd->id = 0]; | ||
| 195 | memset(p, 0, sizeof(*p)); | ||
| 196 | break; | ||
| 197 | case HID_DG_TIPSWITCH: | 342 | case HID_DG_TIPSWITCH: |
| 198 | p->tipswitch = value; | 343 | nd->index = nd->nindex++; |
| 199 | break; | ||
| 200 | case HID_DG_CONFIDENCE: | ||
| 201 | p->confidence = value; | ||
| 202 | break; | ||
| 203 | case HID_DG_CONTACTID: | ||
| 204 | p = &nd->data[nd->id = value]; | ||
| 205 | memset(p, 0, sizeof(*p)); | ||
| 206 | break; | 344 | break; |
| 207 | case HID_GD_X: | 345 | case HID_GD_X: |
| 208 | p->x = value; | 346 | nd->col[nd->index].x = value; |
| 209 | break; | 347 | break; |
| 210 | case HID_GD_Y: | 348 | case HID_GD_Y: |
| 211 | p->y = value; | 349 | nd->col[nd->index].y = value; |
| 212 | break; | 350 | break; |
| 213 | case HID_DG_WIDTH: | 351 | case HID_DG_WIDTH: |
| 214 | p->w = value; | 352 | nd->col[nd->index].w = value; |
| 215 | break; | 353 | break; |
| 216 | case HID_DG_HEIGHT: | 354 | case HID_DG_HEIGHT: |
| 217 | p->h = value; | 355 | nd->col[nd->index].h = value; |
| 218 | break; | 356 | break; |
| 219 | case 0xff000002: | 357 | case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ |
| 220 | if (p->nfoot < 4) | 358 | nd->nindex = 0; |
| 221 | p->foot[p->nfoot++] = value; | 359 | nd->ncol = value; |
| 222 | else | ||
| 223 | printk(KERN_INFO "NTRIG: lots %d\n", value); | ||
| 224 | break; | ||
| 225 | case HID_DG_CONTACTCOUNT: | ||
| 226 | nd->contactcount = value; | ||
| 227 | report_frame(input, nd); | 360 | report_frame(input, nd); |
| 228 | break; | 361 | break; |
| 229 | |||
| 230 | default: | ||
| 231 | return 0; | ||
| 232 | } | 362 | } |
| 233 | } | 363 | } |
| 234 | 364 | ||
| @@ -249,7 +379,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 249 | 379 | ||
| 250 | if (id->driver_data & NTRIG_DUPLICATE_USAGES) | 380 | if (id->driver_data & NTRIG_DUPLICATE_USAGES) |
| 251 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | 381 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; |
| 252 | //hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
| 253 | 382 | ||
| 254 | nd = kzalloc(sizeof(struct ntrig_data), GFP_KERNEL); | 383 | nd = kzalloc(sizeof(struct ntrig_data), GFP_KERNEL); |
| 255 | if (!nd) { | 384 | if (!nd) { |
| @@ -274,7 +403,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 274 | 403 | ||
| 275 | list_for_each_entry(hidinput, &hdev->inputs, list) { | 404 | list_for_each_entry(hidinput, &hdev->inputs, list) { |
| 276 | if (hidinput->report->maxfield < 1) | 405 | if (hidinput->report->maxfield < 1) |
| 277 | |||
| 278 | continue; | 406 | continue; |
| 279 | 407 | ||
| 280 | input = hidinput->input; | 408 | input = hidinput->input; |
| @@ -283,18 +411,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 283 | input->name = "N-Trig Pen"; | 411 | input->name = "N-Trig Pen"; |
| 284 | break; | 412 | break; |
| 285 | case HID_DG_TOUCHSCREEN: | 413 | case HID_DG_TOUCHSCREEN: |
| 286 | /* These keys are redundant for fingers, clear them | ||
| 287 | * to prevent incorrect identification */ | ||
| 288 | __clear_bit(BTN_TOOL_PEN, input->keybit); | ||
| 289 | __clear_bit(BTN_TOOL_FINGER, input->keybit); | ||
| 290 | __clear_bit(BTN_0, input->keybit); | ||
| 291 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | ||
| 292 | /* | ||
| 293 | * The physical touchscreen (single touch) | ||
| 294 | * input has a value for physical, whereas | ||
| 295 | * the multitouch only has logical input | ||
| 296 | * fields. | ||
| 297 | */ | ||
| 298 | input->name = | 414 | input->name = |
| 299 | (hidinput->report->field[0] | 415 | (hidinput->report->field[0] |
| 300 | ->physical) ? | 416 | ->physical) ? |
| @@ -309,6 +425,9 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 309 | if (report) | 425 | if (report) |
| 310 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | 426 | usbhid_submit_report(hdev, report, USB_DIR_OUT); |
| 311 | 427 | ||
| 428 | ntrig_report_version(hdev); | ||
| 429 | |||
| 430 | |||
| 312 | return 0; | 431 | return 0; |
| 313 | err_free: | 432 | err_free: |
| 314 | kfree(nd); | 433 | kfree(nd); |
