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/12/14 23:33:51 UTC

[2/4] incubator-mynewt-larva git commit: Generic HCI command queue.

Generic HCI command queue.


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/6d66ff88
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/6d66ff88
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/6d66ff88

Branch: refs/heads/master
Commit: 6d66ff88c911252a327ce8cd07477fb863cf2786
Parents: c2d99ec
Author: Christopher Collins <cc...@gmail.com>
Authored: Fri Dec 11 13:51:08 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Mon Dec 14 12:14:11 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_hs.h       |   1 +
 net/nimble/host/src/ble_gap.c               |  33 ++---
 net/nimble/host/src/ble_gap_conn.c          | 170 +++++++++++++++--------
 net/nimble/host/src/ble_hci_ack.c           |   4 +
 net/nimble/host/src/ble_hci_sched.c         | 158 +++++++++++++++++++++
 net/nimble/host/src/ble_hci_sched.h         |  11 ++
 net/nimble/host/src/ble_hs.c                |  19 ++-
 net/nimble/host/src/ble_hs_hci_batch.c      | 170 -----------------------
 net/nimble/host/src/ble_hs_hci_batch.h      |  55 --------
 net/nimble/host/src/test/ble_gap_test.c     |   3 +-
 net/nimble/host/src/test/ble_hs_conn_test.c |  10 +-
 net/nimble/host/src/test/ble_hs_test_util.c |   4 +-
 12 files changed, 320 insertions(+), 318 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/include/host/ble_hs.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_hs.h b/net/nimble/host/include/host/ble_hs.h
index 010e1f6..79ca8ae 100644
--- a/net/nimble/host/include/host/ble_hs.h
+++ b/net/nimble/host/include/host/ble_hs.h
@@ -29,6 +29,7 @@
 #define BLE_HS_ENOTSUP                  8
 #define BLE_HS_EATT                     9
 #define BLE_HS_EBADDATA                 10
+#define BLE_HS_EOS                      11
 
 int ble_hs_init(uint8_t prio);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_gap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index 7c90cb7..c19906f 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -19,7 +19,6 @@
 #include <string.h>
 #include "ble_hs_priv.h"
 #include "host/ble_gap.h"
-#include "ble_hs_hci_batch.h"
 #include "ble_gap_conn.h"
 
 /**
@@ -46,6 +45,7 @@ ble_gap_set_connect_cb(ble_gap_connect_fn *cb, void *arg)
 int
 ble_gap_general_discovery(void)
 {
+#if 0
     struct ble_hs_hci_batch_entry *entry;
 
     entry = ble_hs_hci_batch_entry_alloc();
@@ -57,6 +57,7 @@ ble_gap_general_discovery(void)
 
     ble_hs_hci_batch_enqueue(entry);
 
+#endif
     return 0;
 }
 
@@ -77,20 +78,13 @@ ble_gap_general_discovery(void)
 int
 ble_gap_direct_connection_establishment(uint8_t addr_type, uint8_t *addr)
 {
-    struct ble_hs_hci_batch_entry *entry;
+    int rc;
 
-    entry = ble_hs_hci_batch_entry_alloc();
-    if (entry == NULL) {
-        return BLE_HS_ENOMEM;
+    rc = ble_gap_conn_direct_connect(addr_type, addr);
+    if (rc != 0) {
+        return rc;
     }
 
-    entry->bhb_type = BLE_HS_HCI_BATCH_TYPE_DIRECT_CONNECT;
-    entry->bhb_direct_connect.bwdc_peer_addr_type = addr_type;
-    memcpy(entry->bhb_direct_connect.bwdc_peer_addr, addr,
-           sizeof entry->bhb_direct_connect.bwdc_peer_addr);
-
-    ble_hs_hci_batch_enqueue(entry);
-
     return 0;
 }
 
@@ -110,19 +104,12 @@ ble_gap_direct_connection_establishment(uint8_t addr_type, uint8_t *addr)
 int
 ble_gap_directed_connectable(uint8_t addr_type, uint8_t *addr)
 {
-    struct ble_hs_hci_batch_entry *entry;
+    int rc;
 
-    entry = ble_hs_hci_batch_entry_alloc();
-    if (entry == NULL) {
-        return BLE_HS_ENOMEM;
+    rc = ble_gap_conn_direct_advertise(addr_type, addr);
+    if (rc != 0) {
+        return rc;
     }
 
-    entry->bhb_type = BLE_HS_HCI_BATCH_TYPE_DIRECT_ADVERTISE;
-    entry->bhb_direct_advertise.bwda_peer_addr_type = addr_type;
-    memcpy(entry->bhb_direct_advertise.bwda_peer_addr, addr,
-           sizeof entry->bhb_direct_advertise.bwda_peer_addr);
-
-    ble_hs_hci_batch_enqueue(entry);
-
     return 0;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_gap_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap_conn.c b/net/nimble/host/src/ble_gap_conn.c
index 71d5579..1b158a4 100644
--- a/net/nimble/host/src/ble_gap_conn.c
+++ b/net/nimble/host/src/ble_gap_conn.c
@@ -23,7 +23,7 @@
 #include "ble_hci_ack.h"
 #include "ble_hs_conn.h"
 #include "ble_hci_ack.h"
-#include "ble_hs_hci_batch.h"
+#include "ble_hci_sched.h"
 #include "ble_gap_conn.h"
 
 #define BLE_GAP_CONN_STATE_IDLE                             0
@@ -32,12 +32,15 @@
 #define BLE_GAP_CONN_STATE_MASTER_GEN_DISC_PARAMS_ACKED     2
 #define BLE_GAP_CONN_STATE_MASTER_GEN_DISC_ENABLE_ACKED     3
 
-#define BLE_GAP_CONN_STATE_MASTER_DIRECT_UNACKED            4
-#define BLE_GAP_CONN_STATE_MASTER_DIRECT_ACKED              5
+#define BLE_GAP_CONN_STATE_MASTER_DIRECT_PENDING            4
+#define BLE_GAP_CONN_STATE_MASTER_DIRECT_UNACKED            5
+#define BLE_GAP_CONN_STATE_MASTER_DIRECT_ACKED              6
 
-#define BLE_GAP_CONN_STATE_SLAVE_UNACKED                    1
-#define BLE_GAP_CONN_STATE_SLAVE_PARAMS_ACKED               2
-#define BLE_GAP_CONN_STATE_SLAVE_ENABLE_ACKED               3
+#define BLE_GAP_CONN_STATE_SLAVE_PENDING                    1
+#define BLE_GAP_CONN_STATE_SLAVE_PARAMS                     2
+#define BLE_GAP_CONN_STATE_SLAVE_PARAMS_ACKED               3
+#define BLE_GAP_CONN_STATE_SLAVE_ENABLE                     4
+#define BLE_GAP_CONN_STATE_SLAVE_ENABLE_ACKED               5
 
 /** 30 ms. */
 #define BLE_GAP_ADV_FAST_INTERVAL1_MIN      (30 * 1000 / BLE_HCI_ADV_ITVL)
