aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorSuraj Sumangala <suraj@atheros.com>2010-07-14 03:32:18 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-21 13:39:12 -0400
commitf39a3c06404d01ef2ce47e821bc778dfb1836df9 (patch)
treeb27dfd8c823bf6ed8c520f8fc84e361cba24238a /net/bluetooth
parent33e882a5f2301a23a85ef2994e30fd9f48d39d9b (diff)
Bluetooth: Modified hci_recv_fragment() to use hci_reassembly helper
Modified packet based reassembly function hci_recv_fragment() to use hci_reassembly() Signed-off-by: Suraj Sumangala <suraj@atheros.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c85
1 files changed, 11 insertions, 74 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 477c4a60a079..451e266840ad 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1142,87 +1142,24 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
1142 return remain; 1142 return remain;
1143} 1143}
1144 1144
1145/* Receive packet type fragment */
1146#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 1])
1147
1148int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) 1145int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
1149{ 1146{
1147 int rem = 0;
1148
1150 if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) 1149 if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
1151 return -EILSEQ; 1150 return -EILSEQ;
1152 1151
1153 while (count) { 1152 do {
1154 struct sk_buff *skb = __reassembly(hdev, type); 1153 rem = hci_reassembly(hdev, type, data, count,
1155 struct { int expect; } *scb; 1154 type - 1, GFP_ATOMIC);
1156 int len = 0; 1155 if (rem < 0)
1157 1156 return rem;
1158 if (!skb) {
1159 /* Start of the frame */
1160
1161 switch (type) {
1162 case HCI_EVENT_PKT:
1163 if (count >= HCI_EVENT_HDR_SIZE) {
1164 struct hci_event_hdr *h = data;
1165 len = HCI_EVENT_HDR_SIZE + h->plen;
1166 } else
1167 return -EILSEQ;
1168 break;
1169
1170 case HCI_ACLDATA_PKT:
1171 if (count >= HCI_ACL_HDR_SIZE) {
1172 struct hci_acl_hdr *h = data;
1173 len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
1174 } else
1175 return -EILSEQ;
1176 break;
1177
1178 case HCI_SCODATA_PKT:
1179 if (count >= HCI_SCO_HDR_SIZE) {
1180 struct hci_sco_hdr *h = data;
1181 len = HCI_SCO_HDR_SIZE + h->dlen;
1182 } else
1183 return -EILSEQ;
1184 break;
1185 }
1186
1187 skb = bt_skb_alloc(len, GFP_ATOMIC);
1188 if (!skb) {
1189 BT_ERR("%s no memory for packet", hdev->name);
1190 return -ENOMEM;
1191 }
1192
1193 skb->dev = (void *) hdev;
1194 bt_cb(skb)->pkt_type = type;
1195
1196 __reassembly(hdev, type) = skb;
1197
1198 scb = (void *) skb->cb;
1199 scb->expect = len;
1200 } else {
1201 /* Continuation */
1202
1203 scb = (void *) skb->cb;
1204 len = scb->expect;
1205 }
1206
1207 len = min(len, count);
1208
1209 memcpy(skb_put(skb, len), data, len);
1210
1211 scb->expect -= len;
1212
1213 if (scb->expect == 0) {
1214 /* Complete frame */
1215 1157
1216 __reassembly(hdev, type) = NULL; 1158 data += (count - rem);
1159 count = rem;
1160 } while (count);
1217 1161
1218 bt_cb(skb)->pkt_type = type; 1162 return rem;
1219 hci_recv_frame(skb);
1220 }
1221
1222 count -= len; data += len;
1223 }
1224
1225 return 0;
1226} 1163}
1227EXPORT_SYMBOL(hci_recv_fragment); 1164EXPORT_SYMBOL(hci_recv_fragment);
1228 1165