From 5c6ad8eee0a8c5fb4ba8b741008490da9eb66af6 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:00 +0900 Subject: Bluetooth: Added /proc/net/hidp via bt_procfs_init() Added /proc/net/hidp via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/hidp/sock.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hidp') diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a36..eca3889371c4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -25,6 +25,10 @@ #include "hidp.h" +static struct bt_sock_list hidp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) +}; + static int hidp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&hidp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&hidp_sk_list, sk); + return 0; } @@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register HIDP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HIDP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("HIDP socket layer initialized"); return 0; @@ -284,6 +303,7 @@ error: void __exit hidp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "hidp"); if (bt_sock_unregister(BTPROTO_HIDP) < 0) BT_ERR("Can't unregister HIDP socket"); -- cgit v1.2.3 From 4529eefad087f97b33c0f31984d924b1f15d7bae Mon Sep 17 00:00:00 2001 From: "Lamarque V. Souza" Date: Thu, 6 Dec 2012 12:39:55 -0200 Subject: HID: hidp: fallback to input session properly if hid is blacklisted 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 Acked-by: Gustavo Padovan Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 11 ++++++++--- include/linux/hid.h | 1 + net/bluetooth/hidp/core.c | 9 ++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/hidp') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a7550bb30836..2629d5240d63 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -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 */ @@ -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) { @@ -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; /* diff --git a/include/linux/hid.h b/include/linux/hid.h index 7e1f37db7582..abce7eb4f258 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -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 *); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ccd985da6518..1f4a32bb2971 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -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: @@ -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; } -- cgit v1.2.3