diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hidp/core.c | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 96434d774c84..56a51f91591a 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 */ |
@@ -698,12 +698,13 @@ static void hidp_setup_quirks(struct hid_device *hid) | |||
698 | hid->quirks = hidp_blacklist[n].quirks; | 698 | hid->quirks = hidp_blacklist[n].quirks; |
699 | } | 699 | } |
700 | 700 | ||
701 | static void hidp_setup_hid(struct hidp_session *session, | 701 | static int hidp_setup_hid(struct hidp_session *session, |
702 | struct hidp_connadd_req *req) | 702 | struct hidp_connadd_req *req) |
703 | { | 703 | { |
704 | struct hid_device *hid = session->hid; | 704 | struct hid_device *hid = session->hid; |
705 | struct hid_report *report; | 705 | struct hid_report *report; |
706 | bdaddr_t src, dst; | 706 | bdaddr_t src, dst; |
707 | int ret; | ||
707 | 708 | ||
708 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); | 709 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); |
709 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); | 710 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); |
@@ -721,7 +722,7 @@ static void hidp_setup_hid(struct hidp_session *session, | |||
721 | strncpy(hid->phys, batostr(&src), 64); | 722 | strncpy(hid->phys, batostr(&src), 64); |
722 | strncpy(hid->uniq, batostr(&dst), 64); | 723 | strncpy(hid->uniq, batostr(&dst), 64); |
723 | 724 | ||
724 | hid->dev = hidp_get_device(session); | 725 | hid->dev.parent = hidp_get_device(session); |
725 | 726 | ||
726 | hid->hid_open = hidp_open; | 727 | hid->hid_open = hidp_open; |
727 | hid->hid_close = hidp_close; | 728 | hid->hid_close = hidp_close; |
@@ -738,6 +739,15 @@ static void hidp_setup_hid(struct hidp_session *session, | |||
738 | 739 | ||
739 | if (hidinput_connect(hid) == 0) | 740 | if (hidinput_connect(hid) == 0) |
740 | hid->claimed |= HID_CLAIMED_INPUT; | 741 | hid->claimed |= HID_CLAIMED_INPUT; |
742 | |||
743 | ret = hid_add_device(hid); | ||
744 | if (ret) { | ||
745 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
746 | hidinput_disconnect(hid); | ||
747 | skb_queue_purge(&session->intr_transmit); | ||
748 | } | ||
749 | |||
750 | return ret; | ||
741 | } | 751 | } |
742 | 752 | ||
743 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) | 753 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) |
@@ -771,11 +781,19 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
771 | return -EFAULT; | 781 | return -EFAULT; |
772 | } | 782 | } |
773 | 783 | ||
774 | session->hid = hid_parse_report(buf, req->rd_size); | 784 | session->hid = hid_allocate_device(); |
785 | if (IS_ERR(session->hid)) { | ||
786 | kfree(buf); | ||
787 | kfree(session); | ||
788 | return PTR_ERR(session->hid); | ||
789 | } | ||
790 | |||
791 | err = hid_parse_report(session->hid, buf, req->rd_size); | ||
775 | 792 | ||
776 | kfree(buf); | 793 | kfree(buf); |
777 | 794 | ||
778 | if (!session->hid) { | 795 | if (err) { |
796 | hid_destroy_device(session->hid); | ||
779 | kfree(session); | 797 | kfree(session); |
780 | return -EINVAL; | 798 | return -EINVAL; |
781 | } | 799 | } |
@@ -822,8 +840,11 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
822 | goto failed; | 840 | goto failed; |
823 | } | 841 | } |
824 | 842 | ||
825 | if (session->hid) | 843 | if (session->hid) { |
826 | hidp_setup_hid(session, req); | 844 | err = hidp_setup_hid(session, req); |
845 | if (err) | ||
846 | goto failed; | ||
847 | } | ||
827 | 848 | ||
828 | __hidp_link_session(session); | 849 | __hidp_link_session(session); |
829 | 850 | ||
@@ -859,7 +880,7 @@ failed: | |||
859 | up_write(&hidp_session_sem); | 880 | up_write(&hidp_session_sem); |
860 | 881 | ||
861 | if (session->hid) | 882 | if (session->hid) |
862 | hid_free_device(session->hid); | 883 | hid_destroy_device(session->hid); |
863 | 884 | ||
864 | input_free_device(session->input); | 885 | input_free_device(session->input); |
865 | kfree(session); | 886 | kfree(session); |
@@ -950,18 +971,43 @@ int hidp_get_conninfo(struct hidp_conninfo *ci) | |||
950 | return err; | 971 | return err; |
951 | } | 972 | } |
952 | 973 | ||
974 | static const struct hid_device_id hidp_table[] = { | ||
975 | { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) }, | ||
976 | { } | ||
977 | }; | ||
978 | |||
979 | static struct hid_driver hidp_driver = { | ||
980 | .name = "generic-bluetooth", | ||
981 | .id_table = hidp_table, | ||
982 | }; | ||
983 | |||
953 | static int __init hidp_init(void) | 984 | static int __init hidp_init(void) |
954 | { | 985 | { |
986 | int ret; | ||
987 | |||
955 | l2cap_load(); | 988 | l2cap_load(); |
956 | 989 | ||
957 | BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); | 990 | BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); |
958 | 991 | ||
959 | return hidp_init_sockets(); | 992 | ret = hid_register_driver(&hidp_driver); |
993 | if (ret) | ||
994 | goto err; | ||
995 | |||
996 | ret = hidp_init_sockets(); | ||
997 | if (ret) | ||
998 | goto err_drv; | ||
999 | |||
1000 | return 0; | ||
1001 | err_drv: | ||
1002 | hid_unregister_driver(&hidp_driver); | ||
1003 | err: | ||
1004 | return ret; | ||
960 | } | 1005 | } |
961 | 1006 | ||
962 | static void __exit hidp_exit(void) | 1007 | static void __exit hidp_exit(void) |
963 | { | 1008 | { |
964 | hidp_cleanup_sockets(); | 1009 | hidp_cleanup_sockets(); |
1010 | hid_unregister_driver(&hidp_driver); | ||
965 | } | 1011 | } |
966 | 1012 | ||
967 | module_init(hidp_init); | 1013 | module_init(hidp_init); |