@@ -51,13 +54,15 @@
 /** 11.25 ms. */
 #define BLE_GAP_SCAN_SLOW_WINDOW1           (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
 
+static void ble_gap_conn_slave_ack(struct ble_hci_ack *ack, void *arg);
+
 ble_gap_connect_fn *ble_gap_conn_cb;
 void *ble_gap_conn_arg;
 
 static int ble_gap_conn_master_state;
 static int ble_gap_conn_slave_state;
-static uint8_t ble_gap_conn_addr_master[BLE_DEV_ADDR_LEN];
-static uint8_t ble_gap_conn_addr_slave[BLE_DEV_ADDR_LEN];
+static uint8_t ble_gap_conn_master_addr[BLE_DEV_ADDR_LEN];
+static uint8_t ble_gap_conn_slave_addr[BLE_DEV_ADDR_LEN];
 
 /**
  * Calls the connect callback if one is configured.
@@ -140,13 +145,11 @@ ble_gap_conn_master_ack(struct ble_hci_ack *ack, void *arg)
     case BLE_GAP_CONN_STATE_MASTER_GEN_DISC_PARAMS_ACKED:
         ble_gap_conn_master_state =
             BLE_GAP_CONN_STATE_MASTER_GEN_DISC_ENABLE_ACKED;
-        ble_hs_hci_batch_done();
         break;
 
     /*** Direct connect. */
     case BLE_GAP_CONN_STATE_MASTER_DIRECT_UNACKED:
         ble_gap_conn_master_state = BLE_GAP_CONN_STATE_MASTER_DIRECT_ACKED;
-        ble_hs_hci_batch_done();
         break;
 
     default:
@@ -155,6 +158,26 @@ ble_gap_conn_master_ack(struct ble_hci_ack *ack, void *arg)
     }
 }
 
