Bluetooth: controller: Issue Data Buffer Overflow event

Whenever the HCI ACL flow control is violated by the Host, a Data Buffer
Overflow event is now issued by the Controller (if enabled) to notify
the Host of the buffer overrun.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2017-09-12 17:14:30 +02:00 committed by Carles Cufí
commit b77b8e615b
4 changed files with 47 additions and 4 deletions

View file

@ -1438,6 +1438,15 @@ struct bt_hci_evt_link_key_notify {
u8_t key_type; u8_t key_type;
} __packed; } __packed;
/* Overflow link types */
#define BT_OVERFLOW_LINK_SYNCH 0x00
#define BT_OVERFLOW_LINK_ACL 0x01
#define BT_HCI_EVT_DATA_BUF_OVERFLOW 0x1a
struct bt_hci_evt_data_buf_overflow {
u8_t link_type;
} __packed;
#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22 #define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22
struct bt_hci_evt_inquiry_result_with_rssi { struct bt_hci_evt_inquiry_result_with_rssi {
bt_addr_t addr; bt_addr_t addr;

View file

@ -1811,6 +1811,21 @@ static int vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
return 0; return 0;
} }
static void data_buf_overflow(struct net_buf **buf)
{
struct bt_hci_evt_data_buf_overflow *ep;
if (!(event_mask & BT_EVT_MASK_DATA_BUFFER_OVERFLOW)) {
return;
}
*buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
evt_create(*buf, BT_HCI_EVT_DATA_BUF_OVERFLOW, sizeof(*ep));
ep = net_buf_add(*buf, sizeof(*ep));
ep->link_type = BT_OVERFLOW_LINK_ACL;
}
struct net_buf *hci_cmd_handle(struct net_buf *cmd) struct net_buf *hci_cmd_handle(struct net_buf *cmd)
{ {
struct bt_hci_evt_cc_status *ccst; struct bt_hci_evt_cc_status *ccst;
@ -1869,7 +1884,7 @@ struct net_buf *hci_cmd_handle(struct net_buf *cmd)
return evt; return evt;
} }
int hci_acl_handle(struct net_buf *buf) int hci_acl_handle(struct net_buf *buf, struct net_buf **evt)
{ {
struct radio_pdu_node_tx *radio_pdu_node_tx; struct radio_pdu_node_tx *radio_pdu_node_tx;
struct bt_hci_acl_hdr *acl; struct bt_hci_acl_hdr *acl;
@ -1878,6 +1893,8 @@ int hci_acl_handle(struct net_buf *buf)
u8_t flags; u8_t flags;
u16_t len; u16_t len;
*evt = NULL;
if (buf->len < sizeof(*acl)) { if (buf->len < sizeof(*acl)) {
BT_ERR("No HCI ACL header"); BT_ERR("No HCI ACL header");
return -EINVAL; return -EINVAL;
@ -1900,6 +1917,7 @@ int hci_acl_handle(struct net_buf *buf)
radio_pdu_node_tx = radio_tx_mem_acquire(); radio_pdu_node_tx = radio_tx_mem_acquire();
if (!radio_pdu_node_tx) { if (!radio_pdu_node_tx) {
BT_ERR("Tx Buffer Overflow"); BT_ERR("Tx Buffer Overflow");
data_buf_overflow(evt);
return -ENOBUFS; return -ENOBUFS;
} }

View file

@ -347,6 +347,22 @@ static int cmd_handle(struct net_buf *buf)
return 0; return 0;
} }
#if defined(CONFIG_BT_CONN)
static int acl_handle(struct net_buf *buf)
{
struct net_buf *evt;
int err;
err = hci_acl_handle(buf, &evt);
if (evt) {
BT_DBG("Replying with event of %u bytes", evt->len);
bt_recv_prio(evt);
}
return err;
}
#endif /* CONFIG_BT_CONN */
static int hci_driver_send(struct net_buf *buf) static int hci_driver_send(struct net_buf *buf)
{ {
u8_t type; u8_t type;
@ -363,9 +379,9 @@ static int hci_driver_send(struct net_buf *buf)
switch (type) { switch (type) {
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
case BT_BUF_ACL_OUT: case BT_BUF_ACL_OUT:
err = hci_acl_handle(buf); err = acl_handle(buf);
break; break;
#endif #endif /* CONFIG_BT_CONN */
case BT_BUF_CMD: case BT_BUF_CMD:
err = cmd_handle(buf); err = cmd_handle(buf);
break; break;

View file

@ -39,7 +39,7 @@ struct net_buf *hci_cmd_handle(struct net_buf *cmd);
void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf); void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf);
s8_t hci_get_class(struct radio_pdu_node_rx *node_rx); s8_t hci_get_class(struct radio_pdu_node_rx *node_rx);
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
int hci_acl_handle(struct net_buf *acl); int hci_acl_handle(struct net_buf *acl, struct net_buf **evt);
void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf); void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf);
void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num); void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num);
#endif #endif