drivers: bluetooth: hci: Support reading long events in ST SPI v1
Provide support for reading events longer than 127 bytes in ST SPI protocol v1 by splitting them into several SPI transactions. Signed-off-by: Ali Hozhabri <ali.hozhabri@st.com>
This commit is contained in:
parent
7392bf284c
commit
0252b6ff88
1 changed files with 40 additions and 15 deletions
|
@ -343,13 +343,29 @@ static int bt_spi_bluenrg_setup(const struct bt_hci_setup_params *params)
|
||||||
|
|
||||||
#endif /* CONFIG_BT_BLUENRG_ACI */
|
#endif /* CONFIG_BT_BLUENRG_ACI */
|
||||||
|
|
||||||
static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
static int bt_spi_rx_buf_construct(uint8_t *msg, struct net_buf **bufp, uint16_t size)
|
||||||
{
|
{
|
||||||
bool discardable = false;
|
bool discardable = false;
|
||||||
k_timeout_t timeout = K_FOREVER;
|
k_timeout_t timeout = K_FOREVER;
|
||||||
struct bt_hci_acl_hdr acl_hdr;
|
struct bt_hci_acl_hdr acl_hdr;
|
||||||
struct net_buf *buf;
|
/* persistent variable to keep packet length in case the HCI packet is split in
|
||||||
int len;
|
* multiple SPI transactions
|
||||||
|
*/
|
||||||
|
static uint16_t len;
|
||||||
|
struct net_buf *buf = *bufp;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1)
|
||||||
|
if (buf) {
|
||||||
|
/* Buffer already allocated, waiting to complete event reception */
|
||||||
|
net_buf_add_mem(buf, msg, MIN(size, len - buf->len));
|
||||||
|
if (buf->len >= len) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */
|
||||||
|
|
||||||
switch (msg[PACKET_TYPE]) {
|
switch (msg[PACKET_TYPE]) {
|
||||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2)
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2)
|
||||||
|
@ -357,8 +373,8 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
struct bt_hci_ext_evt_hdr *evt = (struct bt_hci_ext_evt_hdr *) (msg + 1);
|
struct bt_hci_ext_evt_hdr *evt = (struct bt_hci_ext_evt_hdr *) (msg + 1);
|
||||||
struct bt_hci_evt_hdr *evt2 = (struct bt_hci_evt_hdr *) (msg + 1);
|
struct bt_hci_evt_hdr *evt2 = (struct bt_hci_evt_hdr *) (msg + 1);
|
||||||
|
|
||||||
if (evt->len > 0xff) {
|
if (sys_le16_to_cpu(evt->len) > 0xff) {
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
/* Use memmove instead of memcpy due to buffer overlapping */
|
/* Use memmove instead of memcpy due to buffer overlapping */
|
||||||
memmove(msg + (1 + sizeof(*evt2)), msg + (1 + sizeof(*evt)), evt2->len);
|
memmove(msg + (1 + sizeof(*evt2)), msg + (1 + sizeof(*evt)), evt2->len);
|
||||||
|
@ -370,7 +386,7 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
case BT_HCI_EVT_VENDOR:
|
case BT_HCI_EVT_VENDOR:
|
||||||
/* Run event through interface handler */
|
/* Run event through interface handler */
|
||||||
if (bt_spi_handle_vendor_evt(msg)) {
|
if (bt_spi_handle_vendor_evt(msg)) {
|
||||||
return NULL;
|
return -ECANCELED;
|
||||||
}
|
}
|
||||||
/* Event has not yet been handled */
|
/* Event has not yet been handled */
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
|
@ -384,7 +400,7 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
discardable, timeout);
|
discardable, timeout);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
LOG_DBG("Discard adv report due to insufficient buf");
|
LOG_DBG("Discard adv report due to insufficient buf");
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,9 +408,16 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
if (len > net_buf_tailroom(buf)) {
|
if (len > net_buf_tailroom(buf)) {
|
||||||
LOG_ERR("Event too long: %d", len);
|
LOG_ERR("Event too long: %d", len);
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
net_buf_add_mem(buf, &msg[1], len);
|
/* Skip the first byte (HCI packet indicator) */
|
||||||
|
size = size - 1;
|
||||||
|
net_buf_add_mem(buf, &msg[1], size);
|
||||||
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1)
|
||||||
|
if (size < len) {
|
||||||
|
ret = -EINPROGRESS;
|
||||||
|
}
|
||||||
|
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */
|
||||||
break;
|
break;
|
||||||
case HCI_ACL:
|
case HCI_ACL:
|
||||||
buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
|
buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
|
||||||
|
@ -403,7 +426,7 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
if (len > net_buf_tailroom(buf)) {
|
if (len > net_buf_tailroom(buf)) {
|
||||||
LOG_ERR("ACL too long: %d", len);
|
LOG_ERR("ACL too long: %d", len);
|
||||||
net_buf_unref(buf);
|
net_buf_unref(buf);
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
net_buf_add_mem(buf, &msg[1], len);
|
net_buf_add_mem(buf, &msg[1], len);
|
||||||
break;
|
break;
|
||||||
|
@ -429,10 +452,11 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
|
||||||
#endif /* CONFIG_BT_ISO */
|
#endif /* CONFIG_BT_ISO */
|
||||||
default:
|
default:
|
||||||
LOG_ERR("Unknown BT buf type %d", msg[0]);
|
LOG_ERR("Unknown BT buf type %d", msg[0]);
|
||||||
return NULL;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
*bufp = buf;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_spi_rx_thread(void *p1, void *p2, void *p3)
|
static void bt_spi_rx_thread(void *p1, void *p2, void *p3)
|
||||||
|
@ -441,7 +465,7 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3)
|
||||||
ARG_UNUSED(p2);
|
ARG_UNUSED(p2);
|
||||||
ARG_UNUSED(p3);
|
ARG_UNUSED(p3);
|
||||||
|
|
||||||
struct net_buf *buf;
|
struct net_buf *buf = NULL;
|
||||||
uint16_t size = 0U;
|
uint16_t size = 0U;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -477,10 +501,11 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3)
|
||||||
LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX");
|
LOG_HEXDUMP_DBG(rxmsg, size, "SPI RX");
|
||||||
|
|
||||||
/* Construct net_buf from SPI data */
|
/* Construct net_buf from SPI data */
|
||||||
buf = bt_spi_rx_buf_construct(rxmsg);
|
ret = bt_spi_rx_buf_construct(rxmsg, &buf, size);
|
||||||
if (buf) {
|
if (!ret) {
|
||||||
/* Handle the received HCI data */
|
/* Handle the received HCI data */
|
||||||
bt_recv(buf);
|
bt_recv(buf);
|
||||||
|
buf = NULL;
|
||||||
}
|
}
|
||||||
} while (READ_CONDITION);
|
} while (READ_CONDITION);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue