aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Poole <mdpoole@troilus.org>2010-02-05 12:23:43 -0500
committerMarcel Holtmann <marcel@holtmann.org>2010-02-05 12:50:05 -0500
commit15c697ce1c5b408c5e20dcdc6aea2968d1125b75 (patch)
tree3326cde1d106ed92046639e23bb81a9fc3b3f667
parentc390216b3e868b16d8154939f4b6f8c16dbd9a9f (diff)
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>
-rw-r--r--net/bluetooth/hidp/core.c49
-rw-r--r--net/bluetooth/hidp/hidp.h4
2 files changed, 27 insertions, 26 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)
703static int hidp_parse(struct hid_device *hid) 703static int hidp_parse(struct hid_device *hid)
704{ 704{
705 struct hidp_session *session = hid->driver_data; 705 struct hidp_session *session = hid->driver_data;
706 struct hidp_connadd_req *req = session->req;
707 unsigned char *buf;
708 int ret;
709
710 buf = kmalloc(req->rd_size, GFP_KERNEL);
711 if (!buf)
712 return -ENOMEM;
713
714 if (copy_from_user(buf, req->rd_data, req->rd_size)) {
715 kfree(buf);
716 return -EFAULT;
717 }
718
719 ret = hid_parse_report(session->hid, buf, req->rd_size);
720
721 kfree(buf);
722
723 if (ret)
724 return ret;
725
726 session->req = NULL;
727 706
728 return 0; 707 return hid_parse_report(session->hid, session->rd_data,
708 session->rd_size);
729} 709}
730 710
731static int hidp_start(struct hid_device *hid) 711static int hidp_start(struct hid_device *hid)
@@ -770,12 +750,24 @@ static int hidp_setup_hid(struct hidp_session *session,
770 bdaddr_t src, dst; 750 bdaddr_t src, dst;
771 int err; 751 int err;
772 752
753 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
754 if (!session->rd_data)
755 return -ENOMEM;
756
757 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
758 err = -EFAULT;
759 goto fault;
760 }
761 session->rd_size = req->rd_size;
762
773 hid = hid_allocate_device(); 763 hid = hid_allocate_device();
774 if (IS_ERR(hid)) 764 if (IS_ERR(hid)) {
775 return PTR_ERR(hid); 765 err = PTR_ERR(hid);
766 goto fault;
767 }
776 768
777 session->hid = hid; 769 session->hid = hid;
778 session->req = req; 770
779 hid->driver_data = session; 771 hid->driver_data = session;
780 772
781 baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); 773 baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
@@ -806,6 +798,10 @@ failed:
806 hid_destroy_device(hid); 798 hid_destroy_device(hid);
807 session->hid = NULL; 799 session->hid = NULL;
808 800
801fault:
802 kfree(session->rd_data);
803 session->rd_data = NULL;
804
809 return err; 805 return err;
810} 806}
811 807
@@ -900,6 +896,9 @@ unlink:
900 session->hid = NULL; 896 session->hid = NULL;
901 } 897 }
902 898
899 kfree(session->rd_data);
900 session->rd_data = NULL;
901
903purge: 902purge:
904 skb_queue_purge(&session->ctrl_transmit); 903 skb_queue_purge(&session->ctrl_transmit);
905 skb_queue_purge(&session->intr_transmit); 904 skb_queue_purge(&session->intr_transmit);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index faf3d74c3586..a4e215d50c10 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -154,7 +154,9 @@ struct hidp_session {
154 struct sk_buff_head ctrl_transmit; 154 struct sk_buff_head ctrl_transmit;
155 struct sk_buff_head intr_transmit; 155 struct sk_buff_head intr_transmit;
156 156
157 struct hidp_connadd_req *req; 157 /* Report descriptor */
158 __u8 *rd_data;
159 uint rd_size;
158}; 160};
159 161
160static inline void hidp_schedule(struct hidp_session *session) 162static inline void hidp_schedule(struct hidp_session *session)