]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/hid/hid-roccat-kone.c
HID: roccat: propagate special events of roccat hardware to userspace
[karo-tx-linux.git] / drivers / hid / hid-roccat-kone.c
index b6371d3fe0f9d2b612960fa23ee879f0bb85e0ba..17f2dc04f883d0eb9462444a816d50ebf9b50b41 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include "hid-ids.h"
+#include "hid-roccat.h"
 #include "hid-roccat-kone.h"
 
 static void kone_set_settings_checksum(struct kone_settings *settings)
@@ -849,6 +850,16 @@ static int kone_init_specials(struct hid_device *hdev)
                                        "couldn't init struct kone_device\n");
                        goto exit_free;
                }
+
+               retval = roccat_connect(hdev);
+               if (retval < 0) {
+                       dev_err(&hdev->dev, "couldn't init char dev\n");
+                       /* be tolerant about not getting chrdev */
+               } else {
+                       kone->roccat_claimed = 1;
+                       kone->chrdev_minor = retval;
+               }
+
                retval = kone_create_sysfs_attributes(intf);
                if (retval) {
                        dev_err(&hdev->dev, "cannot create sysfs files\n");
@@ -868,10 +879,14 @@ exit_free:
 static void kone_remove_specials(struct hid_device *hdev)
 {
        struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct kone_device *kone;
 
        if (intf->cur_altsetting->desc.bInterfaceProtocol
                        == USB_INTERFACE_PROTOCOL_MOUSE) {
                kone_remove_sysfs_attributes(intf);
+               kone = hid_get_drvdata(hdev);
+               if (kone->roccat_claimed)
+                       roccat_disconnect(kone->chrdev_minor);
                kfree(hid_get_drvdata(hdev));
        }
 }
@@ -930,6 +945,37 @@ static void kone_keep_values_up_to_date(struct kone_device *kone,
        }
 }
 
+static void kone_report_to_chrdev(struct kone_device const *kone,
+               struct kone_mouse_event const *event)
+{
+       struct kone_roccat_report roccat_report;
+
+       switch (event->event) {
+       case kone_mouse_event_switch_profile:
+       case kone_mouse_event_switch_dpi:
+       case kone_mouse_event_osd_profile:
+       case kone_mouse_event_osd_dpi:
+               roccat_report.event = event->event;
+               roccat_report.value = event->value;
+               roccat_report.key = 0;
+               roccat_report_event(kone->chrdev_minor,
+                               (uint8_t *)&roccat_report,
+                               sizeof(struct kone_roccat_report));
+               break;
+       case kone_mouse_event_call_overlong_macro:
+               if (event->value == kone_keystroke_action_press) {
+                       roccat_report.event = kone_mouse_event_call_overlong_macro;
+                       roccat_report.value = kone->actual_profile;
+                       roccat_report.key = event->macro_key;
+                       roccat_report_event(kone->chrdev_minor,
+                                       (uint8_t *)&roccat_report,
+                                       sizeof(struct kone_roccat_report));
+               }
+               break;
+       }
+
+}
+
 /*
  * Is called for keyboard- and mousepart.
  * Only mousepart gets informations about special events in its extended event
@@ -958,6 +1004,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
 
        kone_keep_values_up_to_date(kone, event);
 
+       if (kone->roccat_claimed)
+               kone_report_to_chrdev(kone, event);
+
        return 0; /* always do further processing */
 }