diff options
author | Andrei Emeltchenko <andrei.emeltchenko@intel.com> | 2012-01-04 05:41:58 -0500 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-02-13 10:01:20 -0500 |
commit | 25e89e99b4a54a2cb6e27b4675cd71a3d8a9b3fc (patch) | |
tree | caa527d1692f5679b4f6923ac96161cdd58477f2 /net/bluetooth/hci_event.c | |
parent | 5e41862322388224eef7ce221c8772489e3aa39a (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.c | 54 |
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 | ||
2411 | static 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 | |||
2411 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2461 | static 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; |