hid-logitech-wtp: refactoring for extensibility
[cascardo/linux.git] / drivers / hid / hid-logitech-wtp.c
1 /*
2  *  HID driver for Logitech Wireless Touchpad device
3  *
4  *  Copyright (c) 2011 Logitech (c)
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  * Should you need to contact me, the author, you can do so by e-mail send
23  * your message to Benjamin Tissoires <benjamin.tissoires at gmail com>
24  *
25  */
26
27 #include <linux/device.h>
28 #include <linux/hid.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/input/mt.h>
32
33 MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
34 MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");
35 MODULE_DESCRIPTION("Logitech Wireless Touchpad");
36 MODULE_LICENSE("GPL");
37
38 #include "hid-ids.h"
39 #include "hid-logitech-hidpp.h"
40
41 #define SOFTWARE_ID 0xB
42
43 #define ORIGIN_LOWER_LEFT 0x1
44 #define ORIGIN_LOWER_RIGHT 0x2
45 #define ORIGIN_UPPER_LEFT 0x3
46 #define ORIGIN_UPPER_RIGHT 0x4
47 #define ORIGIN_IS_HIGH(origin) ((origin - 1) & 2)
48 #define ORIGIN_IS_RIGHT(origin) ((origin - 1) & 1)
49
50 /* Converts a value in DPI to dots-per-millimeter */
51 #define DPI_TO_DPMM(dpi) (((dpi) * 5) / 127)
52
53 #define SLOT_COUNT 16
54
55 #define CONTACT_STATUS_RELEASED 0
56 #define CONTACT_STATUS_TOUCH 1
57 #define CONTACT_STATUS_HOVER 2
58 #define CONTACT_STATUS_RESERVED 3
59
60 #define BUTTON_LEFT 0
61 #define BUTTON_RIGHT 1
62 #define BUTTON_MIDDLE 2
63
64 #define BUTTON_LEFT_MASK (1 << BUTTON_LEFT)
65 #define BUTTON_RIGHT_MASK (1 << BUTTON_RIGHT)
66 #define BUTTON_MIDDLE_MASK (1 << BUTTON_MIDDLE)
67
68 #define ARRAYSIZE(array) (sizeof(array) / sizeof(*(array)))
69
70 /* Supported Devices */
71 static const struct hid_device_id wtp_devices[] = {
72         {HID_DEVICE(BUS_DJ, USB_VENDOR_ID_LOGITECH, UNIFYING_DEVICE_ID_WIRELESS_TOUCHPAD) },
73         {HID_DEVICE(BUS_DJ, USB_VENDOR_ID_LOGITECH, UNIFYING_DEVICE_ID_WIRELESS_TOUCHPAD_T650) },
74         {HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_WIRELESS_TOUCHPAD_T651) },
75         { }
76 };
77 MODULE_DEVICE_TABLE(hid, wtp_devices);
78
79
80 /* This struct represents a finger including location, pressure and
81         its status */
82 struct wtp_event_finger {
83         u8 status;
84         u16 abs_x;
85         u16 abs_y;
86         u8 pressure;
87         u8 id;
88 };
89
90 /* This struct represents a touch data message from a touchpad  */
91 struct wtp_event {
92         struct wtp_event_finger fingers[4];
93
94         /* bitmask of button states. 1=down, 0=up. */
95         u8 buttons;
96
97         /* bitmask of buttons included within this event */
98         u8 has_buttons;
99
100         /* true if this event includes finger data */
101         bool has_abs:1;
102
103         /* false if there are events following with more data,
104                 true if this is the last one */
105         bool end_of_frame:1;
106 };
107
108 /* Struct describing the touch devices axis properties */
109 struct wtp_device_info {
110         u16 abs_max_x;
111         u16 abs_res_x;
112
113         u16 abs_max_y;
114         u16 abs_res_y;
115
116         u8 origin;
117
118         u16 abs_min_pressure;
119         u16 abs_max_pressure;
120
121         u8 max_contacts;
122 };
123
124 struct wtp_data;
125
126 /* Struct storing feature-specific information. Each feature_id
127         has methods assigned that process messages from this feature. */
128 struct wtp_feature {
129         u16 id;
130         u8 index;
131         u8 event_format;
132         int (*init)(struct hidpp_device *);
133         int (*probe)(struct hidpp_device *, struct wtp_device_info *);
134         int (*parse_feature_event)(struct wtp_data *, struct hidpp_report *,
135                         struct wtp_event *);
136         int (*parse_other_event)(struct wtp_data *, struct hidpp_report *,
137                         struct wtp_event *);
138 };
139
140 /* Structure containing device data */
141 struct wtp_data {
142         struct input_dev *input;
143
144         struct wtp_device_info info;
145
146         /* the touch feature supported by this device */
147         struct wtp_feature feature;
148
149         /* keep track of which buttons are down */
150         u8 buttons;
151
152         /* For assigning tracking IDs for MT-B protocol. */
153         u16 next_tracking_id;
154         u16 current_slots_used;  /* slots = device IDs. Bitmask. */
155         u16 prev_slots_used;  /* slots = device IDs. Bitmask. */
156
157         u8 fingers_seen_this_frame;
158 };
159
160 /* Bit Operations Helper */
161 static u16 make_u16(u8 high, u8 low)
162 {
163         return (high << 8) | low;
164 }
165 static u8 low_nib(u8 val)
166 {
167         return val & 0xf;
168 }
169 static u8 high_nib(u8 val)
170 {
171         return val >> 4;
172 }
173 static bool get_bit(u8 mask, u8 idx)
174 {
175         return mask & (1 << idx);
176 }
177
178 /*
179         Helper methods for parsing mouse events. Some devices
180         use mouse events to report buttons.
181 */
182
183 #define GENERIC_EVENT_MOUSE 0x02
184
185 static void generic_parse_mouse_button(struct hidpp_report *report,
186                 struct wtp_event *event) {
187         u8 *raw = (u8 *)report;
188         event->has_buttons = BUTTON_LEFT_MASK | BUTTON_RIGHT_MASK |
189                 BUTTON_MIDDLE_MASK;
190         event->buttons = raw[1] & event->has_buttons;
191 }
192
193 /*
194         TouchPadRawXY (TPRXY) Feature
195 */
196
197 #define TPRXY_FEATURE 0x6100
198 #define TPRXY_CMD_GET_TOUCHPAD_INFO (0x00 & SOFTWARE_ID)
199 #define TPRXY_CMD_GET_RAW_REPORT_STATE (0x10 & SOFTWARE_ID)
200 #define TPRXY_CMD_SET_RAW_REPORT_STATE (0x20 & SOFTWARE_ID)
201 #define TPRXY_EVENT_TOUCHPAD_RAW_TOUCH_POINTS 0x00
202
203 #define TPRXY_FORMAT_RAW 0x01
204 #define TPRXY_FORMAT_MOUSE_EXTENDED 0x02
205
206 #define TPRXY_DEFAULT_RES 1000  /* DPI */
207
208 #define TPRXY_SLOTS_PER_FRAME 2
209
210 /* Initialize TouchPadRawXY feature:
211         Set touchpad into raw mode (except for T651, which allows for raw touch
212         data appended to mouse events). */
213 static int tprxy_init(struct hidpp_device *hidpp_dev)
214 {
215         struct wtp_data *fd = hidpp_dev->driver_data;
216         struct hidpp_report response;
217         int ret;
218         u8 params;
219
220         dbg_hid("%s\n", __func__);
221
222         if (hidpp_dev->hid_dev->product ==
223                         USB_DEVICE_ID_WIRELESS_TOUCHPAD_T651) {
224                 params = 0x4; /* enhanced sensitivity */
225                 fd->feature.event_format = TPRXY_FORMAT_MOUSE_EXTENDED;
226         } else {
227                 params = 0x5; /* enhanced sensitivity + raw */
228                 fd->feature.event_format = TPRXY_FORMAT_RAW;
229         }
230
231         ret = hidpp_send_fap_command_sync(hidpp_dev, fd->feature.index,
232                 TPRXY_CMD_SET_RAW_REPORT_STATE, &params, 1, &response);
233
234         return -ret;
235 }
236
237 /* Probe TouchPadRawXY feature */
238 static int tprxy_probe(struct hidpp_device *hidpp_dev,
239                 struct wtp_device_info *info)
240 {
241         struct wtp_data *fd = hidpp_dev->driver_data;
242         struct hidpp_report response;
243         int ret;
244         u16 res;
245         u8 *params = (u8 *)response.fap.params;
246
247         dbg_hid("%s\n", __func__);
248
249         ret = hidpp_send_fap_command_sync(hidpp_dev, fd->feature.index,
250                         TPRXY_CMD_GET_TOUCHPAD_INFO, NULL, 0, &response);
251
252         if (ret)
253                 return -ret;
254
255         info->abs_max_x = make_u16(params[0], params[1]);
256         info->abs_max_y = make_u16(params[2], params[3]);
257         info->abs_max_pressure = params[5];
258         info->max_contacts = params[7];
259         info->origin = params[8];
260
261         res = make_u16(params[13], params[14]);
262         if (!res)
263                 res = TPRXY_DEFAULT_RES;
264         info->abs_res_x = res;
265         info->abs_res_y = res;
266         return ret;
267 }
268
269 /* Parse other events while using TouchPadRawXY feature:
270         Mouse events might still be received in the following cases:
271         - Touchpad with separate buttons send mouse events on click
272         - Touchpad using extended mouse events send touch data as
273                 mouse events */
274 static int tprxy_parse_other_event(struct wtp_data *wtp,
275                 struct hidpp_report *report,
276                 struct wtp_event *event) {
277         int i;
278         u8 *buf = &report->rap.params[0];
279
280         dbg_hid("%s\n", __func__);
281
282         if (report->report_id != GENERIC_EVENT_MOUSE)
283                 return -1;
284
285         generic_parse_mouse_button(report, event);
286
287         if (wtp->feature.event_format != TPRXY_FORMAT_MOUSE_EXTENDED)
288                 return 0;
289
290         for (i = 0; i < TPRXY_SLOTS_PER_FRAME; ++i) {
291                 struct wtp_event_finger *finger = &event->fingers[i];
292                 u8 *raw = buf + (5 + i * 6);
293                 u8 width = low_nib(raw[5]);
294                 u8 height = high_nib(raw[5]);
295
296                 finger->pressure = (width * width + height * height) / 2;
297                 finger->status = finger->pressure > 0;
298                 finger->abs_x = make_u16(raw[2], raw[1]);
299                 finger->abs_y = make_u16(raw[4], raw[3]);
300                 finger->id = raw[0];
301         }
302         event->end_of_frame = !get_bit(buf[3], 7);
303         event->has_abs = true;
304
305         return 0;
306 }
307
308 /* Parse TouchPadRawXY events */
309 static int tprxy_parse_feature_event(struct wtp_data *wtp,
310                 struct hidpp_report *report,
311                 struct wtp_event *event) {
312         int i;
313         u8 *buf = &report->rap.params[0];
314         u8 fingers_this_frame;
315
316         dbg_hid("%s\n", __func__);
317
318         if (wtp->feature.event_format != TPRXY_FORMAT_RAW)
319                 return -1;
320
321         for (i = 0; i < TPRXY_SLOTS_PER_FRAME; ++i) {
322                 u8 *raw = buf + (2 + i * 7);
323                 event->fingers[i].status = raw[0];
324                 event->fingers[i].abs_x = make_u16(raw[0] & 0x3f, raw[1]);
325                 event->fingers[i].abs_y = make_u16(raw[2] & 0x3f, raw[3]);
326                 event->fingers[i].pressure = raw[5];
327                 event->fingers[i].id = high_nib(raw[6]);
328         }
329         event->buttons = get_bit(buf[8], 2);
330         event->end_of_frame = get_bit(buf[8], 0);
331
332         /* For single event frames, the end of frame flag is implied. */
333         fingers_this_frame = low_nib(buf[15]);
334         if (fingers_this_frame <= TPRXY_SLOTS_PER_FRAME)
335                 event->end_of_frame = true;
336
337         event->has_abs = true;
338         event->has_buttons = 0x1;
339         return 0;
340 }
341
342 /* Array enumerating all supported hidpp features */
343 static struct wtp_feature wtp_supported_features[] = {
344         {
345                 TPRXY_FEATURE,
346                 0, 0,
347                 &tprxy_init,
348                 &tprxy_probe,
349                 &tprxy_parse_feature_event,
350                 &tprxy_parse_other_event
351         },
352         { }
353 };
354
355 /*
356         Common code for all devices/features
357 */
358
359 /* Report a single finger as input_events. This method will also assign
360         tracking ids to each new finger. */
361 static void wtp_process_event_finger(struct wtp_data *fd,
362         struct wtp_event_finger *finger)
363 {
364         int slot = finger->id - 1;
365
366         bool new_finger = !(fd->prev_slots_used & (1 << slot));
367         fd->current_slots_used |= 1 << slot;
368         fd->fingers_seen_this_frame++;
369
370         dbg_hid("Finger %d: (%d,%d,%d) s=%d\n",
371                 slot,
372                 finger->abs_x,
373                 finger->abs_y,
374                 finger->pressure,
375                 finger->status);
376
377         input_mt_slot(fd->input, slot);
378         if (new_finger) {
379                 input_event(fd->input, EV_ABS, ABS_MT_TRACKING_ID,
380                                 fd->next_tracking_id++);
381                 if (fd->next_tracking_id == 0xffff)
382                         fd->next_tracking_id = 1;
383         }
384         input_mt_report_slot_state(fd->input, MT_TOOL_FINGER, 1);
385         input_event(fd->input, EV_ABS, ABS_MT_POSITION_X,
386                         ORIGIN_IS_RIGHT(fd->info.origin) ?
387                         fd->info.abs_max_x - finger->abs_x : finger->abs_x);
388         input_event(fd->input, EV_ABS, ABS_MT_POSITION_Y,
389                         ORIGIN_IS_HIGH(fd->info.origin) ?
390                         finger->abs_y : fd->info.abs_max_y - finger->abs_y);
391         input_event(fd->input, EV_ABS, ABS_MT_PRESSURE, finger->pressure);
392 }
393
394 /* Report an event as input_events */
395 static int wtp_process_event(struct hidpp_device *hidpp_dev,
396                                 struct wtp_event *event)
397 {
398         struct wtp_data *fd = (struct wtp_data *)hidpp_dev->driver_data;
399
400         int i;
401         if (!hidpp_dev->initialized)
402                 return -1;
403
404         /* report buttons */
405         if (event->has_buttons != 0) {
406                 fd->buttons &= ~event->has_buttons;
407                 fd->buttons |= event->buttons & event->has_buttons;
408                 dbg_hid("Button: 0x%x\n", fd->buttons);
409                 input_report_key(fd->input, BTN_LEFT,
410                         get_bit(fd->buttons, BUTTON_LEFT));
411                 input_report_key(fd->input, BTN_RIGHT,
412                         get_bit(fd->buttons, BUTTON_RIGHT));
413                 input_report_key(fd->input, BTN_MIDDLE,
414                         get_bit(fd->buttons, BUTTON_MIDDLE));
415         }
416
417         /* sync now if there is no touch data following */
418         if (!event->has_abs) {
419                 input_sync(fd->input);
420                 return 1; /* we successfully consumed the event */
421         }
422
423         /* update fingers */
424         for (i = 0; i < ARRAYSIZE(event->fingers); i++) {
425                 if (event->fingers[i].status != CONTACT_STATUS_RELEASED)
426                         wtp_process_event_finger(fd, &event->fingers[i]);
427         }
428
429         /* update released fingers and sync */
430         if (event->end_of_frame) {
431                 for (i = 0; i < SLOT_COUNT; i++) {
432                         __u16 slot_mask = 1 << i;
433                         bool released = (fd->prev_slots_used & slot_mask) &&
434                                 !(fd->current_slots_used & slot_mask);
435                         if (!released)
436                                 continue;
437                         dbg_hid("Finger %d: released\n", i);
438                         input_mt_slot(fd->input, i);
439                         input_event(fd->input, EV_ABS, ABS_MT_TRACKING_ID, -1);
440                         input_mt_report_slot_state(fd->input, MT_TOOL_FINGER, 0);
441                 }
442                 input_mt_report_pointer_emulation(fd->input, true);
443
444                 input_sync(fd->input);
445
446                 fd->prev_slots_used = fd->current_slots_used;
447                 fd->current_slots_used = 0;
448                 fd->fingers_seen_this_frame = 0;
449         }
450         return 1; /* we successfully consumed the event */
451 }
452
453 /* dispatches events to feature event parsing methods and reports
454         the result as input_events */
455 static int wtp_hidpp_event_handler(struct hidpp_device *hidpp_device,
456                 struct hidpp_report *report)
457 {
458         struct wtp_event event;
459         struct wtp_data *fd = (struct wtp_data *)hidpp_device->driver_data;
460         int ret;
461
462         memset(&event, 0, sizeof(event));
463
464         if (report->report_id == REPORT_ID_HIDPP_LONG &&
465                         report->rap.sub_id == fd->feature.index) {
466                 ret = (*fd->feature.parse_feature_event)(fd, report, &event);
467         } else {
468                 ret = (*fd->feature.parse_other_event)(fd, report, &event);
469         }
470         if (ret)
471                 return ret;
472         return wtp_process_event(hidpp_device, &event);
473 }
474
475 /* report device info */
476 static int wtp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
477                 struct hid_field *field, struct hid_usage *usage,
478                 unsigned long **bit, int *max)
479 {
480         struct hidpp_device *hidpp_dev = hid_get_drvdata(hdev);
481         struct wtp_data *fd = (struct wtp_data *)hidpp_dev->driver_data;
482         struct input_dev *input = hi->input;
483         int res_x_mm, res_y_mm;
484
485         dbg_hid("%s:\n", __func__);
486
487         if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
488                 return -1;
489
490         fd->input = hi->input;
491
492         __set_bit(BTN_TOUCH, input->keybit);
493         __set_bit(BTN_TOOL_FINGER, input->keybit);
494         __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
495         __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
496         __set_bit(BTN_TOOL_QUADTAP, input->keybit);
497         __set_bit(BTN_TOOL_QUINTTAP, input->keybit);
498
499         __set_bit(EV_ABS, input->evbit);
500
501         input_mt_init_slots(input, SLOT_COUNT);
502
503         input_set_capability(input, EV_KEY, BTN_TOUCH);
504
505         input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0);
506         input_set_abs_params(input, ABS_MT_POSITION_X,
507                         0, fd->info.abs_max_x, 0, 0);
508         input_set_abs_params(input, ABS_MT_POSITION_Y,
509                         0, fd->info.abs_max_y, 0, 0);
510         input_set_abs_params(input, ABS_X, 0, fd->info.abs_max_x, 0, 0);
511         input_set_abs_params(input, ABS_Y, 0, fd->info.abs_max_y, 0, 0);
512
513         res_x_mm = DPI_TO_DPMM(fd->info.abs_res_x);
514         res_y_mm = DPI_TO_DPMM(fd->info.abs_res_y);
515
516         input_abs_set_res(input, ABS_MT_POSITION_X, res_x_mm);
517         input_abs_set_res(input, ABS_MT_POSITION_Y, res_y_mm);
518         input_abs_set_res(input, ABS_X, res_x_mm);
519         input_abs_set_res(input, ABS_Y, res_y_mm);
520
521         return 0;
522 }
523
524 /* probes for all supported features and uses the first available
525         to initialize the device */
526 static int wtp_init_feature(struct hidpp_device *hidpp_device)
527 {
528         struct wtp_feature *feature = wtp_supported_features;
529         struct wtp_data *fd = (struct wtp_data *)hidpp_device->driver_data;
530         dbg_hid("%s\n", __func__);
531
532         while (feature->id) {
533                 int ret;
534                 dbg_hid("Probing feature 0x%x\n", feature->id);
535                 ret = hidpp_get_hidpp2_feature_index(hidpp_device,
536                                                 SOFTWARE_ID,
537                                                 feature->id,
538                                                 &feature->index);
539                 if (ret)
540                         return -ENODEV;
541
542                 if (feature->index != 0) {
543                         dbg_hid("Feature found at index: %d\n", feature->index);
544                         fd->feature = *feature;
545                         ret = (*fd->feature.probe)(hidpp_device, &fd->info);
546                         if (ret)
547                                 return ret;
548                         ret = (*fd->feature.init)(hidpp_device);
549                         return ret;
550                 } else {
551                         dbg_hid("unavailable feature 0x%x\n", feature->id);
552                 }
553                 ++feature;
554         }
555         /* no supported feature found on this device */
556         return -ENODEV;
557 }
558
559 static void wtp_connect_change(struct hidpp_device *hidpp_dev, bool connected)
560 {
561         struct wtp_data *fd = (struct wtp_data *)hidpp_dev->driver_data;
562         dbg_hid("%s: connected:%d\n", __func__, connected);
563         if (connected && hidpp_dev->initialized && fd->feature.init)
564                 (*fd->feature.init)(hidpp_dev);
565 }
566
567 static int wtp_probe(struct hid_device *hdev, const struct hid_device_id *id)
568 {
569         struct wtp_data *fd = NULL;
570         struct hidpp_device *hidpp_device = NULL;
571         int ret;
572         struct hidpp_report response;
573
574         dbg_hid("%s\n", __func__);
575
576         hidpp_device = kzalloc(sizeof(struct hidpp_device), GFP_KERNEL);
577         if (!hidpp_device) {
578                 hid_err(hdev, "cannot allocate hidpp_device\n");
579                 ret = -ENOMEM;
580                 goto hidpp_alloc_failed;
581         }
582
583         fd = kzalloc(sizeof(struct wtp_data), GFP_KERNEL);
584         if (!fd) {
585                 hid_err(hdev, "cannot allocate wtp Touch data\n");
586                 ret = -ENOMEM;
587                 goto fd_alloc_failed;
588         }
589         fd->next_tracking_id = 1;
590
591         hidpp_device->driver_data = (void *)fd;
592         hid_set_drvdata(hdev, hidpp_device);
593
594         hidpp_device->connect_change = wtp_connect_change;
595
596         ret = hid_parse(hdev);
597         if (ret) {
598                 ret = -ENODEV;
599                 goto failed;
600         }
601
602         ret = hidpp_init(hidpp_device, hdev);
603         if (ret) {
604                 ret = -ENODEV;
605                 goto failed;
606         }
607
608         hid_device_io_start(hdev);
609
610         /* Get hid++ version number */
611         ret = hidpp_send_hidpp2_sync(hidpp_device, REPORT_ID_HIDPP_LONG,
612                                         0, 1,
613                                         SOFTWARE_ID,
614                                         NULL, 0, &response);
615         if (ret) {
616                 dbg_hid("send root cmd returned: %d", ret);
617                 ret = -ENODEV;
618                 goto failed;
619         }
620
621         dbg_hid("HID++ version: %d.%d\n", response.rap.params[0],
622                 response.rap.params[1]);
623
624         /* TODO(adlr): Consider requiring a specific/minimum HID++ version. */
625
626         ret = wtp_init_feature(hidpp_device);
627         if (ret) {
628                 dbg_hid("wtp_init_feature returned: %d", ret);
629                 ret = -ENODEV;
630                 goto failed;
631         }
632
633         hid_device_io_stop(hdev);
634
635         hidpp_device->raw_event = wtp_hidpp_event_handler;
636
637         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
638         if (ret) {
639                 ret = -ENODEV;
640                 goto failed;
641         }
642
643         return 0;
644
645 failed:
646         hid_set_drvdata(hdev, NULL);
647         kfree(fd);
648 fd_alloc_failed:
649         kfree(hidpp_device);
650 hidpp_alloc_failed:
651         return ret;
652 }
653
654 static void wtp_remove(struct hid_device *hdev)
655 {
656         struct hidpp_device *hidpp_dev = hid_get_drvdata(hdev);
657         struct wtp_data *fd = hidpp_dev->driver_data;
658         dbg_hid("%s\n", __func__);
659         hid_hw_stop(hdev);
660         hidpp_remove(hidpp_dev);
661         kfree(fd);
662         kfree(hidpp_dev);
663         hid_set_drvdata(hdev, NULL);
664 }
665
666 static struct hid_driver wtp_driver = {
667         .name = "wtp-touch",
668         .id_table = wtp_devices,
669         .probe = wtp_probe,
670         .remove = wtp_remove,
671         .input_mapping = wtp_input_mapping,
672         .raw_event = hidpp_raw_event,
673 };
674
675 static int __init wtp_init(void)
676 {
677         return hid_register_driver(&wtp_driver);
678 }
679
680 static void __exit wtp_exit(void)
681 {
682         hid_unregister_driver(&wtp_driver);
683 }
684
685 module_init(wtp_init);
686 module_exit(wtp_exit);