HID: logitech-hidpp: store the name of the device in struct hidpp
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Thu, 8 Jan 2015 19:37:12 +0000 (14:37 -0500)
committerJiri Kosina <jkosina@suse.cz>
Fri, 9 Jan 2015 10:29:39 +0000 (11:29 +0100)
If a disconnect occurs while getting the actual name of the device
(which can take several HID transactions), the name of the device will
be the hid name, provided by the Unifying Receiver.
This means that in some cases, the user space will see a different
name that what it usually sees when there is no disconnect.

We should store the name of the device in the struct hidpp. That way,
if a disconnect occurs while we are accessing the name,
hidpp_connect_event() can fail, and the input node is not created.

The input node will be created only if we have a connection which
lasts long enough to retrieve all the requested information:
name, protocol, and specific configuration.

Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Tested-by: Peter Wu <peter@lekensteyn.nl>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-logitech-hidpp.c

index cf5795552bccc874c13824919a48283d52c2fcf5..acb632db3bb55a3e26893ad5fe3cebe5c1744e06 100644 (file)
@@ -89,6 +89,7 @@ struct hidpp_device {
        struct hid_device *hid_dev;
        struct mutex send_mutex;
        void *send_receive_buf;
+       char *name;             /* will never be NULL and should not be freed */
        wait_queue_head_t wait;
        bool answer_available;
        u8 protocol_major;
@@ -1080,6 +1081,7 @@ static void hidpp_input_close(struct input_dev *dev)
 static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)
 {
        struct input_dev *input_dev = devm_input_allocate_device(&hdev->dev);
+       struct hidpp_device *hidpp = hid_get_drvdata(hdev);
 
        if (!input_dev)
                return NULL;
@@ -1088,7 +1090,7 @@ static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)
        input_dev->open = hidpp_input_open;
        input_dev->close = hidpp_input_close;
 
-       input_dev->name = hdev->name;
+       input_dev->name = hidpp->name;
        input_dev->phys = hdev->phys;
        input_dev->uniq = hdev->uniq;
        input_dev->id.bustype = hdev->bus;
@@ -1130,22 +1132,28 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
        hid_info(hdev, "HID++ %u.%u device connected.\n",
                 hidpp->protocol_major, hidpp->protocol_minor);
 
+       if (!hidpp->name || hidpp->name == hdev->name) {
+               name = hidpp_get_device_name(hidpp);
+               if (!name) {
+                       hid_err(hdev,
+                               "unable to retrieve the name of the device");
+                       return;
+               }
+
+               devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name);
+               kfree(name);
+               if (!devm_name)
+                       return;
+
+               hidpp->name = devm_name;
+       }
+
        input = hidpp_allocate_input(hdev);
        if (!input) {
                hid_err(hdev, "cannot allocate new input device: %d\n", ret);
                return;
        }
 
-       name = hidpp_get_device_name(hidpp);
-       if (!name) {
-               hid_err(hdev, "unable to retrieve the name of the device");
-       } else {
-               devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name);
-               if (devm_name)
-                       input->name = devm_name;
-               kfree(name);
-       }
-
        hidpp_populate_input(hidpp, input, false);
 
        ret = input_register_device(input);
@@ -1168,6 +1176,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                return -ENOMEM;
 
        hidpp->hid_dev = hdev;
+       hidpp->name = hdev->name;
        hid_set_drvdata(hdev, hidpp);
 
        hidpp->quirks = id->driver_data;