Skip to content

Commit

Permalink
Bluetooth: Keep a copy of each HID device's report descriptor
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
  • Loading branch information
entrope authored and holtmann committed Feb 5, 2010
1 parent c390216 commit 15c697c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 26 deletions.
49 changes: 24 additions & 25 deletions net/bluetooth/hidp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -806,6 +798,10 @@ static int hidp_setup_hid(struct hidp_session *session,
hid_destroy_device(hid);
session->hid = NULL;

fault:
kfree(session->rd_data);
session->rd_data = NULL;

return err;
}

Expand Down Expand Up @@ -900,6 +896,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
session->hid = NULL;
}

kfree(session->rd_data);
session->rd_data = NULL;

purge:
skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit);
Expand Down
4 changes: 3 additions & 1 deletion net/bluetooth/hidp/hidp.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ struct hidp_session {
struct sk_buff_head ctrl_transmit;
struct sk_buff_head intr_transmit;

struct hidp_connadd_req *req;
/* Report descriptor */
__u8 *rd_data;
uint rd_size;
};

static inline void hidp_schedule(struct hidp_session *session)
Expand Down

0 comments on commit 15c697c

Please sign in to comment.