KVM: Fix order passed to iommu_unmap
[safe/jmp/linux-2.6] / drivers / hid / hid-roccat-kone.c
index a41df9a..17f2dc0 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)
@@ -263,7 +264,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
        return 0;
 }
 
-static ssize_t kone_sysfs_read_settings(struct kobject *kobj,
+static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        struct device *dev = container_of(kobj, struct device, kobj);
@@ -287,7 +288,7 @@ static ssize_t kone_sysfs_read_settings(struct kobject *kobj,
  * This function keeps values in kone_device up to date and assumes that in
  * case of error the old data is still valid
  */
-static ssize_t kone_sysfs_write_settings(struct kobject *kobj,
+static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        struct device *dev = container_of(kobj, struct device, kobj);
@@ -342,31 +343,31 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
        return count;
 }
 
-static ssize_t kone_sysfs_read_profile1(struct kobject *kobj,
+static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
 }
 
-static ssize_t kone_sysfs_read_profile2(struct kobject *kobj,
+static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
 }
 
-static ssize_t kone_sysfs_read_profile3(struct kobject *kobj,
+static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
 }
 
-static ssize_t kone_sysfs_read_profile4(struct kobject *kobj,
+static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
 }
 
-static ssize_t kone_sysfs_read_profile5(struct kobject *kobj,
+static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
@@ -404,31 +405,31 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
        return sizeof(struct kone_profile);
 }
 
-static ssize_t kone_sysfs_write_profile1(struct kobject *kobj,
+static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
 }
 
-static ssize_t kone_sysfs_write_profile2(struct kobject *kobj,
+static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
 }
 
-static ssize_t kone_sysfs_write_profile3(struct kobject *kobj,
+static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
 }
 
-static ssize_t kone_sysfs_write_profile4(struct kobject *kobj,
+static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
 }
 
-static ssize_t kone_sysfs_write_profile5(struct kobject *kobj,
+static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj,
                struct bin_attribute *attr, char *buf,
                loff_t off, size_t count) {
        return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
@@ -630,7 +631,7 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
 static ssize_t kone_sysfs_show_driver_version(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, DRIVER_VERSION "\n");
+       return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_DRIVER_VERSION "\n");
 }
 
 /*
@@ -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));
        }
 }
@@ -912,6 +927,55 @@ static void kone_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
+/* handle special events and keep actual profile and dpi values up to date */
+static void kone_keep_values_up_to_date(struct kone_device *kone,
+               struct kone_mouse_event const *event)
+{
+       switch (event->event) {
+       case kone_mouse_event_switch_profile:
+       case kone_mouse_event_osd_profile:
+               kone->actual_profile = event->value;
+               kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
+                               startup_dpi;
+               break;
+       case kone_mouse_event_switch_dpi:
+       case kone_mouse_event_osd_dpi:
+               kone->actual_dpi = event->value;
+               break;
+       }
+}
+
+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
@@ -928,50 +992,22 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
                return 0;
 
        /*
-        * Firmware 1.38 introduced new behaviour for tilt buttons.
-        * Pressed tilt button is reported in each movement event.
+        * Firmware 1.38 introduced new behaviour for tilt and special buttons.
+        * Pressed button is reported in each movement event.
         * Workaround sends only one event per press.
         */
-       if (kone->last_tilt_state == event->tilt)
-               event->tilt = 0;
+       if (memcmp(&kone->last_mouse_event.tilt, &event->tilt, 5))
+               memcpy(&kone->last_mouse_event, event,
+                               sizeof(struct kone_mouse_event));
        else
-               kone->last_tilt_state = event->tilt;
+               memset(&event->tilt, 0, 5);
 
-       /*
-        * handle special events and keep actual profile and dpi values
-        * up to date
-        */
-       switch (event->event) {
-       case kone_mouse_event_osd_dpi:
-               dev_dbg(&hdev->dev, "osd dpi event. actual dpi %d\n",
-                               event->value);
-               return 1; /* return 1 if event was handled */
-       case kone_mouse_event_switch_dpi:
-               kone->actual_dpi = event->value;
-               dev_dbg(&hdev->dev, "switched dpi to %d\n", event->value);
-               return 1;
-       case kone_mouse_event_osd_profile:
-               dev_dbg(&hdev->dev, "osd profile event. actual profile %d\n",
-                               event->value);
-               return 1;
-       case kone_mouse_event_switch_profile:
-               kone->actual_profile = event->value;
-               kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
-                               startup_dpi;
-               dev_dbg(&hdev->dev, "switched profile to %d\n", event->value);
-               return 1;
-       case kone_mouse_event_call_overlong_macro:
-               dev_dbg(&hdev->dev, "overlong macro called, button %d %s/%s\n",
-                               event->macro_key,
-                               kone->profiles[kone->actual_profile - 1].
-                               button_infos[event->macro_key].macro_set_name,
-                               kone->profiles[kone->actual_profile - 1].
-                               button_infos[event->macro_key].macro_name
-                               );
-               return 1;
-       }
+       kone_keep_values_up_to_date(kone, event);
+
+       if (kone->roccat_claimed)
+               kone_report_to_chrdev(kone, event);
 
-       return 0; /* do further processing */
+       return 0; /* always do further processing */
 }
 
 static const struct hid_device_id kone_devices[] = {
@@ -1002,6 +1038,6 @@ static void __exit kone_exit(void)
 module_init(kone_init);
 module_exit(kone_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Kone driver");
+MODULE_LICENSE("GPL v2");