static void bt_spi_rx_thread(void) { struct net_buf *buf; u8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 }; u8_t header_slave[5]; struct bt_hci_acl_hdr acl_hdr; u8_t size; memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN); while (true) { k_sem_take(&sem_request, K_FOREVER); /* Disable IRQ pin callback to avoid spurious IRQs */ gpio_pin_disable_callback(irq_dev, GPIO_IRQ_PIN); k_sem_take(&sem_busy, K_FOREVER); do { #if defined(CONFIG_BLUETOOTH_SPI_BLUENRG) gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); #endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */ spi_transceive(spi_dev, header_master, 5, header_slave, 5); } while (header_slave[STATUS_HEADER_TOREAD] == 0 || header_slave[STATUS_HEADER_TOREAD] == 0xFF); size = header_slave[STATUS_HEADER_TOREAD]; do { spi_transceive(spi_dev, &txmsg, size, &rxmsg, size); } while (rxmsg[0] == 0); gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN); #if defined(CONFIG_BLUETOOTH_SPI_BLUENRG) gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); #endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */ k_sem_give(&sem_busy); spi_dump_message("RX:ed", rxmsg, size); switch (rxmsg[PACKET_TYPE]) { case HCI_EVT: switch (rxmsg[EVT_HEADER_EVENT]) { case BT_HCI_EVT_VENDOR: /* Vendor events are currently unsupported */ bt_spi_handle_vendor_evt(rxmsg); continue; case BT_HCI_EVT_CMD_COMPLETE: case BT_HCI_EVT_CMD_STATUS: buf = bt_buf_get_cmd_complete(K_FOREVER); break; default: buf = bt_buf_get_rx(K_FOREVER); break; } bt_buf_set_type(buf, BT_BUF_EVT); net_buf_add_mem(buf, &rxmsg[1], rxmsg[EVT_HEADER_SIZE] + 2); break; case HCI_ACL: buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_ACL_IN); memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr)); net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr)); net_buf_add_mem(buf, &rxmsg[5], sys_le16_to_cpu(acl_hdr.len)); break; default: BT_ERR("Unknown BT buf type %d", rxmsg[0]); continue; } if (rxmsg[PACKET_TYPE] == HCI_EVT && bt_hci_evt_is_prio(rxmsg[EVT_HEADER_EVENT])) { bt_recv_prio(buf); } else { bt_recv(buf); } } }
static inline void read_payload(void) { struct net_buf *buf; bool prio; int read; if (!rx.buf) { rx.buf = get_rx(K_NO_WAIT); if (!rx.buf) { if (rx.discardable) { BT_WARN("Discarding event 0x%02x", rx.evt.evt); rx.discard = rx.remaining; reset_rx(); return; } BT_WARN("Failed to allocate, deferring to rx_thread"); uart_irq_rx_disable(h4_dev); return; } BT_DBG("Allocated rx.buf %p", rx.buf); if (rx.remaining > net_buf_tailroom(rx.buf)) { BT_ERR("Not enough space in buffer"); rx.discard = rx.remaining; reset_rx(); return; } copy_hdr(rx.buf); } read = uart_fifo_read(h4_dev, net_buf_tail(rx.buf), rx.remaining); net_buf_add(rx.buf, read); rx.remaining -= read; BT_DBG("got %d bytes, remaining %u", read, rx.remaining); BT_DBG("Payload (len %u): %s", rx.buf->len, bt_hex(rx.buf->data, rx.buf->len)); if (rx.remaining) { return; } prio = (rx.type == H4_EVT && bt_hci_evt_is_prio(rx.evt.evt)); buf = rx.buf; rx.buf = NULL; if (rx.type == H4_EVT) { bt_buf_set_type(buf, BT_BUF_EVT); } else { bt_buf_set_type(buf, BT_BUF_ACL_IN); } reset_rx(); if (prio) { BT_DBG("Calling bt_recv_prio(%p)", buf); bt_recv_prio(buf); } else { BT_DBG("Putting buf %p to rx fifo", buf); net_buf_put(&rx.fifo, buf); } }