Skip to content

Commit

Permalink
HID: hidp: fallback to input session properly if hid is blacklisted
Browse files Browse the repository at this point in the history
This patch against kernel 3.7.0-rc8 fixes a kernel oops when turning on the
bluetooth mouse with id 0458:0058 [1].

The mouse in question supports both input and hid sessions, however it is
blacklisted in drivers/hid/hid-core.c so the input session is one that should
be used. Long ago (around kernel 3.0.0) some changes in the bluetooth
subsystem made the kernel do not fallback to input session when hid session is
not supported or blacklisted. This patch restore that behaviour by making the
kernel try the input session if hid_add_device returns ENODEV.

The patch exports hid_ignore() from hid-core.c so that it can be used in the
bluetooth subsystem.

[1] https://bugzilla.kernel.org/show_bug.cgi?id=39882

Signed-off-by: Lamarque V. Souza <lamarque@gmail.com>
Acked-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Lamarque V. Souza authored and Jiri Kosina committed Dec 7, 2012
1 parent ae751fa commit 4529eef
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 4 deletions.
11 changes: 8 additions & 3 deletions drivers/hid/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2145,8 +2145,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ }
};

static bool hid_ignore(struct hid_device *hdev)
bool hid_ignore(struct hid_device *hdev)
{
if (hdev->quirks & HID_QUIRK_NO_IGNORE)
return false;
if (hdev->quirks & HID_QUIRK_IGNORE)
return true;

switch (hdev->vendor) {
case USB_VENDOR_ID_CODEMERCS:
/* ignore all Code Mercenaries IOWarrior devices */
Expand Down Expand Up @@ -2201,6 +2206,7 @@ static bool hid_ignore(struct hid_device *hdev)

return !!hid_match_id(hdev, hid_ignore_list);
}
EXPORT_SYMBOL_GPL(hid_ignore);

int hid_add_device(struct hid_device *hdev)
{
Expand All @@ -2212,8 +2218,7 @@ int hid_add_device(struct hid_device *hdev)

/* we need to kill them here, otherwise they will stay allocated to
* wait for coming driver */
if (!(hdev->quirks & HID_QUIRK_NO_IGNORE)
&& (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
if (hid_ignore(hdev))
return -ENODEV;

/*
Expand Down
1 change: 1 addition & 0 deletions include/linux/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ struct hid_ll_driver {

extern int hid_debug;

extern bool hid_ignore(struct hid_device *);
extern int hid_add_device(struct hid_device *);
extern void hid_destroy_device(struct hid_device *);

Expand Down
9 changes: 8 additions & 1 deletion net/bluetooth/hidp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,13 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->hid_get_raw_report = hidp_get_raw_report;
hid->hid_output_raw_report = hidp_output_raw_report;

/* True if device is blacklisted in drivers/hid/hid-core.c */
if (hid_ignore(hid)) {
hid_destroy_device(session->hid);
session->hid = NULL;
return -ENODEV;
}

return 0;

fault:
Expand Down Expand Up @@ -1013,7 +1020,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,

if (req->rd_size > 0) {
err = hidp_setup_hid(session, req);
if (err)
if (err && err != -ENODEV)
goto purge;
}

Expand Down

0 comments on commit 4529eef

Please sign in to comment.