summaryrefslogtreecommitdiff
path: root/net/nimble/host/src/ble_hci_cmd.c
diff options
context:
space:
mode:
authorChristopher Collins <ccollins@apache.org>2016-08-03 19:44:39 -0700
committerChristopher Collins <ccollins@apache.org>2016-08-03 19:54:16 -0700
commit2444d8f66060385b3b3dce29b1b7ff09cacdf9eb (patch)
tree38eeeb108812c68686c9aedd8058eee64417b8ca /net/nimble/host/src/ble_hci_cmd.c
parentc9708658fddf140f2b5ac25b58e165b6191e01ae (diff)
BLE Host - Use HCI transport API
Prior to this change, the host assumed it was running with a combined host-controller setup. Now it uses the available HCI transport instead.
Diffstat (limited to 'net/nimble/host/src/ble_hci_cmd.c')
-rw-r--r--net/nimble/host/src/ble_hci_cmd.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/net/nimble/host/src/ble_hci_cmd.c b/net/nimble/host/src/ble_hci_cmd.c
index 23eaba37..53fe726b 100644
--- a/net/nimble/host/src/ble_hci_cmd.c
+++ b/net/nimble/host/src/ble_hci_cmd.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <stdio.h>
#include "os/os.h"
+#include "nimble/ble_hci_trans.h"
#include "ble_hs_priv.h"
#include "host_dbg_priv.h"
@@ -29,6 +30,8 @@
static struct os_mutex ble_hci_cmd_mutex;
static struct os_sem ble_hci_cmd_sem;
+static uint8_t *ble_hci_cmd_ack;
+
#if PHONY_HCI_ACKS
static ble_hci_cmd_phony_ack_fn *ble_hci_cmd_phony_ack_cb;
#endif
@@ -69,7 +72,6 @@ ble_hci_cmd_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len,
uint8_t num_pkts;
if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
- /* XXX: Increment stat. */
return BLE_HS_ECONTROLLER;
}
@@ -112,7 +114,6 @@ ble_hci_cmd_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
uint8_t status;
if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
- /* XXX: Increment stat. */
return BLE_HS_ECONTROLLER;
}
@@ -132,7 +133,8 @@ ble_hci_cmd_rx_cmd_status(uint8_t event_code, uint8_t *data, int len,
}
static int
-ble_hci_cmd_process_ack(uint8_t *params_buf, uint8_t params_buf_len,
+ble_hci_cmd_process_ack(uint16_t expected_opcode,
+ uint8_t *params_buf, uint8_t params_buf_len,
struct ble_hci_ack *out_ack)
{
uint8_t event_code;
@@ -140,20 +142,16 @@ ble_hci_cmd_process_ack(uint8_t *params_buf, uint8_t params_buf_len,
uint8_t event_len;
int rc;
- /***
- * The controller always reuses the command buffer for its acknowledgement
- * events. This function processes the acknowledgement event contained in
- * the command buffer.
- */
+ BLE_HS_DBG_ASSERT(ble_hci_cmd_ack != NULL);
/* Count events received */
STATS_INC(ble_hs_stats, hci_event);
/* Display to console */
- host_hci_dbg_event_disp(host_hci_cmd_buf);
+ host_hci_dbg_event_disp(ble_hci_cmd_ack);
- event_code = host_hci_cmd_buf[0];
- param_len = host_hci_cmd_buf[1];
+ event_code = ble_hci_cmd_ack[0];
+ param_len = ble_hci_cmd_ack[1];
event_len = param_len + 2;
/* Clear ack fields up front to silence spurious gcc warnings. */
@@ -161,12 +159,12 @@ ble_hci_cmd_process_ack(uint8_t *params_buf, uint8_t params_buf_len,
switch (event_code) {
case BLE_HCI_EVCODE_COMMAND_COMPLETE:
- rc = ble_hci_cmd_rx_cmd_complete(event_code, host_hci_cmd_buf,
+ rc = ble_hci_cmd_rx_cmd_complete(event_code, ble_hci_cmd_ack,
event_len, out_ack);
break;
case BLE_HCI_EVCODE_COMMAND_STATUS:
- rc = ble_hci_cmd_rx_cmd_status(event_code, host_hci_cmd_buf,
+ rc = ble_hci_cmd_rx_cmd_status(event_code, ble_hci_cmd_ack,
event_len, out_ack);
break;
@@ -187,6 +185,14 @@ ble_hci_cmd_process_ack(uint8_t *params_buf, uint8_t params_buf_len,
memcpy(params_buf, out_ack->bha_params, out_ack->bha_params_len);
}
out_ack->bha_params = params_buf;
+
+ if (out_ack->bha_opcode != expected_opcode) {
+ rc = BLE_HS_ECONTROLLER;
+ }
+ }
+
+ if (rc != 0) {
+ STATS_INC(ble_hs_stats, hci_invalid_ack);
}
return rc;
@@ -201,15 +207,20 @@ ble_hci_cmd_wait_for_ack(void)
if (ble_hci_cmd_phony_ack_cb == NULL) {
rc = BLE_HS_ETIMEOUT_HCI;
} else {
- rc = ble_hci_cmd_phony_ack_cb(host_hci_cmd_buf, 260);
+ ble_hci_cmd_ack =
+ ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ BLE_HS_DBG_ASSERT(ble_hci_cmd_ack != NULL);
+ rc = ble_hci_cmd_phony_ack_cb(ble_hci_cmd_ack, 260);
}
#else
rc = os_sem_pend(&ble_hci_cmd_sem, BLE_HCI_CMD_TIMEOUT);
switch (rc) {
case 0:
+ BLE_HS_DBG_ASSERT(ble_hci_cmd_ack != NULL);
break;
case OS_TIMEOUT:
rc = BLE_HS_ETIMEOUT_HCI;
+ STATS_INC(ble_hs_stats, hci_timeout);
break;
default:
rc = BLE_HS_EOS;
@@ -225,8 +236,12 @@ ble_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
uint8_t *out_evt_buf_len)
{
struct ble_hci_ack ack;
+ uint16_t opcode;
int rc;
+ opcode = le16toh((uint8_t *)cmd);
+
+ BLE_HS_DBG_ASSERT(ble_hci_cmd_ack == NULL);
ble_hci_cmd_lock();
rc = host_hci_cmd_send_buf(cmd);
@@ -236,11 +251,13 @@ ble_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
rc = ble_hci_cmd_wait_for_ack();
if (rc != 0) {
+ ble_hs_sched_reset(rc);
goto done;
}
- rc = ble_hci_cmd_process_ack(evt_buf, evt_buf_len, &ack);
+ rc = ble_hci_cmd_process_ack(opcode, evt_buf, evt_buf_len, &ack);
if (rc != 0) {
+ ble_hs_sched_reset(rc);
goto done;
}
@@ -251,6 +268,11 @@ ble_hci_cmd_tx(void *cmd, void *evt_buf, uint8_t evt_buf_len,
rc = ack.bha_status;
done:
+ if (ble_hci_cmd_ack != NULL) {
+ ble_hci_trans_buf_free(ble_hci_cmd_ack);
+ ble_hci_cmd_ack = NULL;
+ }
+
ble_hci_cmd_unlock();
return rc;
}
@@ -271,17 +293,17 @@ ble_hci_cmd_tx_empty_ack(void *cmd)
void
ble_hci_cmd_rx_ack(uint8_t *ack_ev)
{
- /* The controller should always reuse the command buffer for its acks. */
- BLE_HS_DBG_ASSERT(ack_ev == host_hci_cmd_buf);
-
if (ble_hci_cmd_sem.sem_tokens != 0) {
/* This ack is unexpected; ignore it. */
+ ble_hci_trans_buf_free(ack_ev);
return;
}
+ BLE_HS_DBG_ASSERT(ble_hci_cmd_ack == NULL);
/* Unblock the application now that the HCI command buffer is populated
* with the acknowledgement.
*/
+ ble_hci_cmd_ack = ack_ev;
os_sem_release(&ble_hci_cmd_sem);
}