diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/bluetooth/hidp | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/bluetooth/hidp')
-rw-r--r-- | net/bluetooth/hidp/core.c | 137 | ||||
-rw-r--r-- | net/bluetooth/hidp/hidp.h | 4 | ||||
-rw-r--r-- | net/bluetooth/hidp/sock.c | 7 |
3 files changed, 86 insertions, 62 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 49d8495d69be..280529ad9274 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -243,6 +243,39 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) | |||
243 | input_sync(dev); | 243 | input_sync(dev); |
244 | } | 244 | } |
245 | 245 | ||
246 | static int __hidp_send_ctrl_message(struct hidp_session *session, | ||
247 | unsigned char hdr, unsigned char *data, int size) | ||
248 | { | ||
249 | struct sk_buff *skb; | ||
250 | |||
251 | BT_DBG("session %p data %p size %d", session, data, size); | ||
252 | |||
253 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { | ||
254 | BT_ERR("Can't allocate memory for new frame"); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | *skb_put(skb, 1) = hdr; | ||
259 | if (data && size > 0) | ||
260 | memcpy(skb_put(skb, size), data, size); | ||
261 | |||
262 | skb_queue_tail(&session->ctrl_transmit, skb); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static inline int hidp_send_ctrl_message(struct hidp_session *session, | ||
268 | unsigned char hdr, unsigned char *data, int size) | ||
269 | { | ||
270 | int err; | ||
271 | |||
272 | err = __hidp_send_ctrl_message(session, hdr, data, size); | ||
273 | |||
274 | hidp_schedule(session); | ||
275 | |||
276 | return err; | ||
277 | } | ||
278 | |||
246 | static int hidp_queue_report(struct hidp_session *session, | 279 | static int hidp_queue_report(struct hidp_session *session, |
247 | unsigned char *data, int size) | 280 | unsigned char *data, int size) |
248 | { | 281 | { |
@@ -280,6 +313,26 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep | |||
280 | return hidp_queue_report(session, buf, rsize); | 313 | return hidp_queue_report(session, buf, rsize); |
281 | } | 314 | } |
282 | 315 | ||
316 | static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, | ||
317 | unsigned char report_type) | ||
318 | { | ||
319 | switch (report_type) { | ||
320 | case HID_FEATURE_REPORT: | ||
321 | report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; | ||
322 | break; | ||
323 | case HID_OUTPUT_REPORT: | ||
324 | report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; | ||
325 | break; | ||
326 | default: | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | if (hidp_send_ctrl_message(hid->driver_data, report_type, | ||
331 | data, count)) | ||
332 | return -ENOMEM; | ||
333 | return count; | ||
334 | } | ||
335 | |||
283 | static void hidp_idle_timeout(unsigned long arg) | 336 | static void hidp_idle_timeout(unsigned long arg) |
284 | { | 337 | { |
285 | struct hidp_session *session = (struct hidp_session *) arg; | 338 | struct hidp_session *session = (struct hidp_session *) arg; |
@@ -300,39 +353,6 @@ static inline void hidp_del_timer(struct hidp_session *session) | |||
300 | del_timer(&session->timer); | 353 | del_timer(&session->timer); |
301 | } | 354 | } |
302 | 355 | ||
303 | static int __hidp_send_ctrl_message(struct hidp_session *session, | ||
304 | unsigned char hdr, unsigned char *data, int size) | ||
305 | { | ||
306 | struct sk_buff *skb; | ||
307 | |||
308 | BT_DBG("session %p data %p size %d", session, data, size); | ||
309 | |||
310 | if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { | ||
311 | BT_ERR("Can't allocate memory for new frame"); | ||
312 | return -ENOMEM; | ||
313 | } | ||
314 | |||
315 | *skb_put(skb, 1) = hdr; | ||
316 | if (data && size > 0) | ||
317 | memcpy(skb_put(skb, size), data, size); | ||
318 | |||
319 | skb_queue_tail(&session->ctrl_transmit, skb); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static inline int hidp_send_ctrl_message(struct hidp_session *session, | ||
325 | unsigned char hdr, unsigned char *data, int size) | ||
326 | { | ||
327 | int err; | ||
328 | |||
329 | err = __hidp_send_ctrl_message(session, hdr, data, size); | ||
330 | |||
331 | hidp_schedule(session); | ||
332 | |||
333 | return err; | ||
334 | } | ||
335 | |||
336 | static void hidp_process_handshake(struct hidp_session *session, | 356 | static void hidp_process_handshake(struct hidp_session *session, |
337 | unsigned char param) | 357 | unsigned char param) |
338 | { | 358 | { |
@@ -694,29 +714,9 @@ static void hidp_close(struct hid_device *hid) | |||
694 | static int hidp_parse(struct hid_device *hid) | 714 | static int hidp_parse(struct hid_device *hid) |
695 | { | 715 | { |
696 | struct hidp_session *session = hid->driver_data; | 716 | struct hidp_session *session = hid->driver_data; |
697 | struct hidp_connadd_req *req = session->req; | ||
698 | unsigned char *buf; | ||
699 | int ret; | ||
700 | |||
701 | buf = kmalloc(req->rd_size, GFP_KERNEL); | ||
702 | if (!buf) | ||
703 | return -ENOMEM; | ||
704 | |||
705 | if (copy_from_user(buf, req->rd_data, req->rd_size)) { | ||
706 | kfree(buf); | ||
707 | return -EFAULT; | ||
708 | } | ||
709 | |||
710 | ret = hid_parse_report(session->hid, buf, req->rd_size); | ||
711 | |||
712 | kfree(buf); | ||
713 | |||
714 | if (ret) | ||
715 | return ret; | ||
716 | 717 | ||
717 | session->req = NULL; | 718 | return hid_parse_report(session->hid, session->rd_data, |
718 | 719 | session->rd_size); | |
719 | return 0; | ||
720 | } | 720 | } |
721 | 721 | ||
722 | static int hidp_start(struct hid_device *hid) | 722 | static int hidp_start(struct hid_device *hid) |
@@ -761,12 +761,24 @@ static int hidp_setup_hid(struct hidp_session *session, | |||
761 | bdaddr_t src, dst; | 761 | bdaddr_t src, dst; |
762 | int err; | 762 | int err; |
763 | 763 | ||
764 | session->rd_data = kzalloc(req->rd_size, GFP_KERNEL); | ||
765 | if (!session->rd_data) | ||
766 | return -ENOMEM; | ||
767 | |||
768 | if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) { | ||
769 | err = -EFAULT; | ||
770 | goto fault; | ||
771 | } | ||
772 | session->rd_size = req->rd_size; | ||
773 | |||
764 | hid = hid_allocate_device(); | 774 | hid = hid_allocate_device(); |
765 | if (IS_ERR(hid)) | 775 | if (IS_ERR(hid)) { |
766 | return PTR_ERR(session->hid); | 776 | err = PTR_ERR(hid); |
777 | goto fault; | ||
778 | } | ||
767 | 779 | ||
768 | session->hid = hid; | 780 | session->hid = hid; |
769 | session->req = req; | 781 | |
770 | hid->driver_data = session; | 782 | hid->driver_data = session; |
771 | 783 | ||
772 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); | 784 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); |
@@ -785,6 +797,8 @@ static int hidp_setup_hid(struct hidp_session *session, | |||
785 | hid->dev.parent = hidp_get_device(session); | 797 | hid->dev.parent = hidp_get_device(session); |
786 | hid->ll_driver = &hidp_hid_driver; | 798 | hid->ll_driver = &hidp_hid_driver; |
787 | 799 | ||
800 | hid->hid_output_raw_report = hidp_output_raw_report; | ||
801 | |||
788 | err = hid_add_device(hid); | 802 | err = hid_add_device(hid); |
789 | if (err < 0) | 803 | if (err < 0) |
790 | goto failed; | 804 | goto failed; |
@@ -795,6 +809,10 @@ failed: | |||
795 | hid_destroy_device(hid); | 809 | hid_destroy_device(hid); |
796 | session->hid = NULL; | 810 | session->hid = NULL; |
797 | 811 | ||
812 | fault: | ||
813 | kfree(session->rd_data); | ||
814 | session->rd_data = NULL; | ||
815 | |||
798 | return err; | 816 | return err; |
799 | } | 817 | } |
800 | 818 | ||
@@ -889,6 +907,9 @@ unlink: | |||
889 | session->hid = NULL; | 907 | session->hid = NULL; |
890 | } | 908 | } |
891 | 909 | ||
910 | kfree(session->rd_data); | ||
911 | session->rd_data = NULL; | ||
912 | |||
892 | purge: | 913 | purge: |
893 | skb_queue_purge(&session->ctrl_transmit); | 914 | skb_queue_purge(&session->ctrl_transmit); |
894 | skb_queue_purge(&session->intr_transmit); | 915 | 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 | ||
160 | static inline void hidp_schedule(struct hidp_session *session) | 162 | static inline void hidp_schedule(struct hidp_session *session) |
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 37c9d7d2e688..250dfd46237d 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/capability.h> | 26 | #include <linux/capability.h> |
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/slab.h> | ||
30 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
31 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
32 | #include <linux/skbuff.h> | 31 | #include <linux/skbuff.h> |
@@ -35,6 +34,7 @@ | |||
35 | #include <linux/file.h> | 34 | #include <linux/file.h> |
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/compat.h> | 36 | #include <linux/compat.h> |
37 | #include <linux/gfp.h> | ||
38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
39 | 39 | ||
40 | #include "hidp.h" | 40 | #include "hidp.h" |
@@ -241,7 +241,8 @@ static struct proto hidp_proto = { | |||
241 | .obj_size = sizeof(struct bt_sock) | 241 | .obj_size = sizeof(struct bt_sock) |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static int hidp_sock_create(struct net *net, struct socket *sock, int protocol) | 244 | static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, |
245 | int kern) | ||
245 | { | 246 | { |
246 | struct sock *sk; | 247 | struct sock *sk; |
247 | 248 | ||
@@ -268,7 +269,7 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol) | |||
268 | return 0; | 269 | return 0; |
269 | } | 270 | } |
270 | 271 | ||
271 | static struct net_proto_family hidp_sock_family_ops = { | 272 | static const struct net_proto_family hidp_sock_family_ops = { |
272 | .family = PF_BLUETOOTH, | 273 | .family = PF_BLUETOOTH, |
273 | .owner = THIS_MODULE, | 274 | .owner = THIS_MODULE, |
274 | .create = hidp_sock_create | 275 | .create = hidp_sock_create |