+static int
+ble_gap_conn_direct_advertise_tx_enable(void *arg)
+{
+    int rc;
+
+    rc = host_hci_cmd_le_set_adv_enable(1);
+    if (rc != BLE_ERR_SUCCESS) {
+        goto err;
+    }
+
+    ble_hci_ack_set_callback(ble_gap_conn_slave_ack, NULL);
+    ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_ENABLE;
+
+    return 0;
+
+err:
+    ble_gap_conn_slave_failed(rc);
+    return 1;
+}
+
 /**
  * Processes an HCI acknowledgement (either command status or command complete)
  * while a slave connection is being established.
@@ -165,31 +188,36 @@ ble_gap_conn_slave_ack(struct ble_hci_ack *ack, void *arg)
     int rc;
 
     if (ack->bha_status != BLE_ERR_SUCCESS) {
-        ble_gap_conn_slave_failed(ack->bha_status);
-        return;
+        rc = ack->bha_status;
+        goto err;
     }
 
     switch (ble_gap_conn_slave_state) {
-    case BLE_GAP_CONN_STATE_SLAVE_UNACKED:
+    case BLE_GAP_CONN_STATE_SLAVE_PARAMS:
         ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_PARAMS_ACKED;
-        ble_hci_ack_set_callback(ble_gap_conn_slave_ack, NULL);
-        rc = host_hci_cmd_le_set_adv_enable(1);
-        if (rc != BLE_ERR_SUCCESS) {
-            ble_gap_conn_slave_failed(rc);
+        rc = ble_hci_sched_enqueue(ble_gap_conn_direct_advertise_tx_enable,
+                                   NULL);
+        if (rc != 0) {
+            goto err;
         }
         break;
 
-    case BLE_GAP_CONN_STATE_SLAVE_PARAMS_ACKED:
+    case BLE_GAP_CONN_STATE_SLAVE_ENABLE:
         ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_ENABLE_ACKED;
-        ble_hs_hci_batch_done();
         break;
 
     default:
         assert(0);
         break;
     }
+
+    return;
+
+err:
+    ble_gap_conn_slave_failed(rc);
 }
 
+#if 0
 int
 ble_gap_conn_general_discovery(void)
 {
@@ -220,30 +248,19 @@ err:
     ble_gap_conn_notify_app(rc, NULL);
     return rc;
 }
+#endif
 
-/**
- * Initiates a connection using the GAP Direct Connection Establishment
- * Procedure.
- *
- * @return 0 on success; nonzero on failure.
- */
-int
-ble_gap_conn_direct_connect(int addr_type, uint8_t *addr)
+static int
+ble_gap_conn_direct_connect_tx(void *arg)
 {
     struct hci_create_conn hcc;
     int rc;
 
-    /* Make sure no master connection attempt is already in progress. */
-    if (ble_gap_conn_master_in_progress()) {
-        rc = BLE_HS_EALREADY;
-        goto err;
-    }
-
     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.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
+    memcpy(hcc.peer_addr, ble_gap_conn_master_addr, sizeof hcc.peer_addr);
     hcc.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
     hcc.conn_itvl_min = 24;
     hcc.conn_itvl_max = 40;
@@ -252,8 +269,6 @@ ble_gap_conn_direct_connect(int addr_type, uint8_t *addr)
     hcc.min_ce_len = 0x0010; // XXX
     hcc.max_ce_len = 0x0300; // XXX
 
-    memcpy(ble_gap_conn_addr_master, addr, BLE_DEV_ADDR_LEN);
-
     rc = host_hci_cmd_le_create_connection(&hcc);
     if (rc != 0) {
         goto err;
@@ -265,51 +280,92 @@ ble_gap_conn_direct_connect(int addr_type, uint8_t *addr)
     return 0;
 
 err:
-    ble_gap_conn_notify_app(rc, NULL);
-    return rc;
+    ble_gap_conn_master_failed(rc);
+    return 1;
 }
 
 /**
- * Enables the GAP Directed Connectable Mode.
+ * Initiates a connection using the GAP Direct Connection Establishment
+ * Procedure.
  *
  * @return 0 on success; nonzero on failure.
  */
 int
-ble_gap_conn_direct_advertise(int addr_type, uint8_t *addr)
+ble_gap_conn_direct_connect(int addr_type, uint8_t *addr)
 {
-    struct hci_adv_params hap;
     int rc;
 
-    /* Make sure no slave connection attempt is already in progress. */
-    if (ble_gap_conn_slave_in_progress()) {
-        rc = BLE_HS_EALREADY;
-        goto err;
+    /* Make sure no master connection attempt is already in progress. */
+    if (ble_gap_conn_master_in_progress()) {
+        return BLE_HS_EALREADY;
+    }
+
+    ble_gap_conn_master_state = BLE_GAP_CONN_STATE_MASTER_DIRECT_PENDING;
+    memcpy(ble_gap_conn_master_addr, addr, BLE_DEV_ADDR_LEN);
+
+    rc = ble_hci_sched_enqueue(ble_gap_conn_direct_connect_tx, NULL);
+    if (rc != 0) {
+        ble_gap_conn_master_state = BLE_GAP_CONN_STATE_IDLE;
+        return rc;
     }
 
+    return 0;
+}
+
+static int
+ble_gap_conn_direct_advertise_tx_params(void *arg)
+{
+    struct hci_adv_params hap;
+    int rc;
+
     hap.adv_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
     hap.adv_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
     hap.adv_type = BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
     hap.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
-    hap.peer_addr_type = addr_type;
-    memcpy(hap.peer_addr, addr, sizeof hap.peer_addr);
+    hap.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
+    memcpy(hap.peer_addr, ble_gap_conn_slave_addr, sizeof hap.peer_addr);
     hap.adv_channel_map = BLE_HCI_ADV_CHANMASK_DEF;
     hap.adv_filter_policy = BLE_HCI_ADV_FILT_DEF;
 
-    memcpy(ble_gap_conn_addr_slave, addr, BLE_DEV_ADDR_LEN);
-
     rc = host_hci_cmd_le_set_adv_params(&hap);
     if (rc != 0) {
         goto err;
     }
 
-    ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_UNACKED;
+    ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_PARAMS;
     ble_hci_ack_set_callback(ble_gap_conn_slave_ack, NULL);
 
     return 0;
 
 err:
-    ble_gap_conn_notify_app(rc, NULL);
-    return rc;
+    ble_gap_conn_slave_failed(rc);
+    return 1;
+}
+
+/**
+ * Enables the GAP Directed Connectable Mode.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_gap_conn_direct_advertise(int addr_type, uint8_t *addr)
+{
+    int rc;
+
+    /* Make sure no slave connection attempt is already in progress. */
+    if (ble_gap_conn_slave_in_progress()) {
+        return BLE_HS_EALREADY;
+    }
+
+    rc = ble_hci_sched_enqueue(ble_gap_conn_direct_advertise_tx_params, NULL);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_SLAVE_PENDING;
+    memcpy(ble_gap_conn_slave_addr, addr, BLE_DEV_ADDR_LEN);
+
+    return 0;
 }
 
 static int
@@ -317,7 +373,7 @@ ble_gap_conn_accept_new_conn(uint8_t *addr)
 {
     switch (ble_gap_conn_master_state) {
     case BLE_GAP_CONN_STATE_MASTER_DIRECT_ACKED:
-        if (memcmp(ble_gap_conn_addr_master, addr, BLE_DEV_ADDR_LEN) == 0) {
+        if (memcmp(ble_gap_conn_master_addr, addr, BLE_DEV_ADDR_LEN) == 0) {
             ble_gap_conn_master_state = BLE_GAP_CONN_STATE_IDLE;
             return 0;
         }
@@ -325,7 +381,7 @@ ble_gap_conn_accept_new_conn(uint8_t *addr)
 
     switch (ble_gap_conn_slave_state) {
     case BLE_GAP_CONN_STATE_SLAVE_ENABLE_ACKED:
-        if (memcmp(ble_gap_conn_addr_slave, addr, BLE_DEV_ADDR_LEN) == 0) {
+        if (memcmp(ble_gap_conn_slave_addr, addr, BLE_DEV_ADDR_LEN) == 0) {
             ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_IDLE;
             return 0;
         }
@@ -436,8 +492,8 @@ ble_gap_conn_init(void)
     ble_gap_conn_cb = NULL;
     ble_gap_conn_master_state = BLE_GAP_CONN_STATE_IDLE;
     ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_IDLE;
-    memset(ble_gap_conn_addr_master, 0, sizeof ble_gap_conn_addr_master);
-    memset(ble_gap_conn_addr_slave, 0, sizeof ble_gap_conn_addr_slave);
+    memset(ble_gap_conn_master_addr, 0, sizeof ble_gap_conn_master_addr);
+    memset(ble_gap_conn_slave_addr, 0, sizeof ble_gap_conn_slave_addr);
 
     return 0;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hci_ack.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hci_ack.c b/net/nimble/host/src/ble_hci_ack.c
index 7d7f22d..c1cce92 100644
--- a/net/nimble/host/src/ble_hci_ack.c
+++ b/net/nimble/host/src/ble_hci_ack.c
@@ -21,9 +21,11 @@
 #include "nimble/hci_common.h"
 #include "ble_gap_conn.h"
 #include "ble_hs_conn.h"
+#include "ble_hci_sched.h"
 #include "ble_hci_ack.h"
 
 static ble_hci_ack_fn *ble_hci_ack_cb;
+
 static void *ble_hci_ack_arg;
 
 void
@@ -37,6 +39,8 @@ ble_hci_ack_rx(struct ble_hci_ack *ack)
 
         cb(ack, ble_hci_ack_arg);
     }
+
+    ble_hci_sched_command_complete();
 }
 
 void

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hci_sched.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hci_sched.c b/net/nimble/host/src/ble_hci_sched.c
new file mode 100644
index 0000000..d6c11d4
--- /dev/null
+++ b/net/nimble/host/src/ble_hci_sched.c
@@ -0,0 +1,158 @@
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "os/queue.h"
+#include "os/os_mempool.h"
+#include "ble_hs_priv.h"
+#include "ble_hci_sched.h"
+
+#define BLE_HCI_SCHED_NUM_ENTRIES       8
+
+struct ble_hci_sched_entry {
+    STAILQ_ENTRY(ble_hci_sched_entry) next;
+
+    ble_hci_sched_tx_fn *tx_cb;
+    void *tx_cb_arg;
+};
+
+static STAILQ_HEAD(, ble_hci_sched_entry) ble_hci_sched_list;
+
+static void *ble_hci_sched_entry_mem;
+static struct os_mempool ble_hci_sched_entry_pool;
+static struct ble_hci_sched_entry *ble_hci_sched_cur_entry;
+
+static struct ble_hci_sched_entry *
+ble_hci_sched_entry_alloc(void)
+{
+    struct ble_hci_sched_entry *entry;
+
+    entry = os_memblock_get(&ble_hci_sched_entry_pool);
+    if (entry != NULL) {
+        memset(entry, 0, sizeof *entry);
+    }
+
+    return entry;
+}
+
+static void
+ble_hci_sched_entry_free(struct ble_hci_sched_entry *entry)
+{
+    int rc;
+
+    rc = os_memblock_put(&ble_hci_sched_entry_pool, entry);
+    assert(rc == 0);
+}
+
+int
+ble_hci_sched_enqueue(ble_hci_sched_tx_fn *tx_cb, void *tx_cb_arg)
+{
+    struct ble_hci_sched_entry *entry;
+
+    entry = ble_hci_sched_entry_alloc();
+    if (entry == NULL) {
+        return BLE_HS_ENOMEM;
+    }
+
+    entry->tx_cb = tx_cb;
+    entry->tx_cb_arg = tx_cb_arg;
+    STAILQ_INSERT_TAIL(&ble_hci_sched_list, entry, next);
+
+    if (ble_hci_sched_cur_entry == NULL) {
+        ble_hs_kick_hci();
+    }
+
+    return 0;
+}
+
+static int
+ble_hci_sched_process_next(void)
+{
+    struct ble_hci_sched_entry *entry;
+    int rc;
+
+    assert(ble_hci_sched_cur_entry == NULL);
+
+    entry = STAILQ_FIRST(&ble_hci_sched_list);
+    if (entry == NULL) {
+        return 0;
+    }
+
+    STAILQ_REMOVE_HEAD(&ble_hci_sched_list, next);
+
+    rc = entry->tx_cb(entry->tx_cb_arg);
+    if (rc == 0) {
+        ble_hci_sched_cur_entry = entry;
+        return 0;
+    } else {
+        return BLE_HS_EAGAIN;
+    }
+}
+
+void
+ble_hci_sched_wakeup(void)
+{
+    int rc;
+
+    do {
+        rc = ble_hci_sched_process_next();
+    } while (rc == BLE_HS_EAGAIN);
+}
+
+void
+ble_hci_sched_command_complete(void)
+{
+    if (ble_hci_sched_cur_entry == NULL) {
+        /* XXX: Increment stat. */
+        return;
+    }
+
+    ble_hci_sched_entry_free(ble_hci_sched_cur_entry);
+    ble_hci_sched_cur_entry = NULL;
+
+    if (!STAILQ_EMPTY(&ble_hci_sched_list)) {
+        ble_hs_kick_hci();
+    }
+}
+
+static void
+ble_hci_sched_free_mem(void)
+{
+    free(ble_hci_sched_entry_mem);
+    ble_hci_sched_entry_mem = NULL;
+}
+
+int
+ble_hci_sched_init(void)
+{
+    int rc;
+
+    ble_hci_sched_free_mem();
+
+    ble_hci_sched_entry_mem = malloc(
+        OS_MEMPOOL_BYTES(BLE_HCI_SCHED_NUM_ENTRIES,
+                         sizeof (struct ble_hci_sched_entry)));
+    if (ble_hci_sched_entry_mem == NULL) {
+        rc = BLE_HS_ENOMEM;
+        goto err;
+    }
+
+    rc = os_mempool_init(&ble_hci_sched_entry_pool,
+                         BLE_HCI_SCHED_NUM_ENTRIES,
+                         sizeof (struct ble_hci_sched_entry),
+                         ble_hci_sched_entry_mem,
+                         "ble_hci_sched_entry_pool");
+    if (rc != 0) {
+        rc = BLE_HS_EOS;
+        goto err;
+    }
+
+    STAILQ_INIT(&ble_hci_sched_list);
+
+    ble_hci_sched_cur_entry = NULL;
+
+    return 0;
+
+err:
+    ble_hci_sched_free_mem();
+    return rc;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hci_sched.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hci_sched.h b/net/nimble/host/src/ble_hci_sched.h
new file mode 100644
index 0000000..389a8f6
--- /dev/null
+++ b/net/nimble/host/src/ble_hci_sched.h
@@ -0,0 +1,11 @@
+#ifndef H_BLE_HCI_SCHED_
+#define H_BLE_HCI_SCHED_
+
+typedef int ble_hci_sched_tx_fn(void *arg);
+
+int ble_hci_sched_enqueue(ble_hci_sched_tx_fn *tx_cb, void *tx_cb_arg);
+void ble_hci_sched_wakeup(void);
+void ble_hci_sched_command_complete(void);
+int ble_hci_sched_init(void);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hs.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index 67e4d12..16660fc 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -24,7 +24,7 @@
 #include "ble_att_priv.h"
 #include "ble_hs_conn.h"
 #include "ble_hci_ack.h"
-#include "ble_hs_hci_batch.h"
+#include "ble_hci_sched.h"
 #include "ble_gap_conn.h"
 #ifdef PHONY_TRANSPORT
 #include "host/ble_hs_test.h"
@@ -116,6 +116,7 @@ ble_hs_process_rx_data_queue(void)
     }
 }
 
+#if 0
 static int
 ble_hs_read_hci_buf_size(void)
 {
@@ -132,16 +133,17 @@ ble_hs_read_hci_buf_size(void)
 
     return 0;
 }
+#endif
 
 static void
 ble_hs_task_handler(void *arg)
 {
     struct os_event *ev;
     struct os_callout_func *cf;
-    int rc;
+    //int rc;
 
-    rc = ble_hs_read_hci_buf_size();
-    assert(rc == 0);
+    //rc = ble_hs_read_hci_buf_size();
+    //assert(rc == 0);
 
     while (1) {
         ev = os_eventq_get(&ble_hs_evq);
@@ -166,7 +168,7 @@ ble_hs_task_handler(void *arg)
             break;
 
         case BLE_HS_KICK_HCI_EVENT:
-            ble_hs_hci_batch_process_next();
+            ble_hci_sched_wakeup();
             break;
 
         case BLE_HS_KICK_GATT_EVENT:
@@ -326,10 +328,17 @@ ble_hs_init(uint8_t prio)
 
     ble_hci_ack_init();
 
+    rc = ble_hci_sched_init();
+    if (rc != 0) {
+        goto err;
+    }
+
+#if 0
     rc = ble_hs_hci_batch_init();
     if (rc != 0) {
         goto err;
     }
+#endif
 
     rc = ble_gatt_init();
     if (rc != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hs_hci_batch.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_batch.c b/net/nimble/host/src/ble_hs_hci_batch.c
deleted file mode 100644
index be0bb26..0000000
--- a/net/nimble/host/src/ble_hs_hci_batch.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * 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 <stddef.h>
-#include <assert.h>
-#include <errno.h>
-#include "os/os.h"
-#include "host/host_hci.h"
-#include "ble_hs_priv.h"
-#include "ble_hci_ack.h"
-#include "ble_gap_conn.h"
-#include "ble_hs_hci_batch.h"
-
-#define BLE_HS_HCI_BATCH_NUM_ENTRIES     16
-
-static void *ble_hs_hci_batch_entry_mem;
-static struct os_mempool ble_hs_hci_batch_entry_pool;
-static STAILQ_HEAD(, ble_hs_hci_batch_entry) ble_hs_hci_batch_queue;
-
-static struct ble_hs_hci_batch_entry *ble_hs_hci_batch_cur_entry;
-
-struct ble_hs_hci_batch_entry *
-ble_hs_hci_batch_entry_alloc(void)
-{
-    struct ble_hs_hci_batch_entry *entry;
-
-    entry = os_memblock_get(&ble_hs_hci_batch_entry_pool);
-    return entry;
-}
-
-void
-ble_hs_hci_batch_enqueue(struct ble_hs_hci_batch_entry *entry)
-{
-    STAILQ_INSERT_TAIL(&ble_hs_hci_batch_queue, entry, bhb_next);
-    if (ble_hs_hci_batch_cur_entry == NULL) {
-        ble_hs_kick_hci();
-    }
-}
-
-void
-ble_hs_hci_batch_done(void)
-{
-    assert(ble_hs_hci_batch_cur_entry != NULL);
-    os_memblock_put(&ble_hs_hci_batch_entry_pool, ble_hs_hci_batch_cur_entry);
-    ble_hs_hci_batch_cur_entry = NULL;
-
-    if (!STAILQ_EMPTY(&ble_hs_hci_batch_queue)) {
-        ble_hs_kick_hci();
-    }
-}
-
-static void
-ble_hs_hci_read_buf_size_ack(struct ble_hci_ack *ack, void *arg)
-{
-    uint16_t pktlen;
-    uint8_t max_pkts;
-    int rc;
-
-    if (ack->bha_status != 0) {
-        /* XXX: Log / stat this. */
-        return;
-    }
-
-    if (ack->bha_params_len != BLE_HCI_RD_BUF_SIZE_RSPLEN + 1) {
-        /* XXX: Log / stat this. */
-        return;
-    }
-
-    pktlen = le16toh(ack->bha_params + 1);
-    max_pkts = ack->bha_params[3];
-
-    rc = host_hci_set_buf_size(pktlen, max_pkts);
-    if (rc != 0) {
-        /* XXX: Send BR command instead. */
-        return;
-    }
-
-    ble_hs_hci_batch_done();
-}
-
-void
-ble_hs_hci_batch_process_next(void)
-{
-    struct ble_hs_hci_batch_entry *entry;
-    int rc;
-
-    entry = STAILQ_FIRST(&ble_hs_hci_batch_queue);
-    if (entry == NULL) {
-        return;
-    }
-
-    STAILQ_REMOVE_HEAD(&ble_hs_hci_batch_queue, bhb_next);
-    ble_hs_hci_batch_cur_entry = entry;
-
-    switch (entry->bhb_type) {
-    case BLE_HS_HCI_BATCH_TYPE_DIRECT_CONNECT:
-        rc = ble_gap_conn_direct_connect(
-            entry->bhb_direct_connect.bwdc_peer_addr_type,
-            entry->bhb_direct_connect.bwdc_peer_addr);
-        break;
-
-    case BLE_HS_HCI_BATCH_TYPE_DIRECT_ADVERTISE:
-        rc = ble_gap_conn_direct_advertise(
-            entry->bhb_direct_advertise.bwda_peer_addr_type,
-            entry->bhb_direct_advertise.bwda_peer_addr);
-        break;
-
-    case BLE_HS_HCI_BATCH_TYPE_READ_HCI_BUF_SIZE:
-        ble_hci_ack_set_callback(ble_hs_hci_read_buf_size_ack, NULL);
-        rc = host_hci_cmd_le_read_buffer_size();
-        if (rc != 0) {
-            /* XXX: Call callback. */
-        }
-        break;
-
-    case BLE_HS_HCI_BATCH_TYPE_GENERAL_DISCOVERY:
-        rc = ble_gap_conn_general_discovery();
-        break;
-
-    default:
-        assert(0);
-        break;
-    }
-
-    if (rc != 0) {
-        ble_hs_hci_batch_done();
-    }
-}
-
-int
-ble_hs_hci_batch_init(void)
-{
-    int rc;
-
-    free(ble_hs_hci_batch_entry_mem);
-    ble_hs_hci_batch_entry_mem = malloc(
-        OS_MEMPOOL_BYTES(BLE_HS_HCI_BATCH_NUM_ENTRIES,
-                         sizeof (struct ble_hs_hci_batch_entry)));
-    if (ble_hs_hci_batch_entry_mem == NULL) {
-        return BLE_HS_ENOMEM;
-    }
-
-    rc = os_mempool_init(&ble_hs_hci_batch_entry_pool,
-                         BLE_HS_HCI_BATCH_NUM_ENTRIES,
-                         sizeof (struct ble_hs_hci_batch_entry),
-                         ble_hs_hci_batch_entry_mem,
-                         "ble_hs_hci_batch_entry_pool");
-    if (rc != 0) {
-        return BLE_HS_EINVAL; // XXX
-    }
-
-    STAILQ_INIT(&ble_hs_hci_batch_queue);
-
-    ble_hs_hci_batch_cur_entry = NULL;
-
-    return 0;
-}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/ble_hs_hci_batch.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_batch.h b/net/nimble/host/src/ble_hs_hci_batch.h
deleted file mode 100644
index af2cde1..0000000
--- a/net/nimble/host/src/ble_hs_hci_batch.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * 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.
- */
-
-#ifndef H_BLE_HCI_BATCH_
-#define H_BLE_HCI_BATCH_
-
-#include <inttypes.h>
-#include "os/queue.h"
-
-#define BLE_HS_HCI_BATCH_TYPE_DIRECT_CONNECT     0
-#define BLE_HS_HCI_BATCH_TYPE_DIRECT_ADVERTISE   1
-#define BLE_HS_HCI_BATCH_TYPE_READ_HCI_BUF_SIZE  2
-#define BLE_HS_HCI_BATCH_TYPE_GENERAL_DISCOVERY  3
-#define BLE_HS_HCI_BATCH_TYPE_MAX                4
-
-struct ble_hs_hci_batch_direct_connect {
-    uint8_t bwdc_peer_addr[8];
-    uint8_t bwdc_peer_addr_type;
-};
-
-struct ble_hs_hci_batch_direct_advertise {
-    uint8_t bwda_peer_addr[8];
-    uint8_t bwda_peer_addr_type;
-};
-
-struct ble_hs_hci_batch_entry {
-    int bhb_type;
-    STAILQ_ENTRY(ble_hs_hci_batch_entry) bhb_next;
-
-    union {
-        struct ble_hs_hci_batch_direct_connect bhb_direct_connect;
-        struct ble_hs_hci_batch_direct_advertise bhb_direct_advertise;
-    };
-};
-
-struct ble_hs_hci_batch_entry *ble_hs_hci_batch_entry_alloc(void);
-void ble_hs_hci_batch_enqueue(struct ble_hs_hci_batch_entry *entry);
-void ble_hs_hci_batch_done(void);
-void ble_hs_hci_batch_process_next(void);
-int ble_hs_hci_batch_init(void);
-
-#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/test/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
index b353da4..cbc9ae0 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -24,7 +24,6 @@
 #include "host/ble_gap.h"
 #include "ble_hs_test_util.h"
 #include "ble_hs_conn.h"
-#include "ble_hs_hci_batch.h"
 #include "ble_gap_conn.h"
 
 #ifdef ARCH_sim
@@ -78,7 +77,7 @@ ble_gap_test_task_handler(void *arg)
     /* Receive the HCI buffer size acknowledgement.  We sent the corresponding
      * request when the host task was started.
      */
-    ble_hs_test_util_rx_hci_buf_size_ack(0xffff);
+    //ble_hs_test_util_rx_hci_buf_size_ack(0xffff);
 
     /* Set the connect callback so we can verify that it gets called with the
      * proper arguments.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/test/ble_hs_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_conn_test.c b/net/nimble/host/src/test/ble_hs_conn_test.c
index 1fce0f7..dab15de 100644
--- a/net/nimble/host/src/test/ble_hs_conn_test.c
+++ b/net/nimble/host/src/test/ble_hs_conn_test.c
@@ -25,7 +25,7 @@
 #include "ble_att_priv.h"
 #include "ble_hs_conn.h"
 #include "ble_hci_ack.h"
-#include "ble_hs_hci_batch.h"
+#include "ble_hci_sched.h"
 #include "ble_gap_conn.h"
 #include "ble_hs_test_util.h"
 #include "testutil/testutil.h"
@@ -48,7 +48,7 @@ TEST_CASE(ble_hs_conn_test_master_direct_success)
     rc = ble_gap_direct_connection_establishment(0, addr);
     TEST_ASSERT(rc == 0);
 
-    ble_hs_hci_batch_process_next();
+    ble_hci_sched_wakeup();
 
     TEST_ASSERT(ble_gap_conn_master_in_progress());
 
@@ -94,7 +94,7 @@ TEST_CASE(ble_hs_conn_test_master_direct_hci_errors)
     rc = ble_gap_direct_connection_establishment(0, addr);
     TEST_ASSERT(rc == 0);
 
-    ble_hs_hci_batch_process_next();
+    ble_hci_sched_wakeup();
 
     TEST_ASSERT(ble_gap_conn_master_in_progress());
 
@@ -139,7 +139,7 @@ TEST_CASE(ble_hs_conn_test_slave_direct_success)
     rc = ble_gap_directed_connectable(0, addr);
     TEST_ASSERT(rc == 0);
 
-    ble_hs_hci_batch_process_next();
+    ble_hci_sched_wakeup();
 
     TEST_ASSERT(!ble_gap_conn_master_in_progress());
     TEST_ASSERT(ble_gap_conn_slave_in_progress());
@@ -149,6 +149,8 @@ TEST_CASE(ble_hs_conn_test_slave_direct_success)
     TEST_ASSERT(!ble_gap_conn_master_in_progress());
     TEST_ASSERT(ble_gap_conn_slave_in_progress());
 
+    ble_hci_sched_wakeup();
+
     /* Receive set-adv-enable ack. */
     ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_SET_ADV_ENABLE, BLE_ERR_SUCCESS);
     TEST_ASSERT(!ble_gap_conn_master_in_progress());

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/6d66ff88/net/nimble/host/src/test/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index 8fff249..eed81fd 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -22,9 +22,9 @@
 #include "host/host_hci.h"
 #include "ble_hs_priv.h"
 #include "ble_hci_ack.h"
+#include "ble_hci_sched.h"
 #include "ble_hs_conn.h"
 #include "ble_gap_conn.h"
-#include "ble_hs_hci_batch.h"
 #include "ble_l2cap.h"
 #include "ble_att_cmd.h"
 #include "ble_hs_test_util.h"
@@ -68,7 +68,7 @@ ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr)
     rc = ble_gap_direct_connection_establishment(0, addr);
     TEST_ASSERT(rc == 0);
 
-    ble_hs_hci_batch_process_next();
+    ble_hci_sched_wakeup();
 
     ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_CREATE_CONN, BLE_ERR_SUCCESS);