aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-01-04 05:41:58 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-13 10:01:20 -0500
commit25e89e99b4a54a2cb6e27b4675cd71a3d8a9b3fc (patch)
treecaa527d1692f5679b4f6923ac96161cdd58477f2 /net/bluetooth/hci_event.c
parent5e41862322388224eef7ce221c8772489e3aa39a (diff)
Bluetooth: Process num completed data blocks event
Adds support for Number Of Completed Data Blocks Event. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 089dff80ccb0..0466ed9c1b47 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2408,6 +2408,56 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
2408 queue_work(hdev->workqueue, &hdev->tx_work); 2408 queue_work(hdev->workqueue, &hdev->tx_work);
2409} 2409}
2410 2410
2411static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev,
2412 struct sk_buff *skb)
2413{
2414 struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
2415 int i;
2416
2417 if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
2418 BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
2419 return;
2420 }
2421
2422 if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) +
2423 ev->num_hndl * sizeof(struct hci_comp_blocks_info)) {
2424 BT_DBG("%s bad parameters", hdev->name);
2425 return;
2426 }
2427
2428 BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
2429 ev->num_hndl);
2430
2431 for (i = 0; i < ev->num_hndl; i++) {
2432 struct hci_comp_blocks_info *info = &ev->handles[i];
2433 struct hci_conn *conn;
2434 __u16 handle, block_count;
2435
2436 handle = __le16_to_cpu(info->handle);
2437 block_count = __le16_to_cpu(info->blocks);
2438
2439 conn = hci_conn_hash_lookup_handle(hdev, handle);
2440 if (!conn)
2441 continue;
2442
2443 conn->sent -= block_count;
2444
2445 switch (conn->type) {
2446 case ACL_LINK:
2447 hdev->block_cnt += block_count;
2448 if (hdev->block_cnt > hdev->num_blocks)
2449 hdev->block_cnt = hdev->num_blocks;
2450 break;
2451
2452 default:
2453 BT_ERR("Unknown type %d conn %p", conn->type, conn);
2454 break;
2455 }
2456 }
2457
2458 queue_work(hdev->workqueue, &hdev->tx_work);
2459}
2460
2411static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2461static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
2412{ 2462{
2413 struct hci_ev_mode_change *ev = (void *) skb->data; 2463 struct hci_ev_mode_change *ev = (void *) skb->data;
@@ -3386,6 +3436,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3386 hci_remote_oob_data_request_evt(hdev, skb); 3436 hci_remote_oob_data_request_evt(hdev, skb);
3387 break; 3437 break;
3388 3438
3439 case HCI_EV_NUM_COMP_BLOCKS:
3440 hci_num_comp_blocks_evt(hdev, skb);
3441 break;
3442
3389 default: 3443 default:
3390 BT_DBG("%s event 0x%x", hdev->name, event); 3444 BT_DBG("%s event 0x%x", hdev->name, event);
3391 break; 3445 break;