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)