ax88796: fix codingstyle and checkpatch warnings
[pandora-kernel.git] / drivers / hid / hid-roccat-koneplus.c
1 /*
2  * Roccat Kone[+] driver for Linux
3  *
4  * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  */
13
14 /*
15  * Roccat Kone[+] is an updated/improved version of the Kone with more memory
16  * and functionality and without the non-standard behaviours the Kone had.
17  */
18
19 #include <linux/device.h>
20 #include <linux/input.h>
21 #include <linux/hid.h>
22 #include <linux/usb.h>
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include "hid-ids.h"
26 #include "hid-roccat.h"
27 #include "hid-roccat-koneplus.h"
28
29 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
30
31 static struct class *koneplus_class;
32
33 static void koneplus_profile_activated(struct koneplus_device *koneplus,
34                 uint new_profile)
35 {
36         koneplus->actual_profile = new_profile;
37 }
38
39 static int koneplus_send_control(struct usb_device *usb_dev, uint value,
40                 enum koneplus_control_requests request)
41 {
42         int len;
43         struct koneplus_control *control;
44
45         if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
46                         request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
47                         value > 4)
48                 return -EINVAL;
49
50         control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
51         if (!control)
52                 return -ENOMEM;
53
54         control->command = KONEPLUS_COMMAND_CONTROL;
55         control->value = value;
56         control->request = request;
57
58         len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
59                         USB_REQ_SET_CONFIGURATION,
60                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
61                         KONEPLUS_USB_COMMAND_CONTROL, 0, control,
62                         sizeof(struct koneplus_control),
63                         USB_CTRL_SET_TIMEOUT);
64
65         kfree(control);
66
67         if (len != sizeof(struct koneplus_control))
68                 return len;
69
70         return 0;
71 }
72
73 static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
74                 void *buf, uint size) {
75         int len;
76
77         len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
78                         USB_REQ_CLEAR_FEATURE,
79                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
80                         usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
81
82         return (len != size) ? -EIO : 0;
83 }
84
85 static int koneplus_receive_control_status(struct usb_device *usb_dev)
86 {
87         int retval;
88         struct koneplus_control *control;
89
90         control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
91         if (!control)
92                 return -ENOMEM;
93
94         do {
95                 retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
96                                 control, sizeof(struct koneplus_control));
97
98                 /* check if we get a completely wrong answer */
99                 if (retval)
100                         goto out;
101
102                 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
103                         retval = 0;
104                         goto out;
105                 }
106
107                 /* indicates that hardware needs some more time to complete action */
108                 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
109                         msleep(500); /* windows driver uses 1000 */
110                         continue;
111                 }
112
113                 /* seems to be critical - replug necessary */
114                 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
115                         retval = -EINVAL;
116                         goto out;
117                 }
118
119                 dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
120                                 "unknown response value 0x%x\n", control->value);
121                 retval = -EINVAL;
122                 goto out;
123
124         } while (1);
125 out:
126         kfree(control);
127         return retval;
128 }
129
130 static int koneplus_send(struct usb_device *usb_dev, uint command,
131                 void *buf, uint size) {
132         int len;
133
134         len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
135                         USB_REQ_SET_CONFIGURATION,
136                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
137                         command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
138
139         if (len != size)
140                 return -EIO;
141
142         if (koneplus_receive_control_status(usb_dev))
143                 return -EIO;
144
145         return 0;
146 }
147
148 static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
149                 enum koneplus_control_requests request)
150 {
151         int retval;
152
153         retval = koneplus_send_control(usb_dev, number, request);
154         if (retval)
155                 return retval;
156
157         /* allow time to settle things - windows driver uses 500 */
158         msleep(100);
159
160         retval = koneplus_receive_control_status(usb_dev);
161         if (retval)
162                 return retval;
163
164         return 0;
165 }
166
167 static int koneplus_get_info(struct usb_device *usb_dev,
168                 struct koneplus_info *buf)
169 {
170         return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
171                         buf, sizeof(struct koneplus_info));
172 }
173
174 static int koneplus_get_profile_settings(struct usb_device *usb_dev,
175                 struct koneplus_profile_settings *buf, uint number)
176 {
177         int retval;
178
179         retval = koneplus_select_profile(usb_dev, number,
180                         KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
181         if (retval)
182                 return retval;
183
184         return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
185                         buf, sizeof(struct koneplus_profile_settings));
186 }
187
188 static int koneplus_set_profile_settings(struct usb_device *usb_dev,
189                 struct koneplus_profile_settings const *settings)
190 {
191         return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
192                         (void *)settings, sizeof(struct koneplus_profile_settings));
193 }
194
195 static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
196                 struct koneplus_profile_buttons *buf, int number)
197 {
198         int retval;
199
200         retval = koneplus_select_profile(usb_dev, number,
201                         KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
202         if (retval)
203                 return retval;
204
205         return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
206                         buf, sizeof(struct koneplus_profile_buttons));
207 }
208
209 static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
210                 struct koneplus_profile_buttons const *buttons)
211 {
212         return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
213                         (void *)buttons, sizeof(struct koneplus_profile_buttons));
214 }
215
216 /* retval is 0-4 on success, < 0 on error */
217 static int koneplus_get_startup_profile(struct usb_device *usb_dev)
218 {
219         struct koneplus_startup_profile *buf;
220         int retval;
221
222         buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
223
224         retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
225                         buf, sizeof(struct koneplus_startup_profile));
226
227         if (retval)
228                 goto out;
229
230         retval = buf->startup_profile;
231 out:
232         kfree(buf);
233         return retval;
234 }
235
236 static int koneplus_set_startup_profile(struct usb_device *usb_dev,
237                 int startup_profile)
238 {
239         struct koneplus_startup_profile buf;
240
241         buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE;
242         buf.size = sizeof(struct koneplus_startup_profile);
243         buf.startup_profile = startup_profile;
244
245         return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
246                         (char *)&buf, sizeof(struct koneplus_profile_buttons));
247 }
248
249 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
250                 char *buf, loff_t off, size_t count,
251                 size_t real_size, uint command)
252 {
253         struct device *dev =
254                         container_of(kobj, struct device, kobj)->parent->parent;
255         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
256         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
257         int retval;
258
259         if (off != 0 || count != real_size)
260                 return -EINVAL;
261
262         mutex_lock(&koneplus->koneplus_lock);
263         retval = koneplus_receive(usb_dev, command, buf, real_size);
264         mutex_unlock(&koneplus->koneplus_lock);
265
266         if (retval)
267                 return retval;
268
269         return real_size;
270 }
271
272 static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
273                 void const *buf, loff_t off, size_t count,
274                 size_t real_size, uint command)
275 {
276         struct device *dev =
277                         container_of(kobj, struct device, kobj)->parent->parent;
278         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
279         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
280         int retval;
281
282         if (off != 0 || count != real_size)
283                 return -EINVAL;
284
285         mutex_lock(&koneplus->koneplus_lock);
286         retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
287         mutex_unlock(&koneplus->koneplus_lock);
288
289         if (retval)
290                 return retval;
291
292         return real_size;
293 }
294
295 static ssize_t koneplus_sysfs_write_macro(struct file *fp,
296                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
297                 loff_t off, size_t count)
298 {
299         return koneplus_sysfs_write(fp, kobj, buf, off, count,
300                         sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO);
301 }
302
303 static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
304                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
305                 loff_t off, size_t count)
306 {
307         return koneplus_sysfs_read(fp, kobj, buf, off, count,
308                         sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
309 }
310
311 static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
312                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
313                 loff_t off, size_t count)
314 {
315         return koneplus_sysfs_write(fp, kobj, buf, off, count,
316                         sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
317 }
318
319 static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
320                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
321                 loff_t off, size_t count)
322 {
323         return koneplus_sysfs_write(fp, kobj, buf, off, count,
324                         sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU);
325 }
326
327 static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
328                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
329                 loff_t off, size_t count)
330 {
331         return koneplus_sysfs_read(fp, kobj, buf, off, count,
332                         sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU);
333 }
334
335 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
336                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
337                 loff_t off, size_t count)
338 {
339         struct device *dev =
340                         container_of(kobj, struct device, kobj)->parent->parent;
341         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
342
343         if (off >= sizeof(struct koneplus_profile_settings))
344                 return 0;
345
346         if (off + count > sizeof(struct koneplus_profile_settings))
347                 count = sizeof(struct koneplus_profile_settings) - off;
348
349         mutex_lock(&koneplus->koneplus_lock);
350         memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
351                         count);
352         mutex_unlock(&koneplus->koneplus_lock);
353
354         return count;
355 }
356
357 static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
358                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
359                 loff_t off, size_t count)
360 {
361         struct device *dev =
362                         container_of(kobj, struct device, kobj)->parent->parent;
363         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
364         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
365         int retval = 0;
366         int difference;
367         int profile_number;
368         struct koneplus_profile_settings *profile_settings;
369
370         if (off != 0 || count != sizeof(struct koneplus_profile_settings))
371                 return -EINVAL;
372
373         profile_number = ((struct koneplus_profile_settings const *)buf)->number;
374         profile_settings = &koneplus->profile_settings[profile_number];
375
376         mutex_lock(&koneplus->koneplus_lock);
377         difference = memcmp(buf, profile_settings,
378                         sizeof(struct koneplus_profile_settings));
379         if (difference) {
380                 retval = koneplus_set_profile_settings(usb_dev,
381                                 (struct koneplus_profile_settings const *)buf);
382                 if (!retval)
383                         memcpy(profile_settings, buf,
384                                         sizeof(struct koneplus_profile_settings));
385         }
386         mutex_unlock(&koneplus->koneplus_lock);
387
388         if (retval)
389                 return retval;
390
391         return sizeof(struct koneplus_profile_settings);
392 }
393
394 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
395                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
396                 loff_t off, size_t count)
397 {
398         struct device *dev =
399                         container_of(kobj, struct device, kobj)->parent->parent;
400         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
401
402         if (off >= sizeof(struct koneplus_profile_buttons))
403                 return 0;
404
405         if (off + count > sizeof(struct koneplus_profile_buttons))
406                 count = sizeof(struct koneplus_profile_buttons) - off;
407
408         mutex_lock(&koneplus->koneplus_lock);
409         memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
410                         count);
411         mutex_unlock(&koneplus->koneplus_lock);
412
413         return count;
414 }
415
416 static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
417                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
418                 loff_t off, size_t count)
419 {
420         struct device *dev =
421                         container_of(kobj, struct device, kobj)->parent->parent;
422         struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
423         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
424         int retval = 0;
425         int difference;
426         uint profile_number;
427         struct koneplus_profile_buttons *profile_buttons;
428
429         if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
430                 return -EINVAL;
431
432         profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
433         profile_buttons = &koneplus->profile_buttons[profile_number];
434
435         mutex_lock(&koneplus->koneplus_lock);
436         difference = memcmp(buf, profile_buttons,
437                         sizeof(struct koneplus_profile_buttons));
438         if (difference) {
439                 retval = koneplus_set_profile_buttons(usb_dev,
440                                 (struct koneplus_profile_buttons const *)buf);
441                 if (!retval)
442                         memcpy(profile_buttons, buf,
443                                         sizeof(struct koneplus_profile_buttons));
444         }
445         mutex_unlock(&koneplus->koneplus_lock);
446
447         if (retval)
448                 return retval;
449
450         return sizeof(struct koneplus_profile_buttons);
451 }
452
453 static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev,
454                 struct device_attribute *attr, char *buf)
455 {
456         struct koneplus_device *koneplus =
457                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
458         return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile);
459 }
460
461 static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
462                 struct device_attribute *attr, char const *buf, size_t size)
463 {
464         struct koneplus_device *koneplus;
465         struct usb_device *usb_dev;
466         unsigned long profile;
467         int retval;
468
469         dev = dev->parent->parent;
470         koneplus = hid_get_drvdata(dev_get_drvdata(dev));
471         usb_dev = interface_to_usbdev(to_usb_interface(dev));
472
473         retval = strict_strtoul(buf, 10, &profile);
474         if (retval)
475                 return retval;
476
477         mutex_lock(&koneplus->koneplus_lock);
478         retval = koneplus_set_startup_profile(usb_dev, profile);
479         mutex_unlock(&koneplus->koneplus_lock);
480         if (retval)
481                 return retval;
482
483         return size;
484 }
485
486 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
487                 struct device_attribute *attr, char *buf)
488 {
489         struct koneplus_device *koneplus =
490                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
491         return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
492 }
493
494 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
495                 struct device_attribute *attr, char *buf)
496 {
497         struct koneplus_device *koneplus =
498                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
499         return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
500 }
501
502 static struct device_attribute koneplus_attributes[] = {
503         __ATTR(startup_profile, 0660,
504                         koneplus_sysfs_show_startup_profile,
505                         koneplus_sysfs_set_startup_profile),
506         __ATTR(actual_profile, 0440,
507                         koneplus_sysfs_show_actual_profile, NULL),
508         __ATTR(firmware_version, 0440,
509                         koneplus_sysfs_show_firmware_version, NULL),
510         __ATTR_NULL
511 };
512
513 static struct bin_attribute koneplus_bin_attributes[] = {
514         {
515                 .attr = { .name = "sensor", .mode = 0220 },
516                 .size = sizeof(struct koneplus_sensor),
517                 .read = koneplus_sysfs_read_sensor,
518                 .write = koneplus_sysfs_write_sensor
519         },
520         {
521                 .attr = { .name = "tcu", .mode = 0220 },
522                 .size = sizeof(struct koneplus_tcu),
523                 .write = koneplus_sysfs_write_tcu
524         },
525         {
526                 .attr = { .name = "tcu_image", .mode = 0440 },
527                 .size = sizeof(struct koneplus_tcu_image),
528                 .read = koneplus_sysfs_read_tcu_image
529         },
530         {
531                 .attr = { .name = "profile_settings", .mode = 0220 },
532                 .size = sizeof(struct koneplus_profile_settings),
533                 .write = koneplus_sysfs_write_profile_settings
534         },
535         {
536                 .attr = { .name = "profile1_settings", .mode = 0440 },
537                 .size = sizeof(struct koneplus_profile_settings),
538                 .read = koneplus_sysfs_read_profilex_settings,
539                 .private = &profile_numbers[0]
540         },
541         {
542                 .attr = { .name = "profile2_settings", .mode = 0440 },
543                 .size = sizeof(struct koneplus_profile_settings),
544                 .read = koneplus_sysfs_read_profilex_settings,
545                 .private = &profile_numbers[1]
546         },
547         {
548                 .attr = { .name = "profile3_settings", .mode = 0440 },
549                 .size = sizeof(struct koneplus_profile_settings),
550                 .read = koneplus_sysfs_read_profilex_settings,
551                 .private = &profile_numbers[2]
552         },
553         {
554                 .attr = { .name = "profile4_settings", .mode = 0440 },
555                 .size = sizeof(struct koneplus_profile_settings),
556                 .read = koneplus_sysfs_read_profilex_settings,
557                 .private = &profile_numbers[3]
558         },
559         {
560                 .attr = { .name = "profile5_settings", .mode = 0440 },
561                 .size = sizeof(struct koneplus_profile_settings),
562                 .read = koneplus_sysfs_read_profilex_settings,
563                 .private = &profile_numbers[4]
564         },
565         {
566                 .attr = { .name = "profile_buttons", .mode = 0220 },
567                 .size = sizeof(struct koneplus_profile_buttons),
568                 .write = koneplus_sysfs_write_profile_buttons
569         },
570         {
571                 .attr = { .name = "profile1_buttons", .mode = 0440 },
572                 .size = sizeof(struct koneplus_profile_buttons),
573                 .read = koneplus_sysfs_read_profilex_buttons,
574                 .private = &profile_numbers[0]
575         },
576         {
577                 .attr = { .name = "profile2_buttons", .mode = 0440 },
578                 .size = sizeof(struct koneplus_profile_buttons),
579                 .read = koneplus_sysfs_read_profilex_buttons,
580                 .private = &profile_numbers[1]
581         },
582         {
583                 .attr = { .name = "profile3_buttons", .mode = 0440 },
584                 .size = sizeof(struct koneplus_profile_buttons),
585                 .read = koneplus_sysfs_read_profilex_buttons,
586                 .private = &profile_numbers[2]
587         },
588         {
589                 .attr = { .name = "profile4_buttons", .mode = 0440 },
590                 .size = sizeof(struct koneplus_profile_buttons),
591                 .read = koneplus_sysfs_read_profilex_buttons,
592                 .private = &profile_numbers[3]
593         },
594         {
595                 .attr = { .name = "profile5_buttons", .mode = 0440 },
596                 .size = sizeof(struct koneplus_profile_buttons),
597                 .read = koneplus_sysfs_read_profilex_buttons,
598                 .private = &profile_numbers[4]
599         },
600         {
601                 .attr = { .name = "macro", .mode = 0220 },
602                 .size = sizeof(struct koneplus_macro),
603                 .write = koneplus_sysfs_write_macro
604         },
605         __ATTR_NULL
606 };
607
608 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
609                 struct koneplus_device *koneplus)
610 {
611         int retval, i;
612         static uint wait = 70; /* device will freeze with just 60 */
613
614         mutex_init(&koneplus->koneplus_lock);
615
616         koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
617
618         msleep(wait);
619         retval = koneplus_get_info(usb_dev, &koneplus->info);
620         if (retval)
621                 return retval;
622
623         for (i = 0; i < 5; ++i) {
624                 msleep(wait);
625                 retval = koneplus_get_profile_settings(usb_dev,
626                                 &koneplus->profile_settings[i], i);
627                 if (retval)
628                         return retval;
629
630                 msleep(wait);
631                 retval = koneplus_get_profile_buttons(usb_dev,
632                                 &koneplus->profile_buttons[i], i);
633                 if (retval)
634                         return retval;
635         }
636
637         koneplus_profile_activated(koneplus, koneplus->startup_profile);
638
639         return 0;
640 }
641
642 static int koneplus_init_specials(struct hid_device *hdev)
643 {
644         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
645         struct usb_device *usb_dev = interface_to_usbdev(intf);
646         struct koneplus_device *koneplus;
647         int retval;
648
649         if (intf->cur_altsetting->desc.bInterfaceProtocol
650                         == USB_INTERFACE_PROTOCOL_MOUSE) {
651
652                 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
653                 if (!koneplus) {
654                         dev_err(&hdev->dev, "can't alloc device descriptor\n");
655                         return -ENOMEM;
656                 }
657                 hid_set_drvdata(hdev, koneplus);
658
659                 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
660                 if (retval) {
661                         dev_err(&hdev->dev,
662                                         "couldn't init struct koneplus_device\n");
663                         goto exit_free;
664                 }
665
666                 retval = roccat_connect(koneplus_class, hdev);
667                 if (retval < 0) {
668                         dev_err(&hdev->dev, "couldn't init char dev\n");
669                 } else {
670                         koneplus->chrdev_minor = retval;
671                         koneplus->roccat_claimed = 1;
672                 }
673         } else {
674                 hid_set_drvdata(hdev, NULL);
675         }
676
677         return 0;
678 exit_free:
679         kfree(koneplus);
680         return retval;
681 }
682
683 static void koneplus_remove_specials(struct hid_device *hdev)
684 {
685         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
686         struct koneplus_device *koneplus;
687
688         if (intf->cur_altsetting->desc.bInterfaceProtocol
689                         == USB_INTERFACE_PROTOCOL_MOUSE) {
690                 koneplus = hid_get_drvdata(hdev);
691                 if (koneplus->roccat_claimed)
692                         roccat_disconnect(koneplus->chrdev_minor);
693                 kfree(koneplus);
694         }
695 }
696
697 static int koneplus_probe(struct hid_device *hdev,
698                 const struct hid_device_id *id)
699 {
700         int retval;
701
702         retval = hid_parse(hdev);
703         if (retval) {
704                 dev_err(&hdev->dev, "parse failed\n");
705                 goto exit;
706         }
707
708         retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
709         if (retval) {
710                 dev_err(&hdev->dev, "hw start failed\n");
711                 goto exit;
712         }
713
714         retval = koneplus_init_specials(hdev);
715         if (retval) {
716                 dev_err(&hdev->dev, "couldn't install mouse\n");
717                 goto exit_stop;
718         }
719
720         return 0;
721
722 exit_stop:
723         hid_hw_stop(hdev);
724 exit:
725         return retval;
726 }
727
728 static void koneplus_remove(struct hid_device *hdev)
729 {
730         koneplus_remove_specials(hdev);
731         hid_hw_stop(hdev);
732 }
733
734 static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus,
735                 u8 const *data)
736 {
737         struct koneplus_mouse_report_button const *button_report;
738
739         switch (data[0]) {
740         case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON:
741                 button_report = (struct koneplus_mouse_report_button const *)data;
742                 switch (button_report->type) {
743                 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE:
744                         koneplus_profile_activated(koneplus, button_report->data1 - 1);
745                         break;
746                 }
747                 break;
748         }
749 }
750
751 static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
752                 u8 const *data)
753 {
754         struct koneplus_roccat_report roccat_report;
755         struct koneplus_mouse_report_button const *button_report;
756
757         if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON)
758                 return;
759
760         button_report = (struct koneplus_mouse_report_button const *)data;
761
762         if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
763                         button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) &&
764                         button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS)
765                 return;
766
767         roccat_report.type = button_report->type;
768         roccat_report.data1 = button_report->data1;
769         roccat_report.data2 = button_report->data2;
770         roccat_report.profile = koneplus->actual_profile + 1;
771         roccat_report_event(koneplus->chrdev_minor,
772                         (uint8_t const *)&roccat_report,
773                         sizeof(struct koneplus_roccat_report));
774 }
775
776 static int koneplus_raw_event(struct hid_device *hdev,
777                 struct hid_report *report, u8 *data, int size)
778 {
779         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
780         struct koneplus_device *koneplus = hid_get_drvdata(hdev);
781
782         if (intf->cur_altsetting->desc.bInterfaceProtocol
783                         != USB_INTERFACE_PROTOCOL_MOUSE)
784                 return 0;
785
786         koneplus_keep_values_up_to_date(koneplus, data);
787
788         if (koneplus->roccat_claimed)
789                 koneplus_report_to_chrdev(koneplus, data);
790
791         return 0;
792 }
793
794 static const struct hid_device_id koneplus_devices[] = {
795         { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
796         { }
797 };
798
799 MODULE_DEVICE_TABLE(hid, koneplus_devices);
800
801 static struct hid_driver koneplus_driver = {
802                 .name = "koneplus",
803                 .id_table = koneplus_devices,
804                 .probe = koneplus_probe,
805                 .remove = koneplus_remove,
806                 .raw_event = koneplus_raw_event
807 };
808
809 static int __init koneplus_init(void)
810 {
811         int retval;
812
813         /* class name has to be same as driver name */
814         koneplus_class = class_create(THIS_MODULE, "koneplus");
815         if (IS_ERR(koneplus_class))
816                 return PTR_ERR(koneplus_class);
817         koneplus_class->dev_attrs = koneplus_attributes;
818         koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
819
820         retval = hid_register_driver(&koneplus_driver);
821         if (retval)
822                 class_destroy(koneplus_class);
823         return retval;
824 }
825
826 static void __exit koneplus_exit(void)
827 {
828         class_destroy(koneplus_class);
829         hid_unregister_driver(&koneplus_driver);
830 }
831
832 module_init(koneplus_init);
833 module_exit(koneplus_exit);
834
835 MODULE_AUTHOR("Stefan Achatz");
836 MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
837 MODULE_LICENSE("GPL v2");