Commit 0252b6ff authored by Ali Hozhabri's avatar Ali Hozhabri Committed by Carles Cufi
Browse files

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: default avatarAli Hozhabri <ali.hozhabri@st.com>
parent 7392bf28
Loading
Loading
Loading
Loading
+40 −15
Original line number Diff line number Diff line
@@ -343,13 +343,29 @@ static int bt_spi_bluenrg_setup(const struct bt_hci_setup_params *params)

#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;
	k_timeout_t timeout = K_FOREVER;
	struct bt_hci_acl_hdr acl_hdr;
	struct net_buf *buf;
	int len;
	/* persistent variable to keep packet length in case the HCI packet is split in
	 * 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]) {
#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_evt_hdr *evt2 = (struct bt_hci_evt_hdr *) (msg + 1);

		if (evt->len > 0xff) {
			return NULL;
		if (sys_le16_to_cpu(evt->len) > 0xff) {
			return -ENOMEM;
		}
		/* Use memmove instead of memcpy due to buffer overlapping */
		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:
			/* Run event through interface handler */
			if (bt_spi_handle_vendor_evt(msg)) {
				return NULL;
				return -ECANCELED;
			}
			/* Event has not yet been handled */
			__fallthrough;
@@ -384,7 +400,7 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
					     discardable, timeout);
			if (!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)) {
			LOG_ERR("Event too long: %d", len);
			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;
	case HCI_ACL:
		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)) {
			LOG_ERR("ACL too long: %d", len);
			net_buf_unref(buf);
			return NULL;
			return -ENOMEM;
		}
		net_buf_add_mem(buf, &msg[1], len);
		break;
@@ -429,10 +452,11 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg)
#endif /* CONFIG_BT_ISO */
	default:
		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)
@@ -441,7 +465,7 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3)
	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	struct net_buf *buf;
	struct net_buf *buf = NULL;
	uint16_t size = 0U;
	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");

			/* Construct net_buf from SPI data */
			buf = bt_spi_rx_buf_construct(rxmsg);
			if (buf) {
			ret = bt_spi_rx_buf_construct(rxmsg, &buf, size);
			if (!ret) {
				/* Handle the received HCI data */
				bt_recv(buf);
				buf = NULL;
			}
		} while (READ_CONDITION);
	}