summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hidp/core.c
diff options
context:
space:
mode:
authorMichael Poole2010-02-05 18:23:43 +0100
committerMarcel Holtmann2010-02-05 18:50:05 +0100
commit15c697ce1c5b408c5e20dcdc6aea2968d1125b75 (patch)
tree3326cde1d106ed92046639e23bb81a9fc3b3f667 /net/bluetooth/hidp/core.c
parentBluetooth: Enter active mode before establishing a SCO link. (diff)
downloadkernel-qcow2-linux-15c697ce1c5b408c5e20dcdc6aea2968d1125b75.tar.gz
kernel-qcow2-linux-15c697ce1c5b408c5e20dcdc6aea2968d1125b75.tar.xz
kernel-qcow2-linux-15c697ce1c5b408c5e20dcdc6aea2968d1125b75.zip
Bluetooth: Keep a copy of each HID device's report descriptor
The report descriptor is read by user space (via the Service Discovery Protocol), so it is only available during the ioctl to connect. However, the HID probe function that needs the descriptor might not be called until a specific module is loaded. Keep a copy of the descriptor so it is available for later use. Signed-off-by: Michael Poole <mdpoole@troilus.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hidp/core.c')
-rw-r--r--net/bluetooth/hidp/core.c49
1 files changed, 24 insertions, 25 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 6cf526d06e21..fc6ec1e72652 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -703,29 +703,9 @@ static void hidp_close(struct hid_device *hid)
static int hidp_parse(struct hid_device *hid)
{
struct hidp_session *session = hid->driver_data;
- struct hidp_connadd_req *req = session->req;
- unsigned char *buf;
- int ret;
-
- buf = kmalloc(req->rd_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (copy_from_user(buf, req->rd_data, req->rd_size)) {
- kfree(buf);
- return -EFAULT;
- }
-
- ret = hid_parse_report(session->hid, buf, req->rd_size);
-
- kfree(buf);
-
- if (ret)
- return ret;
-
- session->req = NULL;
- return 0;
+ return hid_parse_report(session->hid, session->rd_data,
+ session->rd_size);
}
static int hidp_start(struct hid_device *hid)
@@ -770,12 +750,24 @@ static int hidp_setup_hid(struct hidp_session *session,
bdaddr_t src, dst;
int err;
+ session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
+ if (!session->rd_data)
+ return -ENOMEM;
+
+ if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
+ err = -EFAULT;
+ goto fault;
+ }
+ session->rd_size = req->rd_size;
+
hid = hid_allocate_device();
- if (IS_ERR(hid))
- return PTR_ERR(hid);
+ if (IS_ERR(hid)) {
+ err = PTR_ERR(hid);
+ goto fault;
+ }
session->hid = hid;
- session->req = req;
+
hid->driver_data = session;
baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
@@ -806,6 +798,10 @@ failed:
hid_destroy_device(hid);
session->hid = NULL;
+fault:
+ kfree(session->rd_data);
+ session->rd_data = NULL;
+
return err;
}
@@ -900,6 +896,9 @@ unlink:
session->hid = NULL;
}
+ kfree(session->rd_data);
+ session->rd_data = NULL;
+
purge:
skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit);