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

Archive Download this file



interactive