Skip to content

Commit

Permalink
HID: logitech-hidpp: store the name of the device in struct hidpp
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Tissoires authored and Jiri Kosina committed Jan 9, 2015
1 parent f677bb1 commit 005b3f5
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions drivers/hid/hid-logitech-hidpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit 005b3f5

Please sign in to comment.