aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h3
-rw-r--r--net/bluetooth/hci_core.c148
2 files changed, 1 insertions, 150 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ad957f336ead..a056c2bfeb81 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -185,7 +185,6 @@ struct amp_assoc {
185 185
186#define HCI_MAX_PAGES 3 186#define HCI_MAX_PAGES 3
187 187
188#define NUM_REASSEMBLY 4
189struct hci_dev { 188struct hci_dev {
190 struct list_head list; 189 struct list_head list;
191 struct mutex lock; 190 struct mutex lock;
@@ -327,7 +326,6 @@ struct hci_dev {
327 struct sk_buff_head cmd_q; 326 struct sk_buff_head cmd_q;
328 327
329 struct sk_buff *sent_cmd; 328 struct sk_buff *sent_cmd;
330 struct sk_buff *reassembly[NUM_REASSEMBLY];
331 329
332 struct mutex req_lock; 330 struct mutex req_lock;
333 wait_queue_head_t req_wait_q; 331 wait_queue_head_t req_wait_q;
@@ -1012,7 +1010,6 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
1012void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 1010void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
1013 1011
1014int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); 1012int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb);
1015int hci_recv_stream_fragment(struct hci_dev *hdev, const void *data, int count);
1016 1013
1017void hci_init_sysfs(struct hci_dev *hdev); 1014void hci_init_sysfs(struct hci_dev *hdev);
1018void hci_conn_init_sysfs(struct hci_conn *conn); 1015void hci_conn_init_sysfs(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c9e7cafb245a..476709bd068a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3200,7 +3200,7 @@ EXPORT_SYMBOL(hci_register_dev);
3200/* Unregister HCI device */ 3200/* Unregister HCI device */
3201void hci_unregister_dev(struct hci_dev *hdev) 3201void hci_unregister_dev(struct hci_dev *hdev)
3202{ 3202{
3203 int i, id; 3203 int id;
3204 3204
3205 BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); 3205 BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
3206 3206
@@ -3214,9 +3214,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
3214 3214
3215 hci_dev_do_close(hdev); 3215 hci_dev_do_close(hdev);
3216 3216
3217 for (i = 0; i < NUM_REASSEMBLY; i++)
3218 kfree_skb(hdev->reassembly[i]);
3219
3220 cancel_work_sync(&hdev->power_on); 3217 cancel_work_sync(&hdev->power_on);
3221 3218
3222 if (!test_bit(HCI_INIT, &hdev->flags) && 3219 if (!test_bit(HCI_INIT, &hdev->flags) &&
@@ -3320,149 +3317,6 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
3320} 3317}
3321EXPORT_SYMBOL(hci_recv_frame); 3318EXPORT_SYMBOL(hci_recv_frame);
3322 3319
3323static int hci_reassembly(struct hci_dev *hdev, int type, const void *data,
3324 int count, __u8 index)
3325{
3326 int len = 0;
3327 int hlen = 0;
3328 int remain = count;
3329 struct sk_buff *skb;
3330 struct bt_skb_cb *scb;
3331
3332 if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
3333 index >= NUM_REASSEMBLY)
3334 return -EILSEQ;
3335
3336 skb = hdev->reassembly[index];
3337
3338 if (!skb) {
3339 switch (type) {
3340 case HCI_ACLDATA_PKT:
3341 len = HCI_MAX_FRAME_SIZE;
3342 hlen = HCI_ACL_HDR_SIZE;
3343 break;
3344 case HCI_EVENT_PKT:
3345 len = HCI_MAX_EVENT_SIZE;
3346 hlen = HCI_EVENT_HDR_SIZE;
3347 break;
3348 case HCI_SCODATA_PKT:
3349 len = HCI_MAX_SCO_SIZE;
3350 hlen = HCI_SCO_HDR_SIZE;
3351 break;
3352 }
3353
3354 skb = bt_skb_alloc(len, GFP_ATOMIC);
3355 if (!skb)
3356 return -ENOMEM;
3357
3358 scb = (void *) skb->cb;
3359 scb->expect = hlen;
3360 scb->pkt_type = type;
3361
3362 hdev->reassembly[index] = skb;
3363 }
3364
3365 while (count) {
3366 scb = (void *) skb->cb;
3367 len = min_t(uint, scb->expect, count);
3368
3369 memcpy(skb_put(skb, len), data, len);
3370
3371 count -= len;
3372 data += len;
3373 scb->expect -= len;
3374 remain = count;
3375
3376 switch (type) {
3377 case HCI_EVENT_PKT:
3378 if (skb->len == HCI_EVENT_HDR_SIZE) {
3379 struct hci_event_hdr *h = hci_event_hdr(skb);
3380 scb->expect = h->plen;
3381
3382 if (skb_tailroom(skb) < scb->expect) {
3383 kfree_skb(skb);
3384 hdev->reassembly[index] = NULL;
3385 return -ENOMEM;
3386 }
3387 }
3388 break;
3389
3390 case HCI_ACLDATA_PKT:
3391 if (skb->len == HCI_ACL_HDR_SIZE) {
3392 struct hci_acl_hdr *h = hci_acl_hdr(skb);
3393 scb->expect = __le16_to_cpu(h->dlen);
3394
3395 if (skb_tailroom(skb) < scb->expect) {
3396 kfree_skb(skb);
3397 hdev->reassembly[index] = NULL;
3398 return -ENOMEM;
3399 }
3400 }
3401 break;
3402
3403 case HCI_SCODATA_PKT:
3404 if (skb->len == HCI_SCO_HDR_SIZE) {
3405 struct hci_sco_hdr *h = hci_sco_hdr(skb);
3406 scb->expect = h->dlen;
3407
3408 if (skb_tailroom(skb) < scb->expect) {
3409 kfree_skb(skb);
3410 hdev->reassembly[index] = NULL;
3411 return -ENOMEM;
3412 }
3413 }
3414 break;
3415 }
3416
3417 if (scb->expect == 0) {
3418 /* Complete frame */
3419
3420 bt_cb(skb)->pkt_type = type;
3421 hci_recv_frame(hdev, skb);
3422
3423 hdev->reassembly[index] = NULL;
3424 return remain;
3425 }
3426 }
3427
3428 return remain;
3429}
3430
3431#define STREAM_REASSEMBLY 0
3432
3433int hci_recv_stream_fragment(struct hci_dev *hdev, const void *data, int count)
3434{
3435 int type;
3436 int rem = 0;
3437
3438 while (count) {
3439 struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
3440
3441 if (!skb) {
3442 const struct { char type; } *pkt;
3443
3444 /* Start of the frame */
3445 pkt = data;
3446 type = pkt->type;
3447
3448 data++;
3449 count--;
3450 } else
3451 type = bt_cb(skb)->pkt_type;
3452
3453 rem = hci_reassembly(hdev, type, data, count,
3454 STREAM_REASSEMBLY);
3455 if (rem < 0)
3456 return rem;
3457
3458 data += (count - rem);
3459 count = rem;
3460 }
3461
3462 return rem;
3463}
3464EXPORT_SYMBOL(hci_recv_stream_fragment);
3465
3466/* ---- Interface to upper protocols ---- */ 3320/* ---- Interface to upper protocols ---- */
3467 3321
3468int hci_register_cb(struct hci_cb *cb) 3322int hci_register_cb(struct hci_cb *cb)