|
@@ -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);
|