You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/11/10 03:28:20 UTC
incubator-mynewt-larva git commit: Initial processing of HCI events.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master c0c07d8b0 -> 43f639ff2
Initial processing of HCI events.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/43f639ff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/43f639ff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/43f639ff
Branch: refs/heads/master
Commit: 43f639ff2bed711a1466464278e53058627c7b1b
Parents: c0c07d8
Author: Christopher Collins <cc...@gmail.com>
Authored: Mon Nov 9 18:28:09 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Mon Nov 9 18:28:09 2015 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/host_hci.h | 2 +
net/nimble/host/src/ble_hs_att.c | 2 +-
net/nimble/host/src/ble_hs_conn.c | 54 ++++
net/nimble/host/src/ble_hs_conn.h | 1 +
net/nimble/host/src/host_hci.c | 450 ++++++---------------------
net/nimble/host/src/host_hci_cmd.c | 422 +++++++++++++++++++++++++
net/nimble/include/nimble/hci_common.h | 9 +-
7 files changed, 585 insertions(+), 355 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/include/host/host_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/host_hci.h b/net/nimble/host/include/host/host_hci.h
index cf629c3..ec8b36b 100644
--- a/net/nimble/host/include/host/host_hci.h
+++ b/net/nimble/host/include/host/host_hci.h
@@ -39,4 +39,6 @@ int host_hci_cmd_le_rmv_from_whitelist(uint8_t *addr, uint8_t addr_type);
int host_hci_data_rx(void *pkt, uint16_t len);
+extern uint16_t host_hci_outstanding_opcode;
+
#endif /* H_HOST_HCI_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/src/ble_hs_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.c b/net/nimble/host/src/ble_hs_att.c
index 1d04748..da4742d 100644
--- a/net/nimble/host/src/ble_hs_att.c
+++ b/net/nimble/host/src/ble_hs_att.c
@@ -44,7 +44,7 @@ static int ble_hs_att_rx_write_req(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf *om);
-struct ble_hs_att_rx_dispatch_entry ble_hs_att_rx_dispatch[] = {
+static struct ble_hs_att_rx_dispatch_entry ble_hs_att_rx_dispatch[] = {
{ BLE_HS_ATT_OP_MTU_REQ, ble_hs_att_rx_mtu_req },
{ BLE_HS_ATT_OP_READ_REQ, ble_hs_att_rx_read_req },
{ BLE_HS_ATT_OP_WRITE_REQ, ble_hs_att_rx_write_req },
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/src/ble_hs_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.c b/net/nimble/host/src/ble_hs_conn.c
index ad4f7c8..0a1b5b8 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -15,8 +15,10 @@
*/
#include <assert.h>
+#include <string.h>
#include <errno.h>
#include "os/os.h"
+#include "host/host_hci.h"
#include "ble_l2cap.h"
#include "ble_hs_conn.h"
#include "ble_hs_att.h"
@@ -28,6 +30,13 @@ static SLIST_HEAD(, ble_hs_conn) ble_hs_conns =
static struct os_mempool ble_hs_conn_pool;
+static struct {
+ unsigned bhcp_valid:1;
+
+ uint8_t bhcp_addr[6];
+ unsigned bhcp_use_white:1;
+} ble_hs_conn_pending;
+
struct ble_hs_conn *
ble_hs_conn_alloc(void)
{
@@ -106,6 +115,51 @@ ble_hs_conn_first(void)
return SLIST_FIRST(&ble_hs_conns);
}
+/**
+ * Initiates a connection using the GAP Direct Connection Establishment
+ * Procedure.
+ * XXX: This will likely be moved.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_hs_conn_initiate_direct(int addr_type, uint8_t *addr)
+{
+ struct hci_create_conn hcc;
+ int rc;
+
+ /* Make sure no connection attempt is already in progress. */
+ if (ble_hs_conn_pending.bhcp_valid) {
+ return EALREADY;
+ }
+
+ hcc.scan_itvl = 0x0010;
+ hcc.scan_window = 0x0010;
+ hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL;
+ hcc.peer_addr_type = addr_type;
+ memcpy(hcc.peer_addr, addr, sizeof hcc.peer_addr);
+ hcc.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
+ hcc.conn_itvl_min = 24;
+ hcc.conn_itvl_min = 40;
+ hcc.conn_latency = 0;
+ hcc.supervision_timeout = 0x0100; // XXX
+ hcc.min_ce_len = 0x0010; // XXX
+ hcc.min_ce_len = 0x0300; // XXX
+
+ ble_hs_conn_pending.bhcp_valid = 1;
+ memcpy(ble_hs_conn_pending.bhcp_addr, addr,
+ sizeof ble_hs_conn_pending.bhcp_addr);
+ ble_hs_conn_pending.bhcp_use_white = 0;
+
+ rc = host_hci_cmd_le_create_connection(&hcc);
+ if (rc != 0) {
+ ble_hs_conn_pending.bhcp_valid = 0;
+ return rc;
+ }
+
+ return 0;
+}
+
int
ble_hs_conn_init(void)
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/src/ble_hs_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.h b/net/nimble/host/src/ble_hs_conn.h
index 297366d..746383e 100644
--- a/net/nimble/host/src/ble_hs_conn.h
+++ b/net/nimble/host/src/ble_hs_conn.h
@@ -35,6 +35,7 @@ struct ble_hs_conn *ble_hs_conn_alloc(void);
void ble_hs_conn_free(struct ble_hs_conn *conn);
struct ble_hs_conn *ble_hs_conn_find(uint16_t con_handle);
struct ble_hs_conn *ble_hs_conn_first(void);
+int ble_hs_conn_initiate_direct(int addr_type, uint8_t *addr);
int ble_hs_conn_init(void);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/src/host_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci.c b/net/nimble/host/src/host_hci.c
index 17b11e2..164c7ad 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -48,412 +48,156 @@ struct os_eventq g_ble_host_hci_evq;
struct host_hci_stats
{
uint32_t events_rxd;
+ uint32_t good_acks_rxd;
+ uint32_t bad_acks_rxd;
+ uint32_t unknown_events_rxd;
};
struct host_hci_stats g_host_hci_stats;
-static int
-host_hci_cmd_send(uint8_t *cmdbuf)
-{
-#ifdef ARCH_sim
- return 0;
-#else
- return ble_hci_transport_host_cmd_send(cmdbuf);
-#endif
-}
+/** The opcode of the current unacked HCI command; 0 if none. */
+uint16_t host_hci_outstanding_opcode;
-static int
-host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
-{
- int rc;
- uint8_t *cmd;
- uint16_t opcode;
+/** Dispatch table for incoming HCI events. Sorted by event code field. */
+typedef int host_hci_event_fn(uint8_t event_code, uint8_t *data, int len);
+struct host_hci_event_dispatch_entry {
+ uint8_t hed_event_code;
+ host_hci_event_fn *hed_fn;
+};
- rc = -1;
- cmd = os_memblock_get(&g_hci_cmd_pool);
- if (cmd) {
- opcode = (BLE_HCI_OGF_LE << 10) | ocf;
- htole16(cmd, opcode);
- cmd[2] = len;
- if (len) {
- memcpy(cmd + BLE_HCI_CMD_HDR_LEN, cmddata, len);
- }
- rc = host_hci_cmd_send(cmd);
- }
+static int host_hci_rx_cmd_complete(uint8_t event_code, uint8_t *data,
+ int len);
+static int host_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len);
- return rc;
-}
+static struct host_hci_event_dispatch_entry host_hci_event_dispatch[] = {
+ { BLE_HCI_EVCODE_COMMAND_COMPLETE, host_hci_rx_cmd_complete },
+ { BLE_HCI_EVCODE_COMMAND_STATUS, host_hci_rx_cmd_status },
+};
-static int
-host_hci_cmd_le_whitelist_chg(uint8_t *addr, uint8_t addr_type, uint8_t ocf)
-{
- int rc;
- uint8_t cmd[BLE_HCI_CHG_WHITE_LIST_LEN];
+#define HOST_HCI_EVENT_DISPATCH_SZ \
+ (sizeof host_hci_event_dispatch / sizeof host_hci_event_dispatch[0])
- if (addr_type <= BLE_ADDR_TYPE_RANDOM) {
- cmd[0] = addr_type;
- memcpy(cmd + 1, addr, BLE_DEV_ADDR_LEN);
- rc = host_hci_le_cmd_send(ocf, BLE_HCI_CHG_WHITE_LIST_LEN, cmd);
- } else {
- rc = BLE_ERR_INV_HCI_CMD_PARMS;
- }
- return rc;
-}
-
-int
-host_hci_cmd_le_set_adv_params(struct hci_adv_params *adv)
+static struct host_hci_event_dispatch_entry *
+host_hci_dispatch_entry_find(uint8_t event_code)
{
- int rc;
- uint16_t itvl;
- uint8_t cmd[BLE_HCI_SET_ADV_PARAM_LEN];
-
- assert(adv != NULL);
-
- /* Make sure parameters are valid */
- rc = -1;
- if ((adv->adv_itvl_min >= adv->adv_itvl_max) ||
- (adv->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
- (adv->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) ||
- (adv->adv_filter_policy > BLE_HCI_ADV_FILT_MAX) ||
- (adv->adv_type > BLE_HCI_ADV_TYPE_MAX) ||
- (adv->adv_channel_map == 0) ||
- ((adv->adv_channel_map & 0xF8) != 0)) {
- /* These parameters are not valid */
- return rc;
- }
-
- /* Make sure interval is valid for advertising type. */
- if ((adv->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) ||
- (adv->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) {
- itvl = BLE_HCI_ADV_ITVL_NONCONN_MIN;
- } else {
- itvl = BLE_HCI_ADV_ITVL_MIN;
- }
+ struct host_hci_event_dispatch_entry *entry;
+ int i;
- /* Do not check if high duty-cycle directed */
- if (adv->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
- if ((adv->adv_itvl_min < itvl) ||
- (adv->adv_itvl_min > BLE_HCI_ADV_ITVL_MAX)) {
- return rc;
+ for (i = 0; i < HOST_HCI_EVENT_DISPATCH_SZ; i++) {
+ entry = host_hci_event_dispatch + i;
+ if (entry->hed_event_code == event_code) {
+ return entry;
}
}
- htole16(cmd, adv->adv_itvl_min);
- htole16(cmd + 2, adv->adv_itvl_max);
- cmd[4] = adv->adv_type;
- cmd[5] = adv->own_addr_type;
- cmd[6] = adv->peer_addr_type;
- memcpy(cmd + 7, adv->peer_addr, BLE_DEV_ADDR_LEN);
- cmd[13] = adv->adv_channel_map;
- cmd[14] = adv->adv_filter_policy;
-
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_PARAMS,
- BLE_HCI_SET_ADV_PARAM_LEN, cmd);
-
- return rc;
-}
-
-int
-host_hci_cmd_le_set_adv_data(uint8_t *data, uint8_t len)
-{
- int rc;
- uint8_t cmd[BLE_HCI_MAX_ADV_DATA_LEN + 1];
-
- /* Check for valid parameters */
- if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- cmd[0] = len;
- memcpy(cmd + 1, data, len);
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_DATA, len + 1, cmd);
-
- return rc;
-}
-
-int
-host_hci_cmd_le_set_scan_rsp_data(uint8_t *data, uint8_t len)
-{
- int rc;
- uint8_t cmd[BLE_HCI_MAX_SCAN_RSP_DATA_LEN + 1];
-
- /* Check for valid parameters */
- if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- cmd[0] = len;
- memcpy(cmd + 1, data, len);
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA, len + 1, cmd);
-
- return rc;
+ return NULL;
}
-/**
- * ble host hci cmd le set rand addr
- *
- * Sets the random address to be used in advertisements.
- *
- * @param addr Pointer to the random address to send to device
- *
- * @return int
- */
-int
-host_hci_cmd_le_set_rand_addr(uint8_t *addr)
+static int
+host_hci_rx_cmd_complete(uint8_t event_code, uint8_t *data, int len)
{
- int rc;
- uint8_t cmd[BLE_DEV_ADDR_LEN];
+ uint16_t opcode;
+ uint16_t ocf;
+ uint8_t num_pkts;
+ uint8_t *parms;
- /* Check for valid parameters */
- rc = -1;
- if (addr) {
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_RAND_ADDR,
- BLE_DEV_ADDR_LEN, cmd);
+ if (len < BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN) {
+ /* XXX: Increment stat. */
+ return EMSGSIZE;
}
- return rc;
-}
-
-int
-host_hci_cmd_le_set_event_mask(uint64_t event_mask)
-{
- int rc;
- uint8_t cmd[sizeof(uint64_t)];
-
- htole64(cmd, event_mask);
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_EVENT_MASK, sizeof(uint64_t),
- cmd);
-
- return rc;
-}
-
-int
-host_hci_cmd_le_set_adv_enable(uint8_t enable)
-{
- int rc;
- uint8_t cmd[BLE_HCI_SET_ADV_ENABLE_LEN];
-
- cmd[0] = enable;
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_ENABLE,
- BLE_HCI_SET_ADV_ENABLE_LEN, cmd);
-
- return rc;
-}
+ num_pkts = data[2];
+ opcode = le16toh(data + 3);
+ parms = data + 4;
-int
-host_hci_cmd_le_set_scan_params(uint8_t scan_type, uint16_t scan_itvl,
- uint16_t scan_window, uint8_t own_addr_type,
- uint8_t filter_policy) {
- int rc;
- uint8_t cmd[BLE_HCI_SET_SCAN_PARAM_LEN];
+ /* XXX: Process num_pkts field. */
+ (void)num_pkts;
- /* Make sure parameters are valid */
- if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) &&
- (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
+ if (opcode != BLE_HCI_OPCODE_NOP &&
+ opcode != host_hci_outstanding_opcode) {
- /* Check interval and window */
- if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
- (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
- (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
- (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
- (scan_itvl < scan_window)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
+ ++g_host_hci_stats.bad_acks_rxd;
+ return ENOENT;
}
- /* Check own addr type */
- if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
+ if (opcode == host_hci_outstanding_opcode) {
+ host_hci_outstanding_opcode = 0;
}
- /* Check scanner filter policy */
- if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- cmd[0] = scan_type;
- htole16(cmd + 1, scan_itvl);
- htole16(cmd + 3, scan_window);
- cmd[5] = own_addr_type;
- cmd[6] = filter_policy;
-
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
- BLE_HCI_SET_SCAN_PARAM_LEN, cmd);
-
- return rc;
-}
-
-int
-host_hci_cmd_le_set_scan_enable(uint8_t enable, uint8_t filter_dups)
-{
- int rc;
- uint8_t cmd[BLE_HCI_SET_SCAN_ENABLE_LEN];
+ ocf = BLE_HCI_OCF(opcode);
+ /* XXX: Dispatch based on OCF. */
+ (void)parms;
+ (void)ocf;
- cmd[0] = enable;
- cmd[1] = filter_dups;
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
- BLE_HCI_SET_SCAN_ENABLE_LEN, cmd);
- return rc;
+ return 0;
}
-int
-host_hci_cmd_le_create_connection(struct hci_create_conn *hcc)
+static int
+host_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len)
{
- int rc;
- uint8_t cmd[BLE_HCI_CREATE_CONN_LEN];
-
- /* Check scan interval and scan window */
- if ((hcc->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
- (hcc->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
- (hcc->scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
- (hcc->scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
- (hcc->scan_itvl < hcc->scan_window)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- /* Check initiator filter policy */
- if (hcc->filter_policy > BLE_HCI_SCAN_FILT_MAX) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- /* Check peer addr type */
- if (hcc->peer_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
+ uint16_t opcode;
+ uint16_t ocf;
+ uint8_t num_pkts;
+ uint8_t status;
- /* Check own addr type */
- if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
+ if (len < BLE_HCI_EVENT_CMD_STATUS_LEN) {
+ /* XXX: Increment stat. */
+ return EMSGSIZE;
}
- /* Check connection interval min */
- if ((hcc->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
- (hcc->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
+ status = data[2];
+ num_pkts = data[3];
+ opcode = le16toh(data + 4);
- /* Check connection interval max */
- if ((hcc->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
- (hcc->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
- (hcc->conn_itvl_max < hcc->conn_itvl_min)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
+ /* XXX: Process num_pkts field. */
+ (void)num_pkts;
- /* Check connection latency */
- if ((hcc->conn_latency < BLE_HCI_CONN_LATENCY_MIN) ||
- (hcc->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
+ /* XXX: This check might be overaggressive for the command status event. */
+ if (opcode != BLE_HCI_OPCODE_NOP &&
+ opcode != host_hci_outstanding_opcode) {
- /* Check supervision timeout */
- if ((hcc->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
- (hcc->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
+ ++g_host_hci_stats.bad_acks_rxd;
+ return ENOENT;
}
- /* Check connection event length */
- if (hcc->min_ce_len > hcc->max_ce_len) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
+ if (opcode == host_hci_outstanding_opcode) {
+ host_hci_outstanding_opcode = 0;
}
- htole16(cmd + 0, hcc->scan_itvl);
- htole16(cmd + 2, hcc->scan_window);
- cmd[4] = hcc->filter_policy;
- cmd[5] = hcc->peer_addr_type;
- memcpy(cmd + 6, hcc->peer_addr, BLE_DEV_ADDR_LEN);
- cmd[12] = hcc->own_addr_type;
- htole16(cmd + 13, hcc->conn_itvl_min);
- htole16(cmd + 15, hcc->conn_itvl_max);
- htole16(cmd + 17, hcc->conn_latency);
- htole16(cmd + 19, hcc->supervision_timeout);
- htole16(cmd + 21, hcc->min_ce_len);
- htole16(cmd + 23, hcc->max_ce_len);
-
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_CREATE_CONN,
- BLE_HCI_CREATE_CONN_LEN, cmd);
- return rc;
-}
-
-/**
- * Clear the whitelist.
- *
- * @return int
- */
-int
-host_hci_cmd_le_clear_whitelist(void)
-{
- int rc;
-
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST, 0, NULL);
- return rc;
-}
-
-/**
- * Read the whitelist size. Note that this is not how many elements have
- * been added to the whitelist; rather it is the number of whitelist entries
- * allowed by the controller.
- *
- * @return int
- */
-int
-host_hci_cmd_le_read_whitelist(void)
-{
- int rc;
-
- rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE, 0, NULL);
- return rc;
-}
+ ocf = BLE_HCI_OCF(opcode);
+ /* XXX: Dispatch based on OCF. */
+ (void)status;
+ (void)ocf;
-/**
- * Add a device to the whitelist.
- *
- * @param addr
- * @param addr_type
- *
- * @return int
- */
-int
-host_hci_cmd_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type)
-{
- int rc;
-
- rc = host_hci_cmd_le_whitelist_chg(addr, addr_type,
- BLE_HCI_OCF_LE_ADD_WHITE_LIST);
-
- return rc;
-}
-
-/**
- * Remove a device from the whitelist.
- *
- * @param addr
- * @param addr_type
- *
- * @return int
- */
-int
-host_hci_cmd_le_rmv_from_whitelist(uint8_t *addr, uint8_t addr_type)
-{
- int rc;
-
- rc = host_hci_cmd_le_whitelist_chg(addr, addr_type,
- BLE_HCI_OCF_LE_RMV_WHITE_LIST);
- return rc;
+ return 0;
}
void
host_hci_event_proc(struct os_event *ev)
{
+ struct host_hci_event_dispatch_entry *entry;
os_error_t err;
+ uint8_t *data;
+ uint8_t event_code;
+ uint8_t param_len;
/* Count events received */
++g_host_hci_stats.events_rxd;
- /* Display to console */
- host_hci_dbg_event_disp((uint8_t *)ev->ev_arg);
+ data = ev->ev_arg;
- /* XXX: Process the event */
+ /* Display to console */
+ host_hci_dbg_event_disp(data);
+
+ /* Process the event */
+ event_code = data[0];
+ param_len = data[1];
+ entry = host_hci_dispatch_entry_find(event_code);
+ if (entry == NULL) {
+ ++g_host_hci_stats.unknown_events_rxd;
+ } else {
+ entry->hed_fn(event_code, data, param_len + 2);
+ }
/* Free the command buffer */
err = os_memblock_put(&g_hci_cmd_pool, ev->ev_arg);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
new file mode 100644
index 0000000..1593309
--- /dev/null
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -0,0 +1,422 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "os/os.h"
+#include "console/console.h"
+#include "nimble/hci_common.h"
+#include "nimble/hci_transport.h"
+#include "host/ble_hs.h"
+#include "host/host_hci.h"
+#include "host_dbg.h"
+#include "ble_hs_conn.h"
+#include "ble_l2cap.h"
+
+static int
+host_hci_cmd_send(uint8_t *cmdbuf)
+{
+#ifdef ARCH_sim
+ return 0;
+#else
+ return ble_hci_transport_host_cmd_send(cmdbuf);
+#endif
+}
+
+static int
+host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
+{
+ int rc;
+ uint8_t *cmd;
+ uint16_t opcode;
+
+ rc = -1;
+ cmd = os_memblock_get(&g_hci_cmd_pool);
+ if (cmd) {
+ opcode = (BLE_HCI_OGF_LE << 10) | ocf;
+ htole16(cmd, opcode);
+ cmd[2] = len;
+ if (len) {
+ memcpy(cmd + BLE_HCI_CMD_HDR_LEN, cmddata, len);
+ }
+ rc = host_hci_cmd_send(cmd);
+ if (rc == 0) {
+ host_hci_outstanding_opcode = opcode;
+ }
+ }
+
+ return rc;
+}
+
+static int
+host_hci_cmd_le_whitelist_chg(uint8_t *addr, uint8_t addr_type, uint8_t ocf)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_CHG_WHITE_LIST_LEN];
+
+ if (addr_type <= BLE_ADDR_TYPE_RANDOM) {
+ cmd[0] = addr_type;
+ memcpy(cmd + 1, addr, BLE_DEV_ADDR_LEN);
+ rc = host_hci_le_cmd_send(ocf, BLE_HCI_CHG_WHITE_LIST_LEN, cmd);
+ } else {
+ rc = BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_adv_params(struct hci_adv_params *adv)
+{
+ int rc;
+ uint16_t itvl;
+ uint8_t cmd[BLE_HCI_SET_ADV_PARAM_LEN];
+
+ assert(adv != NULL);
+
+ /* Make sure parameters are valid */
+ rc = -1;
+ if ((adv->adv_itvl_min >= adv->adv_itvl_max) ||
+ (adv->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
+ (adv->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) ||
+ (adv->adv_filter_policy > BLE_HCI_ADV_FILT_MAX) ||
+ (adv->adv_type > BLE_HCI_ADV_TYPE_MAX) ||
+ (adv->adv_channel_map == 0) ||
+ ((adv->adv_channel_map & 0xF8) != 0)) {
+ /* These parameters are not valid */
+ return rc;
+ }
+
+ /* Make sure interval is valid for advertising type. */
+ if ((adv->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) ||
+ (adv->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) {
+ itvl = BLE_HCI_ADV_ITVL_NONCONN_MIN;
+ } else {
+ itvl = BLE_HCI_ADV_ITVL_MIN;
+ }
+
+ /* Do not check if high duty-cycle directed */
+ if (adv->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
+ if ((adv->adv_itvl_min < itvl) ||
+ (adv->adv_itvl_min > BLE_HCI_ADV_ITVL_MAX)) {
+ return rc;
+ }
+ }
+
+ htole16(cmd, adv->adv_itvl_min);
+ htole16(cmd + 2, adv->adv_itvl_max);
+ cmd[4] = adv->adv_type;
+ cmd[5] = adv->own_addr_type;
+ cmd[6] = adv->peer_addr_type;
+ memcpy(cmd + 7, adv->peer_addr, BLE_DEV_ADDR_LEN);
+ cmd[13] = adv->adv_channel_map;
+ cmd[14] = adv->adv_filter_policy;
+
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_PARAMS,
+ BLE_HCI_SET_ADV_PARAM_LEN, cmd);
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_adv_data(uint8_t *data, uint8_t len)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_MAX_ADV_DATA_LEN + 1];
+
+ /* Check for valid parameters */
+ if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ cmd[0] = len;
+ memcpy(cmd + 1, data, len);
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_DATA, len + 1, cmd);
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_scan_rsp_data(uint8_t *data, uint8_t len)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_MAX_SCAN_RSP_DATA_LEN + 1];
+
+ /* Check for valid parameters */
+ if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ cmd[0] = len;
+ memcpy(cmd + 1, data, len);
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA, len + 1, cmd);
+
+ return rc;
+}
+
+/**
+ * ble host hci cmd le set rand addr
+ *
+ * Sets the random address to be used in advertisements.
+ *
+ * @param addr Pointer to the random address to send to device
+ *
+ * @return int
+ */
+int
+host_hci_cmd_le_set_rand_addr(uint8_t *addr)
+{
+ int rc;
+ uint8_t cmd[BLE_DEV_ADDR_LEN];
+
+ /* Check for valid parameters */
+ rc = -1;
+ if (addr) {
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_RAND_ADDR,
+ BLE_DEV_ADDR_LEN, cmd);
+ }
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_event_mask(uint64_t event_mask)
+{
+ int rc;
+ uint8_t cmd[sizeof(uint64_t)];
+
+ htole64(cmd, event_mask);
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_EVENT_MASK, sizeof(uint64_t),
+ cmd);
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_adv_enable(uint8_t enable)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_SET_ADV_ENABLE_LEN];
+
+ cmd[0] = enable;
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_ADV_ENABLE,
+ BLE_HCI_SET_ADV_ENABLE_LEN, cmd);
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_scan_params(uint8_t scan_type, uint16_t scan_itvl,
+ uint16_t scan_window, uint8_t own_addr_type,
+ uint8_t filter_policy) {
+ int rc;
+ uint8_t cmd[BLE_HCI_SET_SCAN_PARAM_LEN];
+
+ /* Make sure parameters are valid */
+ if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) &&
+ (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check interval and window */
+ if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
+ (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
+ (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
+ (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
+ (scan_itvl < scan_window)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check own addr type */
+ if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check scanner filter policy */
+ if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ cmd[0] = scan_type;
+ htole16(cmd + 1, scan_itvl);
+ htole16(cmd + 3, scan_window);
+ cmd[5] = own_addr_type;
+ cmd[6] = filter_policy;
+
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_PARAMS,
+ BLE_HCI_SET_SCAN_PARAM_LEN, cmd);
+
+ return rc;
+}
+
+int
+host_hci_cmd_le_set_scan_enable(uint8_t enable, uint8_t filter_dups)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_SET_SCAN_ENABLE_LEN];
+
+ cmd[0] = enable;
+ cmd[1] = filter_dups;
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_SCAN_ENABLE,
+ BLE_HCI_SET_SCAN_ENABLE_LEN, cmd);
+ return rc;
+}
+
+int
+host_hci_cmd_le_create_connection(struct hci_create_conn *hcc)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_CREATE_CONN_LEN];
+
+ /* Check scan interval and scan window */
+ if ((hcc->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
+ (hcc->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
+ (hcc->scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
+ (hcc->scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
+ (hcc->scan_itvl < hcc->scan_window)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check initiator filter policy */
+ if (hcc->filter_policy > BLE_HCI_CONN_FILT_MAX) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check peer addr type */
+ if (hcc->peer_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check own addr type */
+ if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check connection interval min */
+ if ((hcc->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
+ (hcc->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check connection interval max */
+ if ((hcc->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
+ (hcc->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
+ (hcc->conn_itvl_max < hcc->conn_itvl_min)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check connection latency */
+ if ((hcc->conn_latency < BLE_HCI_CONN_LATENCY_MIN) ||
+ (hcc->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check supervision timeout */
+ if ((hcc->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
+ (hcc->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* Check connection event length */
+ if (hcc->min_ce_len > hcc->max_ce_len) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ htole16(cmd + 0, hcc->scan_itvl);
+ htole16(cmd + 2, hcc->scan_window);
+ cmd[4] = hcc->filter_policy;
+ cmd[5] = hcc->peer_addr_type;
+ memcpy(cmd + 6, hcc->peer_addr, BLE_DEV_ADDR_LEN);
+ cmd[12] = hcc->own_addr_type;
+ htole16(cmd + 13, hcc->conn_itvl_min);
+ htole16(cmd + 15, hcc->conn_itvl_max);
+ htole16(cmd + 17, hcc->conn_latency);
+ htole16(cmd + 19, hcc->supervision_timeout);
+ htole16(cmd + 21, hcc->min_ce_len);
+ htole16(cmd + 23, hcc->max_ce_len);
+
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_CREATE_CONN,
+ BLE_HCI_CREATE_CONN_LEN, cmd);
+ return rc;
+}
+
+/**
+ * Clear the whitelist.
+ *
+ * @return int
+ */
+int
+host_hci_cmd_le_clear_whitelist(void)
+{
+ int rc;
+
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST, 0, NULL);
+ return rc;
+}
+
+/**
+ * Read the whitelist size. Note that this is not how many elements have
+ * been added to the whitelist; rather it is the number of whitelist entries
+ * allowed by the controller.
+ *
+ * @return int
+ */
+int
+host_hci_cmd_le_read_whitelist(void)
+{
+ int rc;
+
+ rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE, 0, NULL);
+ return rc;
+}
+
+/**
+ * Add a device to the whitelist.
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int
+ */
+int
+host_hci_cmd_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type)
+{
+ int rc;
+
+ rc = host_hci_cmd_le_whitelist_chg(addr, addr_type,
+ BLE_HCI_OCF_LE_ADD_WHITE_LIST);
+
+ return rc;
+}
+
+/**
+ * Remove a device from the whitelist.
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int
+ */
+int
+host_hci_cmd_le_rmv_from_whitelist(uint8_t *addr, uint8_t addr_type)
+{
+ int rc;
+
+ rc = host_hci_cmd_le_whitelist_chg(addr, addr_type,
+ BLE_HCI_OCF_LE_RMV_WHITE_LIST);
+ return rc;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/43f639ff/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 69abc89..0708487 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -30,6 +30,8 @@
*/
#define BLE_HCI_CMD_HDR_LEN (3)
+#define BLE_HCI_OPCODE_NOP (0)
+
/* Get the OGF and OCF from the opcode in the command */
#define BLE_HCI_OGF(opcode) (((opcode) >> 10) & 0x003F)
#define BLE_HCI_OCF(opcode) ((opcode) & 0x03FF)
@@ -215,6 +217,9 @@
/* Create Connection */
#define BLE_HCI_CREATE_CONN_LEN (25)
+#define BLE_HCI_CONN_FILT_NO_WL (0)
+#define BLE_HCI_CONN_FILT_USE_WL (1)
+#define BLE_HCI_CONN_FILT_MAX (1)
#define BLE_HCI_CONN_ITVL_MIN (0x0006)
#define BLE_HCI_CONN_ITVL_MAX (0x0c80)
#define BLE_HCI_CONN_LATENCY_MIN (0x0000)
@@ -237,7 +242,7 @@
#define BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP (0x0C)
#define BLE_HCI_EVCODE_QOS_SETUP_CMP (0x0D)
#define BLE_HCI_EVCODE_COMMAND_COMPLETE (0x0E)
-#define BLE_HCI_EVCODE_COMMAND_STATE (0x0F)
+#define BLE_HCI_EVCODE_COMMAND_STATUS (0x0F)
#define BLE_HCI_EVCODE_HW_ERROR (0x10)
#define BLE_HCI_EVCODE_LE_META (0x3E)
/* XXX: Define them all... */
@@ -259,6 +264,8 @@
/* Event command complete */
#define BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN (6)
+#define BLE_HCI_EVENT_CMD_STATUS_LEN (6)
+
/* Advertising report */
#define BLE_HCI_ADV_RPT_EVTYPE_ADV_IND (0)
#define BLE_HCI_ADV_RPT_EVTYPE_DIR_IND (1)