From 9644ea0191cd183cbdd0a296fde24ed88cc23c82 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 4 Jan 2012 12:41:58 +0200 Subject: [PATCH] --- yaml --- r: 290839 b: refs/heads/master c: 25e89e99b4a54a2cb6e27b4675cd71a3d8a9b3fc h: refs/heads/master i: 290837: f388d665c530a0db404b002dd2835704ebc6abde 290835: 61ec173f1405c236661362ffb3a8f87338bf1f80 290831: 2f764f8f1a4d90164647203c4d37e7abb7a24b5f v: v3 --- [refs] | 2 +- trunk/include/net/bluetooth/hci.h | 13 ++++++++ trunk/net/bluetooth/hci_event.c | 54 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 3f47c0161a6b..69191887a4e9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5e41862322388224eef7ce221c8772489e3aa39a +refs/heads/master: 25e89e99b4a54a2cb6e27b4675cd71a3d8a9b3fc diff --git a/trunk/include/net/bluetooth/hci.h b/trunk/include/net/bluetooth/hci.h index ce5133b22445..6a9d316fb977 100644 --- a/trunk/include/net/bluetooth/hci.h +++ b/trunk/include/net/bluetooth/hci.h @@ -1168,6 +1168,19 @@ struct hci_ev_le_meta { __u8 subevent; } __packed; +#define HCI_EV_NUM_COMP_BLOCKS 0x48 +struct hci_comp_blocks_info { + __le16 handle; + __le16 pkts; + __le16 blocks; +} __packed; + +struct hci_ev_num_comp_blocks { + __le16 num_blocks; + __u8 num_hndl; + struct hci_comp_blocks_info handles[0]; +} __packed; + /* Low energy meta events */ #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 089dff80ccb0..0466ed9c1b47 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/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 queue_work(hdev->workqueue, &hdev->tx_work); } +static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_num_comp_blocks *ev = (void *) skb->data; + int i; + + if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { + BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); + return; + } + + if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + + ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { + BT_DBG("%s bad parameters", hdev->name); + return; + } + + BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, + ev->num_hndl); + + for (i = 0; i < ev->num_hndl; i++) { + struct hci_comp_blocks_info *info = &ev->handles[i]; + struct hci_conn *conn; + __u16 handle, block_count; + + handle = __le16_to_cpu(info->handle); + block_count = __le16_to_cpu(info->blocks); + + conn = hci_conn_hash_lookup_handle(hdev, handle); + if (!conn) + continue; + + conn->sent -= block_count; + + switch (conn->type) { + case ACL_LINK: + hdev->block_cnt += block_count; + if (hdev->block_cnt > hdev->num_blocks) + hdev->block_cnt = hdev->num_blocks; + break; + + default: + BT_ERR("Unknown type %d conn %p", conn->type, conn); + break; + } + } + + queue_work(hdev->workqueue, &hdev->tx_work); +} + static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { 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) hci_remote_oob_data_request_evt(hdev, skb); break; + case HCI_EV_NUM_COMP_BLOCKS: + hci_num_comp_blocks_evt(hdev, skb); + break; + default: BT_DBG("%s event 0x%x", hdev->name, event); break;