Merge branch 'for-4.20/cougar' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Tue, 23 Oct 2018 11:19:03 +0000 (13:19 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 23 Oct 2018 11:19:03 +0000 (13:19 +0200)
Functional fixes for hid-cougar driver

drivers/hid/hid-cougar.c

index ad2e87de7dc53ee2f2cf93e3e59a171b47d995b6..3f0916b64c60e9bd8fcf29b22386f2a6c7cd7649 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/printk.h>
 
 #include "hid-ids.h"
 
@@ -15,11 +16,9 @@ MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard");
 MODULE_LICENSE("GPL");
 MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18");
 
-static int cougar_g6_is_space = 1;
-module_param_named(g6_is_space, cougar_g6_is_space, int, 0600);
+static bool g6_is_space = true;
 MODULE_PARM_DESC(g6_is_space,
-       "If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)");
-
+       "If true, G6 programmable key sends SPACE instead of F18 (default=true)");
 
 #define COUGAR_VENDOR_USAGE    0xff00ff00
 
@@ -82,20 +81,23 @@ struct cougar {
 static LIST_HEAD(cougar_udev_list);
 static DEFINE_MUTEX(cougar_udev_list_lock);
 
-static void cougar_fix_g6_mapping(struct hid_device *hdev)
+/**
+ * cougar_fix_g6_mapping - configure the mapping for key G6/Spacebar
+ */
+static void cougar_fix_g6_mapping(void)
 {
        int i;
 
        for (i = 0; cougar_mapping[i][0]; i++) {
                if (cougar_mapping[i][0] == COUGAR_KEY_G6) {
                        cougar_mapping[i][1] =
-                               cougar_g6_is_space ? KEY_SPACE : KEY_F18;
-                       hid_info(hdev, "G6 mapped to %s\n",
-                                cougar_g6_is_space ? "space" : "F18");
+                               g6_is_space ? KEY_SPACE : KEY_F18;
+                       pr_info("cougar: G6 mapped to %s\n",
+                               g6_is_space ? "space" : "F18");
                        return;
                }
        }
-       hid_warn(hdev, "no mapping defined for G6/spacebar");
+       pr_warn("cougar: no mappings defined for G6/spacebar");
 }
 
 /*
@@ -154,7 +156,8 @@ static void cougar_remove_shared_data(void *resource)
  * Bind the device group's shared data to this cougar struct.
  * If no shared data exists for this group, create and initialize it.
  */
-static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar)
+static int cougar_bind_shared_data(struct hid_device *hdev,
+                                  struct cougar *cougar)
 {
        struct cougar_shared *shared;
        int error = 0;
@@ -228,7 +231,6 @@ static int cougar_probe(struct hid_device *hdev,
         * to it.
         */
        if (hdev->collection->usage == HID_GD_KEYBOARD) {
-               cougar_fix_g6_mapping(hdev);
                list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) {
                        if (hidinput->registered && hidinput->input != NULL) {
                                cougar->shared->input = hidinput->input;
@@ -237,6 +239,8 @@ static int cougar_probe(struct hid_device *hdev,
                        }
                }
        } else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+               /* Preinit the mapping table */
+               cougar_fix_g6_mapping();
                error = hid_hw_open(hdev);
                if (error)
                        goto fail_stop_and_cleanup;
@@ -257,26 +261,32 @@ static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report,
                            u8 *data, int size)
 {
        struct cougar *cougar;
+       struct cougar_shared *shared;
        unsigned char code, action;
        int i;
 
        cougar = hid_get_drvdata(hdev);
-       if (!cougar->special_intf || !cougar->shared ||
-           !cougar->shared->input || !cougar->shared->enabled)
+       shared = cougar->shared;
+       if (!cougar->special_intf || !shared)
                return 0;
 
+       if (!shared->enabled || !shared->input)
+               return -EPERM;
+
        code = data[COUGAR_FIELD_CODE];
        action = data[COUGAR_FIELD_ACTION];
        for (i = 0; cougar_mapping[i][0]; i++) {
                if (code == cougar_mapping[i][0]) {
-                       input_event(cougar->shared->input, EV_KEY,
+                       input_event(shared->input, EV_KEY,
                                    cougar_mapping[i][1], action);
-                       input_sync(cougar->shared->input);
-                       return 0;
+                       input_sync(shared->input);
+                       return -EPERM;
                }
        }
-       hid_warn(hdev, "unmapped special key code %x: ignoring\n", code);
-       return 0;
+       /* Avoid warnings on the same unmapped key twice */
+       if (action != 0)
+               hid_warn(hdev, "unmapped special key code %0x: ignoring\n", code);
+       return -EPERM;
 }
 
 static void cougar_remove(struct hid_device *hdev)
@@ -293,6 +303,26 @@ static void cougar_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
+static int cougar_param_set_g6_is_space(const char *val,
+                                       const struct kernel_param *kp)
+{
+       int ret;
+
+       ret = param_set_bool(val, kp);
+       if (ret)
+               return ret;
+
+       cougar_fix_g6_mapping();
+
+       return 0;
+}
+
+static const struct kernel_param_ops cougar_g6_is_space_ops = {
+       .set    = cougar_param_set_g6_is_space,
+       .get    = param_get_bool,
+};
+module_param_cb(g6_is_space, &cougar_g6_is_space_ops, &g6_is_space, 0644);
+
 static struct hid_device_id cougar_id_table[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
                         USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },