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>
This commit is contained in:
committed by
Johan Hedberg
parent
5e41862322
commit
25e89e99b4
@@ -1168,6 +1168,19 @@ struct hci_ev_le_meta {
|
|||||||
__u8 subevent;
|
__u8 subevent;
|
||||||
} __packed;
|
} __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 */
|
/* Low energy meta events */
|
||||||
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
||||||
struct hci_ev_le_conn_complete {
|
struct hci_ev_le_conn_complete {
|
||||||
|
@@ -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);
|
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)
|
static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_ev_mode_change *ev = (void *) skb->data;
|
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);
|
hci_remote_oob_data_request_evt(hdev, skb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HCI_EV_NUM_COMP_BLOCKS:
|
||||||
|
hci_num_comp_blocks_evt(hdev, skb);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BT_DBG("%s event 0x%x", hdev->name, event);
|
BT_DBG("%s event 0x%x", hdev->name, event);
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user