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