aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-07-11 00:42:04 -0400
committerMarcel Holtmann <marcel@holtmann.org>2007-07-11 00:42:04 -0400
commitef222013fc8c1a2fcba5c7ab169be8ffcb778ec4 (patch)
tree706fb330afd783755eee511bd9182e507c88c5e6 /net
parent7dcca30a32aadb0520417521b0c44f42d09fe05c (diff)
[Bluetooth] Add hci_recv_fragment() helper function
Most drivers must handle fragmented HCI data packets and events. This patch adds a generic function for their reassembly to the Bluetooth core layer and thus allows to shrink the complexity of the drivers. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c97
1 files changed, 95 insertions, 2 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index aa4b56a8c3ea..9c71cffbc6b0 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev);
826int hci_register_dev(struct hci_dev *hdev) 826int hci_register_dev(struct hci_dev *hdev)
827{ 827{
828 struct list_head *head = &hci_dev_list, *p; 828 struct list_head *head = &hci_dev_list, *p;
829 int id = 0; 829 int i, id = 0;
830 830
831 BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); 831 BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner);
832 832
@@ -865,6 +865,9 @@ int hci_register_dev(struct hci_dev *hdev)
865 skb_queue_head_init(&hdev->cmd_q); 865 skb_queue_head_init(&hdev->cmd_q);
866 skb_queue_head_init(&hdev->raw_q); 866 skb_queue_head_init(&hdev->raw_q);
867 867
868 for (i = 0; i < 3; i++)
869 hdev->reassembly[i] = NULL;
870
868 init_waitqueue_head(&hdev->req_wait_q); 871 init_waitqueue_head(&hdev->req_wait_q);
869 init_MUTEX(&hdev->req_lock); 872 init_MUTEX(&hdev->req_lock);
870 873
@@ -889,6 +892,8 @@ EXPORT_SYMBOL(hci_register_dev);
889/* Unregister HCI device */ 892/* Unregister HCI device */
890int hci_unregister_dev(struct hci_dev *hdev) 893int hci_unregister_dev(struct hci_dev *hdev)
891{ 894{
895 int i;
896
892 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 897 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
893 898
894 hci_unregister_sysfs(hdev); 899 hci_unregister_sysfs(hdev);
@@ -899,9 +904,13 @@ int hci_unregister_dev(struct hci_dev *hdev)
899 904
900 hci_dev_do_close(hdev); 905 hci_dev_do_close(hdev);
901 906
907 for (i = 0; i < 3; i++)
908 kfree_skb(hdev->reassembly[i]);
909
902 hci_notify(hdev, HCI_DEV_UNREG); 910 hci_notify(hdev, HCI_DEV_UNREG);
903 911
904 __hci_dev_put(hdev); 912 __hci_dev_put(hdev);
913
905 return 0; 914 return 0;
906} 915}
907EXPORT_SYMBOL(hci_unregister_dev); 916EXPORT_SYMBOL(hci_unregister_dev);
@@ -922,6 +931,90 @@ int hci_resume_dev(struct hci_dev *hdev)
922} 931}
923EXPORT_SYMBOL(hci_resume_dev); 932EXPORT_SYMBOL(hci_resume_dev);
924 933
934/* Receive packet type fragment */
935#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2])
936
937int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
938{
939 if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
940 return -EILSEQ;
941
942 while (count) {
943 struct sk_buff *skb = __reassembly(hdev, type);
944 struct { int expect; } *scb;
945 int len = 0;
946
947 if (!skb) {
948 /* Start of the frame */
949
950 switch (type) {
951 case HCI_EVENT_PKT:
952 if (count >= HCI_EVENT_HDR_SIZE) {
953 struct hci_event_hdr *h = data;
954 len = HCI_EVENT_HDR_SIZE + h->plen;
955 } else
956 return -EILSEQ;
957 break;
958
959 case HCI_ACLDATA_PKT:
960 if (count >= HCI_ACL_HDR_SIZE) {
961 struct hci_acl_hdr *h = data;
962 len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
963 } else
964 return -EILSEQ;
965 break;
966
967 case HCI_SCODATA_PKT:
968 if (count >= HCI_SCO_HDR_SIZE) {
969 struct hci_sco_hdr *h = data;
970 len = HCI_SCO_HDR_SIZE + h->dlen;
971 } else
972 return -EILSEQ;
973 break;
974 }
975
976 skb = bt_skb_alloc(len, GFP_ATOMIC);
977 if (!skb) {
978 BT_ERR("%s no memory for packet", hdev->name);
979 return -ENOMEM;
980 }
981
982 skb->dev = (void *) hdev;
983 bt_cb(skb)->pkt_type = type;
984
985 __reassembly(hdev, type) = skb;
986
987 scb = (void *) skb->cb;
988 scb->expect = len;
989 } else {
990 /* Continuation */
991
992 scb = (void *) skb->cb;
993 len = scb->expect;
994 }
995
996 len = min(len, count);
997
998 memcpy(skb_put(skb, len), data, len);
999
1000 scb->expect -= len;
1001
1002 if (scb->expect == 0) {
1003 /* Complete frame */
1004
1005 __reassembly(hdev, type) = NULL;
1006
1007 bt_cb(skb)->pkt_type = type;
1008 hci_recv_frame(skb);
1009 }
1010
1011 count -= len; data += len;
1012 }
1013
1014 return 0;
1015}
1016EXPORT_SYMBOL(hci_recv_fragment);
1017
925/* ---- Interface to upper protocols ---- */ 1018/* ---- Interface to upper protocols ---- */
926 1019
927/* Register/Unregister protocols. 1020/* Register/Unregister protocols.
@@ -1029,7 +1122,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
1029 1122
1030 skb = bt_skb_alloc(len, GFP_ATOMIC); 1123 skb = bt_skb_alloc(len, GFP_ATOMIC);
1031 if (!skb) { 1124 if (!skb) {
1032 BT_ERR("%s Can't allocate memory for HCI command", hdev->name); 1125 BT_ERR("%s no memory for command", hdev->name);
1033 return -ENOMEM; 1126 return -ENOMEM;
1034 } 1127 }
1035 1128