Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/hid/hid-roccat-kone.c
15109 views
1
/*
2
* Roccat Kone driver for Linux
3
*
4
* Copyright (c) 2010 Stefan Achatz <[email protected]>
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 a gamer mouse which consists of a mouse part and a keyboard
16
* part. The keyboard part enables the mouse to execute stored macros with mixed
17
* key- and button-events.
18
*
19
* TODO implement on-the-fly polling-rate change
20
* The windows driver has the ability to change the polling rate of the
21
* device on the press of a mousebutton.
22
* Is it possible to remove and reinstall the urb in raw-event- or any
23
* other handler, or to defer this action to be executed somewhere else?
24
*
25
* TODO is it possible to overwrite group for sysfs attributes via udev?
26
*/
27
28
#include <linux/device.h>
29
#include <linux/input.h>
30
#include <linux/hid.h>
31
#include <linux/module.h>
32
#include <linux/slab.h>
33
#include <linux/hid-roccat.h>
34
#include "hid-ids.h"
35
#include "hid-roccat-common.h"
36
#include "hid-roccat-kone.h"
37
38
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
39
40
/* kone_class is used for creating sysfs attributes via roccat char device */
41
static struct class *kone_class;
42
43
static void kone_set_settings_checksum(struct kone_settings *settings)
44
{
45
uint16_t checksum = 0;
46
unsigned char *address = (unsigned char *)settings;
47
int i;
48
49
for (i = 0; i < sizeof(struct kone_settings) - 2; ++i, ++address)
50
checksum += *address;
51
settings->checksum = cpu_to_le16(checksum);
52
}
53
54
/*
55
* Checks success after writing data to mouse
56
* On success returns 0
57
* On failure returns errno
58
*/
59
static int kone_check_write(struct usb_device *usb_dev)
60
{
61
int retval;
62
uint8_t data;
63
64
do {
65
/*
66
* Mouse needs 50 msecs until it says ok, but there are
67
* 30 more msecs needed for next write to work.
68
*/
69
msleep(80);
70
71
retval = roccat_common_receive(usb_dev,
72
kone_command_confirm_write, &data, 1);
73
if (retval)
74
return retval;
75
76
/*
77
* value of 3 seems to mean something like
78
* "not finished yet, but it looks good"
79
* So check again after a moment.
80
*/
81
} while (data == 3);
82
83
if (data == 1) /* everything alright */
84
return 0;
85
86
/* unknown answer */
87
hid_err(usb_dev, "got retval %d when checking write\n", data);
88
return -EIO;
89
}
90
91
/*
92
* Reads settings from mouse and stores it in @buf
93
* On success returns 0
94
* On failure returns errno
95
*/
96
static int kone_get_settings(struct usb_device *usb_dev,
97
struct kone_settings *buf)
98
{
99
return roccat_common_receive(usb_dev, kone_command_settings, buf,
100
sizeof(struct kone_settings));
101
}
102
103
/*
104
* Writes settings from @buf to mouse
105
* On success returns 0
106
* On failure returns errno
107
*/
108
static int kone_set_settings(struct usb_device *usb_dev,
109
struct kone_settings const *settings)
110
{
111
int retval;
112
retval = roccat_common_send(usb_dev, kone_command_settings,
113
settings, sizeof(struct kone_settings));
114
if (retval)
115
return retval;
116
return kone_check_write(usb_dev);
117
}
118
119
/*
120
* Reads profile data from mouse and stores it in @buf
121
* @number: profile number to read
122
* On success returns 0
123
* On failure returns errno
124
*/
125
static int kone_get_profile(struct usb_device *usb_dev,
126
struct kone_profile *buf, int number)
127
{
128
int len;
129
130
if (number < 1 || number > 5)
131
return -EINVAL;
132
133
len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
134
USB_REQ_CLEAR_FEATURE,
135
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
136
kone_command_profile, number, buf,
137
sizeof(struct kone_profile), USB_CTRL_SET_TIMEOUT);
138
139
if (len != sizeof(struct kone_profile))
140
return -EIO;
141
142
return 0;
143
}
144
145
/*
146
* Writes profile data to mouse.
147
* @number: profile number to write
148
* On success returns 0
149
* On failure returns errno
150
*/
151
static int kone_set_profile(struct usb_device *usb_dev,
152
struct kone_profile const *profile, int number)
153
{
154
int len;
155
156
if (number < 1 || number > 5)
157
return -EINVAL;
158
159
len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
160
USB_REQ_SET_CONFIGURATION,
161
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
162
kone_command_profile, number, (void *)profile,
163
sizeof(struct kone_profile),
164
USB_CTRL_SET_TIMEOUT);
165
166
if (len != sizeof(struct kone_profile))
167
return len;
168
169
if (kone_check_write(usb_dev))
170
return -EIO;
171
172
return 0;
173
}
174
175
/*
176
* Reads value of "fast-clip-weight" and stores it in @result
177
* On success returns 0
178
* On failure returns errno
179
*/
180
static int kone_get_weight(struct usb_device *usb_dev, int *result)
181
{
182
int retval;
183
uint8_t data;
184
185
retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
186
187
if (retval)
188
return retval;
189
190
*result = (int)data;
191
return 0;
192
}
193
194
/*
195
* Reads firmware_version of mouse and stores it in @result
196
* On success returns 0
197
* On failure returns errno
198
*/
199
static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
200
{
201
int retval;
202
uint16_t data;
203
204
retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
205
&data, 2);
206
if (retval)
207
return retval;
208
209
*result = le16_to_cpu(data);
210
return 0;
211
}
212
213
static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
214
struct bin_attribute *attr, char *buf,
215
loff_t off, size_t count) {
216
struct device *dev =
217
container_of(kobj, struct device, kobj)->parent->parent;
218
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
219
220
if (off >= sizeof(struct kone_settings))
221
return 0;
222
223
if (off + count > sizeof(struct kone_settings))
224
count = sizeof(struct kone_settings) - off;
225
226
mutex_lock(&kone->kone_lock);
227
memcpy(buf, ((char const *)&kone->settings) + off, count);
228
mutex_unlock(&kone->kone_lock);
229
230
return count;
231
}
232
233
/*
234
* Writing settings automatically activates startup_profile.
235
* This function keeps values in kone_device up to date and assumes that in
236
* case of error the old data is still valid
237
*/
238
static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
239
struct bin_attribute *attr, char *buf,
240
loff_t off, size_t count) {
241
struct device *dev =
242
container_of(kobj, struct device, kobj)->parent->parent;
243
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
244
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
245
int retval = 0, difference;
246
247
/* I need to get my data in one piece */
248
if (off != 0 || count != sizeof(struct kone_settings))
249
return -EINVAL;
250
251
mutex_lock(&kone->kone_lock);
252
difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings));
253
if (difference) {
254
retval = kone_set_settings(usb_dev,
255
(struct kone_settings const *)buf);
256
if (!retval)
257
memcpy(&kone->settings, buf,
258
sizeof(struct kone_settings));
259
}
260
mutex_unlock(&kone->kone_lock);
261
262
if (retval)
263
return retval;
264
265
/*
266
* If we get here, treat settings as okay and update actual values
267
* according to startup_profile
268
*/
269
kone->actual_profile = kone->settings.startup_profile;
270
kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
271
272
return sizeof(struct kone_settings);
273
}
274
275
static ssize_t kone_sysfs_read_profilex(struct file *fp,
276
struct kobject *kobj, struct bin_attribute *attr,
277
char *buf, loff_t off, size_t count) {
278
struct device *dev =
279
container_of(kobj, struct device, kobj)->parent->parent;
280
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
281
282
if (off >= sizeof(struct kone_profile))
283
return 0;
284
285
if (off + count > sizeof(struct kone_profile))
286
count = sizeof(struct kone_profile) - off;
287
288
mutex_lock(&kone->kone_lock);
289
memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count);
290
mutex_unlock(&kone->kone_lock);
291
292
return count;
293
}
294
295
/* Writes data only if different to stored data */
296
static ssize_t kone_sysfs_write_profilex(struct file *fp,
297
struct kobject *kobj, struct bin_attribute *attr,
298
char *buf, loff_t off, size_t count) {
299
struct device *dev =
300
container_of(kobj, struct device, kobj)->parent->parent;
301
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
302
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
303
struct kone_profile *profile;
304
int retval = 0, difference;
305
306
/* I need to get my data in one piece */
307
if (off != 0 || count != sizeof(struct kone_profile))
308
return -EINVAL;
309
310
profile = &kone->profiles[*(uint *)(attr->private)];
311
312
mutex_lock(&kone->kone_lock);
313
difference = memcmp(buf, profile, sizeof(struct kone_profile));
314
if (difference) {
315
retval = kone_set_profile(usb_dev,
316
(struct kone_profile const *)buf,
317
*(uint *)(attr->private) + 1);
318
if (!retval)
319
memcpy(profile, buf, sizeof(struct kone_profile));
320
}
321
mutex_unlock(&kone->kone_lock);
322
323
if (retval)
324
return retval;
325
326
return sizeof(struct kone_profile);
327
}
328
329
static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
330
struct device_attribute *attr, char *buf)
331
{
332
struct kone_device *kone =
333
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
334
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
335
}
336
337
static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
338
struct device_attribute *attr, char *buf)
339
{
340
struct kone_device *kone =
341
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
342
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
343
}
344
345
/* weight is read each time, since we don't get informed when it's changed */
346
static ssize_t kone_sysfs_show_weight(struct device *dev,
347
struct device_attribute *attr, char *buf)
348
{
349
struct kone_device *kone;
350
struct usb_device *usb_dev;
351
int weight = 0;
352
int retval;
353
354
dev = dev->parent->parent;
355
kone = hid_get_drvdata(dev_get_drvdata(dev));
356
usb_dev = interface_to_usbdev(to_usb_interface(dev));
357
358
mutex_lock(&kone->kone_lock);
359
retval = kone_get_weight(usb_dev, &weight);
360
mutex_unlock(&kone->kone_lock);
361
362
if (retval)
363
return retval;
364
return snprintf(buf, PAGE_SIZE, "%d\n", weight);
365
}
366
367
static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
368
struct device_attribute *attr, char *buf)
369
{
370
struct kone_device *kone =
371
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
372
return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
373
}
374
375
static ssize_t kone_sysfs_show_tcu(struct device *dev,
376
struct device_attribute *attr, char *buf)
377
{
378
struct kone_device *kone =
379
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
380
return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu);
381
}
382
383
static int kone_tcu_command(struct usb_device *usb_dev, int number)
384
{
385
unsigned char value;
386
value = number;
387
return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
388
}
389
390
/*
391
* Calibrating the tcu is the only action that changes settings data inside the
392
* mouse, so this data needs to be reread
393
*/
394
static ssize_t kone_sysfs_set_tcu(struct device *dev,
395
struct device_attribute *attr, char const *buf, size_t size)
396
{
397
struct kone_device *kone;
398
struct usb_device *usb_dev;
399
int retval;
400
unsigned long state;
401
402
dev = dev->parent->parent;
403
kone = hid_get_drvdata(dev_get_drvdata(dev));
404
usb_dev = interface_to_usbdev(to_usb_interface(dev));
405
406
retval = strict_strtoul(buf, 10, &state);
407
if (retval)
408
return retval;
409
410
if (state != 0 && state != 1)
411
return -EINVAL;
412
413
mutex_lock(&kone->kone_lock);
414
415
if (state == 1) { /* state activate */
416
retval = kone_tcu_command(usb_dev, 1);
417
if (retval)
418
goto exit_unlock;
419
retval = kone_tcu_command(usb_dev, 2);
420
if (retval)
421
goto exit_unlock;
422
ssleep(5); /* tcu needs this time for calibration */
423
retval = kone_tcu_command(usb_dev, 3);
424
if (retval)
425
goto exit_unlock;
426
retval = kone_tcu_command(usb_dev, 0);
427
if (retval)
428
goto exit_unlock;
429
retval = kone_tcu_command(usb_dev, 4);
430
if (retval)
431
goto exit_unlock;
432
/*
433
* Kone needs this time to settle things.
434
* Reading settings too early will result in invalid data.
435
* Roccat's driver waits 1 sec, maybe this time could be
436
* shortened.
437
*/
438
ssleep(1);
439
}
440
441
/* calibration changes values in settings, so reread */
442
retval = kone_get_settings(usb_dev, &kone->settings);
443
if (retval)
444
goto exit_no_settings;
445
446
/* only write settings back if activation state is different */
447
if (kone->settings.tcu != state) {
448
kone->settings.tcu = state;
449
kone_set_settings_checksum(&kone->settings);
450
451
retval = kone_set_settings(usb_dev, &kone->settings);
452
if (retval) {
453
hid_err(usb_dev, "couldn't set tcu state\n");
454
/*
455
* try to reread valid settings into buffer overwriting
456
* first error code
457
*/
458
retval = kone_get_settings(usb_dev, &kone->settings);
459
if (retval)
460
goto exit_no_settings;
461
goto exit_unlock;
462
}
463
}
464
465
retval = size;
466
exit_no_settings:
467
hid_err(usb_dev, "couldn't read settings\n");
468
exit_unlock:
469
mutex_unlock(&kone->kone_lock);
470
return retval;
471
}
472
473
static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
474
struct device_attribute *attr, char *buf)
475
{
476
struct kone_device *kone =
477
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
478
return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile);
479
}
480
481
static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
482
struct device_attribute *attr, char const *buf, size_t size)
483
{
484
struct kone_device *kone;
485
struct usb_device *usb_dev;
486
int retval;
487
unsigned long new_startup_profile;
488
489
dev = dev->parent->parent;
490
kone = hid_get_drvdata(dev_get_drvdata(dev));
491
usb_dev = interface_to_usbdev(to_usb_interface(dev));
492
493
retval = strict_strtoul(buf, 10, &new_startup_profile);
494
if (retval)
495
return retval;
496
497
if (new_startup_profile < 1 || new_startup_profile > 5)
498
return -EINVAL;
499
500
mutex_lock(&kone->kone_lock);
501
502
kone->settings.startup_profile = new_startup_profile;
503
kone_set_settings_checksum(&kone->settings);
504
505
retval = kone_set_settings(usb_dev, &kone->settings);
506
507
mutex_unlock(&kone->kone_lock);
508
509
if (retval)
510
return retval;
511
512
/* changing the startup profile immediately activates this profile */
513
kone->actual_profile = new_startup_profile;
514
kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
515
516
return size;
517
}
518
519
static struct device_attribute kone_attributes[] = {
520
/*
521
* Read actual dpi settings.
522
* Returns raw value for further processing. Refer to enum
523
* kone_polling_rates to get real value.
524
*/
525
__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
526
__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
527
528
/*
529
* The mouse can be equipped with one of four supplied weights from 5
530
* to 20 grams which are recognized and its value can be read out.
531
* This returns the raw value reported by the mouse for easy evaluation
532
* by software. Refer to enum kone_weights to get corresponding real
533
* weight.
534
*/
535
__ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
536
537
/*
538
* Prints firmware version stored in mouse as integer.
539
* The raw value reported by the mouse is returned for easy evaluation,
540
* to get the real version number the decimal point has to be shifted 2
541
* positions to the left. E.g. a value of 138 means 1.38.
542
*/
543
__ATTR(firmware_version, 0440,
544
kone_sysfs_show_firmware_version, NULL),
545
546
/*
547
* Prints state of Tracking Control Unit as number where 0 = off and
548
* 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
549
* activates the tcu
550
*/
551
__ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
552
553
/* Prints and takes the number of the profile the mouse starts with */
554
__ATTR(startup_profile, 0660,
555
kone_sysfs_show_startup_profile,
556
kone_sysfs_set_startup_profile),
557
__ATTR_NULL
558
};
559
560
static struct bin_attribute kone_bin_attributes[] = {
561
{
562
.attr = { .name = "settings", .mode = 0660 },
563
.size = sizeof(struct kone_settings),
564
.read = kone_sysfs_read_settings,
565
.write = kone_sysfs_write_settings
566
},
567
{
568
.attr = { .name = "profile1", .mode = 0660 },
569
.size = sizeof(struct kone_profile),
570
.read = kone_sysfs_read_profilex,
571
.write = kone_sysfs_write_profilex,
572
.private = &profile_numbers[0]
573
},
574
{
575
.attr = { .name = "profile2", .mode = 0660 },
576
.size = sizeof(struct kone_profile),
577
.read = kone_sysfs_read_profilex,
578
.write = kone_sysfs_write_profilex,
579
.private = &profile_numbers[1]
580
},
581
{
582
.attr = { .name = "profile3", .mode = 0660 },
583
.size = sizeof(struct kone_profile),
584
.read = kone_sysfs_read_profilex,
585
.write = kone_sysfs_write_profilex,
586
.private = &profile_numbers[2]
587
},
588
{
589
.attr = { .name = "profile4", .mode = 0660 },
590
.size = sizeof(struct kone_profile),
591
.read = kone_sysfs_read_profilex,
592
.write = kone_sysfs_write_profilex,
593
.private = &profile_numbers[3]
594
},
595
{
596
.attr = { .name = "profile5", .mode = 0660 },
597
.size = sizeof(struct kone_profile),
598
.read = kone_sysfs_read_profilex,
599
.write = kone_sysfs_write_profilex,
600
.private = &profile_numbers[4]
601
},
602
__ATTR_NULL
603
};
604
605
static int kone_init_kone_device_struct(struct usb_device *usb_dev,
606
struct kone_device *kone)
607
{
608
uint i;
609
int retval;
610
611
mutex_init(&kone->kone_lock);
612
613
for (i = 0; i < 5; ++i) {
614
retval = kone_get_profile(usb_dev, &kone->profiles[i], i + 1);
615
if (retval)
616
return retval;
617
}
618
619
retval = kone_get_settings(usb_dev, &kone->settings);
620
if (retval)
621
return retval;
622
623
retval = kone_get_firmware_version(usb_dev, &kone->firmware_version);
624
if (retval)
625
return retval;
626
627
kone->actual_profile = kone->settings.startup_profile;
628
kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
629
630
return 0;
631
}
632
633
/*
634
* Since IGNORE_MOUSE quirk moved to hid-apple, there is no way to bind only to
635
* mousepart if usb_hid is compiled into the kernel and kone is compiled as
636
* module.
637
* Secial behaviour is bound only to mousepart since only mouseevents contain
638
* additional notifications.
639
*/
640
static int kone_init_specials(struct hid_device *hdev)
641
{
642
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
643
struct usb_device *usb_dev = interface_to_usbdev(intf);
644
struct kone_device *kone;
645
int retval;
646
647
if (intf->cur_altsetting->desc.bInterfaceProtocol
648
== USB_INTERFACE_PROTOCOL_MOUSE) {
649
650
kone = kzalloc(sizeof(*kone), GFP_KERNEL);
651
if (!kone) {
652
hid_err(hdev, "can't alloc device descriptor\n");
653
return -ENOMEM;
654
}
655
hid_set_drvdata(hdev, kone);
656
657
retval = kone_init_kone_device_struct(usb_dev, kone);
658
if (retval) {
659
hid_err(hdev, "couldn't init struct kone_device\n");
660
goto exit_free;
661
}
662
663
retval = roccat_connect(kone_class, hdev,
664
sizeof(struct kone_roccat_report));
665
if (retval < 0) {
666
hid_err(hdev, "couldn't init char dev\n");
667
/* be tolerant about not getting chrdev */
668
} else {
669
kone->roccat_claimed = 1;
670
kone->chrdev_minor = retval;
671
}
672
} else {
673
hid_set_drvdata(hdev, NULL);
674
}
675
676
return 0;
677
exit_free:
678
kfree(kone);
679
return retval;
680
}
681
682
static void kone_remove_specials(struct hid_device *hdev)
683
{
684
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
685
struct kone_device *kone;
686
687
if (intf->cur_altsetting->desc.bInterfaceProtocol
688
== USB_INTERFACE_PROTOCOL_MOUSE) {
689
kone = hid_get_drvdata(hdev);
690
if (kone->roccat_claimed)
691
roccat_disconnect(kone->chrdev_minor);
692
kfree(hid_get_drvdata(hdev));
693
}
694
}
695
696
static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
697
{
698
int retval;
699
700
retval = hid_parse(hdev);
701
if (retval) {
702
hid_err(hdev, "parse failed\n");
703
goto exit;
704
}
705
706
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
707
if (retval) {
708
hid_err(hdev, "hw start failed\n");
709
goto exit;
710
}
711
712
retval = kone_init_specials(hdev);
713
if (retval) {
714
hid_err(hdev, "couldn't install mouse\n");
715
goto exit_stop;
716
}
717
718
return 0;
719
720
exit_stop:
721
hid_hw_stop(hdev);
722
exit:
723
return retval;
724
}
725
726
static void kone_remove(struct hid_device *hdev)
727
{
728
kone_remove_specials(hdev);
729
hid_hw_stop(hdev);
730
}
731
732
/* handle special events and keep actual profile and dpi values up to date */
733
static void kone_keep_values_up_to_date(struct kone_device *kone,
734
struct kone_mouse_event const *event)
735
{
736
switch (event->event) {
737
case kone_mouse_event_switch_profile:
738
case kone_mouse_event_osd_profile:
739
kone->actual_profile = event->value;
740
kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
741
startup_dpi;
742
break;
743
case kone_mouse_event_switch_dpi:
744
case kone_mouse_event_osd_dpi:
745
kone->actual_dpi = event->value;
746
break;
747
}
748
}
749
750
static void kone_report_to_chrdev(struct kone_device const *kone,
751
struct kone_mouse_event const *event)
752
{
753
struct kone_roccat_report roccat_report;
754
755
switch (event->event) {
756
case kone_mouse_event_switch_profile:
757
case kone_mouse_event_switch_dpi:
758
case kone_mouse_event_osd_profile:
759
case kone_mouse_event_osd_dpi:
760
roccat_report.event = event->event;
761
roccat_report.value = event->value;
762
roccat_report.key = 0;
763
roccat_report_event(kone->chrdev_minor,
764
(uint8_t *)&roccat_report);
765
break;
766
case kone_mouse_event_call_overlong_macro:
767
if (event->value == kone_keystroke_action_press) {
768
roccat_report.event = kone_mouse_event_call_overlong_macro;
769
roccat_report.value = kone->actual_profile;
770
roccat_report.key = event->macro_key;
771
roccat_report_event(kone->chrdev_minor,
772
(uint8_t *)&roccat_report);
773
}
774
break;
775
}
776
777
}
778
779
/*
780
* Is called for keyboard- and mousepart.
781
* Only mousepart gets informations about special events in its extended event
782
* structure.
783
*/
784
static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
785
u8 *data, int size)
786
{
787
struct kone_device *kone = hid_get_drvdata(hdev);
788
struct kone_mouse_event *event = (struct kone_mouse_event *)data;
789
790
/* keyboard events are always processed by default handler */
791
if (size != sizeof(struct kone_mouse_event))
792
return 0;
793
794
/*
795
* Firmware 1.38 introduced new behaviour for tilt and special buttons.
796
* Pressed button is reported in each movement event.
797
* Workaround sends only one event per press.
798
*/
799
if (memcmp(&kone->last_mouse_event.tilt, &event->tilt, 5))
800
memcpy(&kone->last_mouse_event, event,
801
sizeof(struct kone_mouse_event));
802
else
803
memset(&event->tilt, 0, 5);
804
805
kone_keep_values_up_to_date(kone, event);
806
807
if (kone->roccat_claimed)
808
kone_report_to_chrdev(kone, event);
809
810
return 0; /* always do further processing */
811
}
812
813
static const struct hid_device_id kone_devices[] = {
814
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
815
{ }
816
};
817
818
MODULE_DEVICE_TABLE(hid, kone_devices);
819
820
static struct hid_driver kone_driver = {
821
.name = "kone",
822
.id_table = kone_devices,
823
.probe = kone_probe,
824
.remove = kone_remove,
825
.raw_event = kone_raw_event
826
};
827
828
static int __init kone_init(void)
829
{
830
int retval;
831
832
/* class name has to be same as driver name */
833
kone_class = class_create(THIS_MODULE, "kone");
834
if (IS_ERR(kone_class))
835
return PTR_ERR(kone_class);
836
kone_class->dev_attrs = kone_attributes;
837
kone_class->dev_bin_attrs = kone_bin_attributes;
838
839
retval = hid_register_driver(&kone_driver);
840
if (retval)
841
class_destroy(kone_class);
842
return retval;
843
}
844
845
static void __exit kone_exit(void)
846
{
847
hid_unregister_driver(&kone_driver);
848
class_destroy(kone_class);
849
}
850
851
module_init(kone_init);
852
module_exit(kone_exit);
853
854
MODULE_AUTHOR("Stefan Achatz");
855
MODULE_DESCRIPTION("USB Roccat Kone driver");
856
MODULE_LICENSE("GPL v2");
857
858