aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hidp/core.c214
-rw-r--r--net/bluetooth/hidp/hidp.h2
2 files changed, 133 insertions, 83 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 96434d774c84..acdeab3d9807 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -578,7 +578,7 @@ static int hidp_session(void *arg)
578 if (session->hid) { 578 if (session->hid) {
579 if (session->hid->claimed & HID_CLAIMED_INPUT) 579 if (session->hid->claimed & HID_CLAIMED_INPUT)
580 hidinput_disconnect(session->hid); 580 hidinput_disconnect(session->hid);
581 hid_free_device(session->hid); 581 hid_destroy_device(session->hid);
582 } 582 }
583 583
584 /* Wakeup user-space polling for socket errors */ 584 /* Wakeup user-space polling for socket errors */
@@ -623,9 +623,15 @@ static struct device *hidp_get_device(struct hidp_session *session)
623static int hidp_setup_input(struct hidp_session *session, 623static int hidp_setup_input(struct hidp_session *session,
624 struct hidp_connadd_req *req) 624 struct hidp_connadd_req *req)
625{ 625{
626 struct input_dev *input = session->input; 626 struct input_dev *input;
627 int i; 627 int i;
628 628
629 input = input_allocate_device();
630 if (!input)
631 return -ENOMEM;
632
633 session->input = input;
634
629 input_set_drvdata(input, session); 635 input_set_drvdata(input, session);
630 636
631 input->name = "Bluetooth HID Boot Protocol Device"; 637 input->name = "Bluetooth HID Boot Protocol Device";
@@ -677,67 +683,114 @@ static void hidp_close(struct hid_device *hid)
677{ 683{
678} 684}
679 685
680static const struct { 686static int hidp_parse(struct hid_device *hid)
681 __u16 idVendor; 687{
682 __u16 idProduct; 688 struct hidp_session *session = hid->driver_data;
683 unsigned quirks; 689 struct hidp_connadd_req *req = session->req;
684} hidp_blacklist[] = { 690 unsigned char *buf;
685 /* Apple wireless Mighty Mouse */ 691 int ret;
686 { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
687 692
688 { } /* Terminating entry */ 693 buf = kmalloc(req->rd_size, GFP_KERNEL);
689}; 694 if (!buf)
695 return -ENOMEM;
696
697 if (copy_from_user(buf, req->rd_data, req->rd_size)) {
698 kfree(buf);
699 return -EFAULT;
700 }
701
702 ret = hid_parse_report(session->hid, buf, req->rd_size);
703
704 kfree(buf);
705
706 if (ret)
707 return ret;
708
709 session->req = NULL;
710
711 return 0;
712}
713
714static int hidp_start(struct hid_device *hid)
715{
716 struct hidp_session *session = hid->driver_data;
717 struct hid_report *report;
690 718
691static void hidp_setup_quirks(struct hid_device *hid) 719 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
720 report_list, list)
721 hidp_send_report(session, report);
722
723 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
724 report_list, list)
725 hidp_send_report(session, report);
726
727 return 0;
728}
729
730static void hidp_stop(struct hid_device *hid)
692{ 731{
693 unsigned int n; 732 struct hidp_session *session = hid->driver_data;
733
734 skb_queue_purge(&session->ctrl_transmit);
735 skb_queue_purge(&session->intr_transmit);
694 736
695 for (n = 0; hidp_blacklist[n].idVendor; n++) 737 if (hid->claimed & HID_CLAIMED_INPUT)
696 if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) && 738 hidinput_disconnect(hid);
697 hidp_blacklist[n].idProduct == le16_to_cpu(hid->product)) 739 hid->claimed = 0;
698 hid->quirks = hidp_blacklist[n].quirks;
699} 740}
700 741
701static void hidp_setup_hid(struct hidp_session *session, 742static struct hid_ll_driver hidp_hid_driver = {
743 .parse = hidp_parse,
744 .start = hidp_start,
745 .stop = hidp_stop,
746 .open = hidp_open,
747 .close = hidp_close,
748 .hidinput_input_event = hidp_hidinput_event,
749};
750
751static int hidp_setup_hid(struct hidp_session *session,
702 struct hidp_connadd_req *req) 752 struct hidp_connadd_req *req)
703{ 753{
704 struct hid_device *hid = session->hid; 754 struct hid_device *hid;
705 struct hid_report *report;
706 bdaddr_t src, dst; 755 bdaddr_t src, dst;
756 int ret;
707 757
708 baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); 758 hid = hid_allocate_device();
709 baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); 759 if (IS_ERR(hid)) {
760 ret = PTR_ERR(session->hid);
761 goto err;
762 }
710 763
764 session->hid = hid;
765 session->req = req;
711 hid->driver_data = session; 766 hid->driver_data = session;
712 767
713 hid->country = req->country; 768 baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
769 baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
714 770
715 hid->bus = BUS_BLUETOOTH; 771 hid->bus = BUS_BLUETOOTH;
716 hid->vendor = req->vendor; 772 hid->vendor = req->vendor;
717 hid->product = req->product; 773 hid->product = req->product;
718 hid->version = req->version; 774 hid->version = req->version;
775 hid->country = req->country;
719 776
720 strncpy(hid->name, req->name, 128); 777 strncpy(hid->name, req->name, 128);
721 strncpy(hid->phys, batostr(&src), 64); 778 strncpy(hid->phys, batostr(&src), 64);
722 strncpy(hid->uniq, batostr(&dst), 64); 779 strncpy(hid->uniq, batostr(&dst), 64);
723 780
724 hid->dev = hidp_get_device(session); 781 hid->dev.parent = hidp_get_device(session);
725 782 hid->ll_driver = &hidp_hid_driver;
726 hid->hid_open = hidp_open;
727 hid->hid_close = hidp_close;
728
729 hid->hidinput_input_event = hidp_hidinput_event;
730 783
731 hidp_setup_quirks(hid); 784 ret = hid_add_device(hid);
785 if (ret)
786 goto err_hid;
732 787
733 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) 788 return 0;
734 hidp_send_report(session, report); 789err_hid:
735 790 hid_destroy_device(hid);
736 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) 791 session->hid = NULL;
737 hidp_send_report(session, report); 792err:
738 793 return ret;
739 if (hidinput_connect(hid) == 0)
740 hid->claimed |= HID_CLAIMED_INPUT;
741} 794}
742 795
743int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) 796int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -757,38 +810,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
757 810
758 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size); 811 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
759 812
760 if (req->rd_size > 0) {
761 unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
762
763 if (!buf) {
764 kfree(session);
765 return -ENOMEM;
766 }
767
768 if (copy_from_user(buf, req->rd_data, req->rd_size)) {
769 kfree(buf);
770 kfree(session);
771 return -EFAULT;
772 }
773
774 session->hid = hid_parse_report(buf, req->rd_size);
775
776 kfree(buf);
777
778 if (!session->hid) {
779 kfree(session);
780 return -EINVAL;
781 }
782 }
783
784 if (!session->hid) {
785 session->input = input_allocate_device();
786 if (!session->input) {
787 kfree(session);
788 return -ENOMEM;
789 }
790 }
791
792 down_write(&hidp_session_sem); 813 down_write(&hidp_session_sem);
793 814
794 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); 815 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
@@ -816,15 +837,18 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
816 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); 837 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
817 session->idle_to = req->idle_to; 838 session->idle_to = req->idle_to;
818 839
819 if (session->input) { 840 if (req->rd_size > 0) {
841 err = hidp_setup_hid(session, req);
842 if (err && err != -ENODEV)
843 goto err_skb;
844 }
845
846 if (!session->hid) {
820 err = hidp_setup_input(session, req); 847 err = hidp_setup_input(session, req);
821 if (err < 0) 848 if (err < 0)
822 goto failed; 849 goto err_skb;
823 } 850 }
824 851
825 if (session->hid)
826 hidp_setup_hid(session, req);
827
828 __hidp_link_session(session); 852 __hidp_link_session(session);
829 853
830 hidp_set_timer(session); 854 hidp_set_timer(session);
@@ -850,17 +874,16 @@ unlink:
850 874
851 __hidp_unlink_session(session); 875 __hidp_unlink_session(session);
852 876
853 if (session->input) { 877 if (session->input)
854 input_unregister_device(session->input); 878 input_unregister_device(session->input);
855 session->input = NULL; /* don't try to free it here */ 879 if (session->hid)
856 } 880 hid_destroy_device(session->hid);
857 881err_skb:
882 skb_queue_purge(&session->ctrl_transmit);
883 skb_queue_purge(&session->intr_transmit);
858failed: 884failed:
859 up_write(&hidp_session_sem); 885 up_write(&hidp_session_sem);
860 886
861 if (session->hid)
862 hid_free_device(session->hid);
863
864 input_free_device(session->input); 887 input_free_device(session->input);
865 kfree(session); 888 kfree(session);
866 return err; 889 return err;
@@ -950,18 +973,43 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
950 return err; 973 return err;
951} 974}
952 975
976static const struct hid_device_id hidp_table[] = {
977 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
978 { }
979};
980
981static struct hid_driver hidp_driver = {
982 .name = "generic-bluetooth",
983 .id_table = hidp_table,
984};
985
953static int __init hidp_init(void) 986static int __init hidp_init(void)
954{ 987{
988 int ret;
989
955 l2cap_load(); 990 l2cap_load();
956 991
957 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); 992 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
958 993
959 return hidp_init_sockets(); 994 ret = hid_register_driver(&hidp_driver);
995 if (ret)
996 goto err;
997
998 ret = hidp_init_sockets();
999 if (ret)
1000 goto err_drv;
1001
1002 return 0;
1003err_drv:
1004 hid_unregister_driver(&hidp_driver);
1005err:
1006 return ret;
960} 1007}
961 1008
962static void __exit hidp_exit(void) 1009static void __exit hidp_exit(void)
963{ 1010{
964 hidp_cleanup_sockets(); 1011 hidp_cleanup_sockets();
1012 hid_unregister_driver(&hidp_driver);
965} 1013}
966 1014
967module_init(hidp_init); 1015module_init(hidp_init);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 343fb0566b3e..e503c89057ad 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -151,6 +151,8 @@ struct hidp_session {
151 151
152 struct sk_buff_head ctrl_transmit; 152 struct sk_buff_head ctrl_transmit;
153 struct sk_buff_head intr_transmit; 153 struct sk_buff_head intr_transmit;
154
155 struct hidp_connadd_req *req;
154}; 156};
155 157
156static inline void hidp_schedule(struct hidp_session *session) 158static inline void hidp_schedule(struct hidp_session *session)