MYNEWT-87: add channel map update procedure. This also fixes a big in the data 
channel selection index code that was not picking the correct channels if any 
channels were masked out


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

Branch: refs/heads/develop
Commit: 9e54d5f5e076b6f39f6babc11aa20988c45c6455
Parents: f1e3970
Author: wes3 <w...@micosa.io>
Authored: Wed Feb 17 16:34:25 2016 -0800
Committer: wes3 <w...@micosa.io>
Committed: Wed Feb 17 17:01:03 2016 -0800

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll.h      |   2 +-
 .../controller/include/controller/ble_ll_conn.h |   5 +-
 net/nimble/controller/src/ble_ll.c              |   1 -
 net/nimble/controller/src/ble_ll_conn.c         | 104 ++++++++++----
 net/nimble/controller/src/ble_ll_conn_hci.c     |  75 +++++++++-
 net/nimble/controller/src/ble_ll_conn_priv.h    |  23 +++-
 net/nimble/controller/src/ble_ll_ctrl.c         |  92 +++++++++++--
 net/nimble/controller/src/ble_ll_hci.c          | 137 +++++++++----------
 net/nimble/host/include/host/host_hci.h         |   2 +
 net/nimble/host/src/host_dbg.c                  |  11 ++
 net/nimble/host/src/host_hci_cmd.c              |  36 +++++
 net/nimble/include/nimble/hci_common.h          |  15 ++
 net/nimble/src/hci_common.c                     |  80 +++++++++++
 project/bletest/src/main.c                      |  40 ++++--
 14 files changed, 493 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h 
b/net/nimble/controller/include/controller/ble_ll.h
index 402f078..e9000ab 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -348,7 +348,7 @@ uint8_t ble_ll_read_supp_features(void);
  * XXX: temporary LL debug log. Will get removed once we transition to real
  * log
  */ 
-#undef BLE_LL_LOG
+#define BLE_LL_LOG
 
 #define BLE_LL_LOG_ID_PHY_SETCHAN       (1)
 #define BLE_LL_LOG_ID_RX_START          (2)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h 
b/net/nimble/controller/include/controller/ble_ll_conn.h
index 172d076..b1bceca 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -76,7 +76,8 @@ union ble_ll_conn_sm_flags {
         uint16_t host_expects_upd_event:1;
         uint16_t version_ind_sent:1;
         uint16_t rxd_version_ind:1;
-        uint16_t reserved:4;
+        uint16_t chanmap_update_scheduled:1;
+        uint16_t reserved:3;
     } cfbit;
     uint16_t conn_flags;
 } __attribute__((packed));
@@ -107,6 +108,8 @@ struct ble_ll_conn_sm
 
     /* Used to calculate data channel index for connection */
     uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
+    uint8_t req_chanmap[BLE_LL_CONN_CHMAP_LEN];
+    uint16_t chanmap_instant;
     uint8_t hop_inc;
     uint8_t data_chan_index;
     uint8_t unmapped_chan;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c 
b/net/nimble/controller/src/ble_ll.c
index 687e79d..5896918 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -837,7 +837,6 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t 
hdr)
     ble_hdr->txinfo.hdr_byte = hdr;
 }
 
-
 /**
  * Called to reset the controller. This performs a "software reset" of the 
link 
  * layer; it does not perform a HW reset of the controller nor does it reset 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c 
b/net/nimble/controller/src/ble_ll_conn.c
index a1e2d03..7dd18ad 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -118,16 +118,6 @@ static const uint16_t g_ble_sca_ppm_tbl[8] =
     500, 250, 150, 100, 75, 50, 30, 20
 };
 
-/* Global Link Layer connection parameters */
-struct ble_ll_conn_global_params
-{
-    uint8_t supp_max_tx_octets;
-    uint8_t supp_max_rx_octets;
-    uint8_t conn_init_max_tx_octets;
-    uint16_t conn_init_max_tx_time;
-    uint16_t supp_max_tx_time;
-    uint16_t supp_max_rx_time;
-};
 struct ble_ll_conn_global_params g_ble_ll_conn_params;
 
 /* Pointer to connection state machine we are trying to create */
@@ -464,6 +454,7 @@ ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn)
 {
     int     i;
     int     j;
+    uint8_t chan;
     uint8_t curchan;
     uint8_t remap_index;
     uint8_t bitpos;
@@ -490,6 +481,7 @@ ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn)
         /* NOTE: possible to build a map but this would use memory. For now,
            we just calculate */
         /* Iterate through channel map to find this channel */
+        chan = 0;
         cntr = 0;
         for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; i++) {
             usable_chans = conn->chanmap[i];
@@ -498,13 +490,14 @@ ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn)
                 for (j = 0; j < 8; j++) {
                     if (usable_chans & mask) {
                         if (cntr == remap_index) {
-                            return cntr;
+                            return (chan + j);
                         }
                         ++cntr;
                     }
                     mask <<= 1;
                 }
             }
+            chan += 8;
         }
     }
 
@@ -940,13 +933,10 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
         connsm->max_ce_len = hcc->max_ce_len;
     }
 
-    /* 
-     * XXX: for now, just set the channel map to all 1's. Needs to get
-     * set to default or initialized or something
-     */ 
-    connsm->num_used_chans = BLE_PHY_NUM_DATA_CHANS;
-    memset(connsm->chanmap, 0xff, BLE_LL_CONN_CHMAP_LEN - 1);
-    connsm->chanmap[4] = 0x1f;
+    /* Set channel map to map requested by host */
+    connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans;
+    memcpy(connsm->chanmap, g_ble_ll_conn_params.master_chan_map,
+           BLE_LL_CONN_CHMAP_LEN);
 
     /*  Calculate random access address and crc initialization value */
     connsm->access_addr = ble_ll_conn_calc_access_addr();
@@ -1206,18 +1196,12 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         connsm->csmflags.cfbit.host_expects_upd_event = 0;
     }
 
-    /* 
-     * XXX: not quite sure I am interpreting slave latency correctly here.
-     * The spec says if you applied slave latency and you dont hear a packet,
-     * you dont apply slave latency. Does that mean you dont apply slave
-     * latency until you hear a packet or on the next interval if you listen
-     * and dont hear anything, can you apply slave latency?
-     */
     /* Set event counter to the next connection event that we will tx/rx in */
     itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
     latency = 1;
-    if (connsm->csmflags.cfbit.allow_slave_latency && 
-        !connsm->csmflags.cfbit.conn_update_scheduled) {
+    if (connsm->csmflags.cfbit.allow_slave_latency      && 
+        !connsm->csmflags.cfbit.conn_update_scheduled   &&
+        !connsm->csmflags.cfbit.chanmap_update_scheduled) {
         if (connsm->csmflags.cfbit.pkt_rxd) {
             latency += connsm->slave_latency;
             itvl = itvl * latency;
@@ -1267,6 +1251,34 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         connsm->csmflags.cfbit.conn_update_scheduled = 0;
     }
 
+    /* 
+     * If there is a channel map request pending and we have reached the
+     * instant, change to new channel map. Note there is a special case here.
+     * If we received a channel map update with an instant equal to the event
+     * counter, when we get here the event counter has already been
+     * incremented by 1. That is why we do a signed comparison and change to
+     * new channel map once the event counter equals or has passed channel
+     * map update instant.
+     */ 
+    if (connsm->csmflags.cfbit.chanmap_update_scheduled && 
+        ((int16_t)(connsm->chanmap_instant - connsm->event_cntr) <= 0)) {
+
+        /* XXX: there is a chance that the control packet is still on
+         * the queue of the master. This means that we never successfully
+         * transmitted update request. Would end up killing connection
+           on slave side. Could ignore it or see if still enqueued. */
+        connsm->num_used_chans = 
+            ble_ll_conn_calc_used_chans(connsm->req_chanmap);
+        memcpy(connsm->chanmap, connsm->req_chanmap, BLE_LL_CONN_CHMAP_LEN);
+
+        connsm->csmflags.cfbit.chanmap_update_scheduled = 0;
+
+        ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD);
+
+        /* XXX: host could have resent channel map command. Need to
+           check to make sure we dont have to restart! */
+    }
+
     /* Calculate data channel index of next connection event */
     while (latency > 0) {
         connsm->last_unmapped_chan = connsm->unmapped_chan;
@@ -2225,6 +2237,36 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t 
handle, uint16_t length)
 }
 
 /**
+ * Called to set the global channel mask that we use for all connections.
+ * 
+ * @param num_used_chans 
+ * @param chanmap 
+ */
+void
+ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap)
+{
+    struct ble_ll_conn_sm *connsm;
+    struct ble_ll_conn_global_params *conn_params;
+
+    /* Do nothing if same channel map */
+    conn_params = &g_ble_ll_conn_params;
+    if (!memcmp(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN)) 
{
+        return;
+    }
+
+    /* Change channel map and cause channel map update procedure to start */
+    conn_params->num_used_chans = num_used_chans;
+    memcpy(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN);
+
+    /* Perform channel map update */
+    SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD);
+        }
+    }
+}
+
+/**
  * Called when a device has received a connect request while advertising and 
  * the connect request has passed the advertising filter policy and is for 
  * us. This will start a connection in the slave role assuming that we dont 
@@ -2378,6 +2420,9 @@ ble_ll_conn_reset(void)
         }
         ble_ll_conn_end(connsm, BLE_ERR_SUCCESS);
     }
+
+    /* Call conn module init */
+    ble_ll_conn_module_init();
 }
 
 /* Initialize the connection module */
@@ -2436,5 +2481,10 @@ ble_ll_conn_module_init(void)
     maxbytes = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES + BLE_LL_DATA_MIC_LEN;
     conn_params->conn_init_max_tx_time = BLE_TX_DUR_USECS_M(maxbytes);
     conn_params->conn_init_max_tx_octets = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES;
+
+    /* Mask in all channels by default */
+    conn_params->num_used_chans = BLE_PHY_NUM_DATA_CHANS;
+    memset(conn_params->master_chan_map, 0xff, BLE_LL_CONN_CHMAP_LEN - 1);
+    conn_params->master_chan_map[4] = 0x1f;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll_conn_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_hci.c 
b/net/nimble/controller/src/ble_ll_conn_hci.c
index 2ded499..0e9a9c9 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -435,7 +435,7 @@ ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct 
ble_ll_conn_sm *connsm)
  * @return int 
  */
 int
-ble_ll_conn_read_rem_features(uint8_t *cmdbuf)
+ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf)
 {
     uint16_t handle;
     struct ble_ll_conn_sm *connsm;
@@ -521,6 +521,16 @@ ble_ll_conn_hci_update(uint8_t *cmdbuf)
         }
     }
 
+    /* 
+     * If we are a slave and the master has initiated the channel map
+     * update procedure we should deny the slave request for now.
+     */
+    if (connsm->csmflags.cfbit.chanmap_update_scheduled) {
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+            return BLE_ERR_DIFF_TRANS_COLL;
+        }
+    }
+
     /* Retrieve command data */
     hcu = &connsm->conn_param_req;
     hcu->handle = handle;
@@ -788,3 +798,66 @@ ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, 
uint8_t *rsplen)
     return rc;
 }
 
+/**
+ * Called to read the current channel map of a connection 
+ * 
+ * @param cmdbuf 
+ * @param rspbuf 
+ * @param rsplen 
+ * 
+ * @return int 
+ */
+int
+ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
+{
+    int rc;
+    uint16_t handle;
+    struct ble_ll_conn_sm *connsm;
+
+    handle = le16toh(cmdbuf);
+    connsm = ble_ll_conn_find_active_conn(handle);
+    if (!connsm) {
+        rc = BLE_ERR_UNK_CONN_ID;
+    } else {
+        if (connsm->csmflags.cfbit.chanmap_update_scheduled) {
+            memcpy(rspbuf + 2, &connsm->req_chanmap[0], BLE_LL_CONN_CHMAP_LEN);
+        } else {
+            memcpy(rspbuf + 2, &connsm->chanmap[0], BLE_LL_CONN_CHMAP_LEN);
+        }
+        rc = BLE_ERR_SUCCESS;
+    }
+
+    htole16(rspbuf, handle);
+    *rsplen = sizeof(uint16_t) + BLE_LL_CONN_CHMAP_LEN;
+    return rc;
+}
+
+/**
+ * Called when the host issues the LE command "set host channel classification"
+ * 
+ * @param cmdbuf 
+ * 
+ * @return int 
+ */
+int
+ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf)
+{
+    int rc;
+    uint8_t num_used_chans;
+
+    /* 
+     * The HCI command states that the host is allowed to mask in just one
+     * channel but the Link Layer needs minimum two channels to operate. So
+     * I will not allow this command if there are less than 2 channels masked.
+     */
+    rc = BLE_ERR_SUCCESS;
+    num_used_chans = ble_ll_conn_calc_used_chans(cmdbuf);
+    if ((num_used_chans < 2) || ((cmdbuf[4] & 0xe0) != 0)) {
+        rc = BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    /* Set the host channel mask */
+    ble_ll_conn_set_global_chanmap(num_used_chans, cmdbuf);
+    return rc;
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h 
b/net/nimble/controller/src/ble_ll_conn_priv.h
index f31aeae..5d29337 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -51,6 +51,21 @@
 /* Offset (in bytes) of advertising address in connect request */
 #define BLE_LL_CONN_REQ_ADVA_OFF    (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
 
+/* Global Link Layer connection parameters */
+struct ble_ll_conn_global_params
+{
+    uint8_t master_chan_map[BLE_LL_CONN_CHMAP_LEN];
+    uint8_t num_used_chans;
+    uint8_t supp_max_tx_octets;
+    uint8_t supp_max_rx_octets;
+    uint8_t conn_init_max_tx_octets;
+    uint8_t reserved;
+    uint16_t conn_init_max_tx_time;
+    uint16_t supp_max_tx_time;
+    uint16_t supp_max_rx_time;
+};
+extern struct ble_ll_conn_global_params g_ble_ll_conn_params;
+
 /* Some data structures used by other LL routines */
 SLIST_HEAD(ble_ll_conn_active_list, ble_ll_conn_sm);
 STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm);
@@ -80,6 +95,7 @@ int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t 
conn_req_end);
 
 /* Link Layer interface */
 void ble_ll_conn_module_init(void);
+void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap);
 void ble_ll_conn_reset(void);
 void ble_ll_conn_event_end(void *arg);
 void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
@@ -93,15 +109,16 @@ void ble_ll_conn_wfr_timer_exp(void);
 int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2);
 uint32_t ble_ll_conn_get_ce_end_time(void);
 void ble_ll_conn_event_halt(void);
+uint8_t ble_ll_conn_calc_used_chans(uint8_t *chmap);
 
 /* HCI */
 void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, 
                                     uint8_t reason);
-
 int ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf);
 int ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf);
 int ble_ll_conn_create(uint8_t *cmdbuf);
 int ble_ll_conn_hci_update(uint8_t *cmdbuf);
+int ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf);
 int ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int negative_reply);
 int ble_ll_conn_create_cancel(void);
 void ble_ll_conn_num_comp_pkts_event_send(void);
@@ -109,7 +126,9 @@ void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm 
*connsm, uint8_t status);
 void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
 int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
                                     uint16_t latency, uint16_t spvn_tmo);
-int ble_ll_conn_read_rem_features(uint8_t *cmdbuf);
+int ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf);
 int ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf, 
+                                uint8_t *rsplen);
 
 #endif /* H_BLE_LL_CONN_PRIV_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c 
b/net/nimble/controller/src/ble_ll_ctrl.c
index 59b5e6f..7925a64 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -386,6 +386,27 @@ ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm 
*connsm, uint8_t *pyld)
 }
 
 /**
+ * Called to make a LL control channel map request PDU.
+ * 
+ * @param connsm    Pointer to connection state machine
+ * @param pyld      Pointer to payload of LL control PDU
+ */
+static void
+ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld)
+{
+    /* Copy channel map that host desires into request */
+    memcpy(pyld, g_ble_ll_conn_params.master_chan_map, BLE_LL_CONN_CHMAP_LEN);
+    memcpy(connsm->req_chanmap, pyld, BLE_LL_CONN_CHMAP_LEN);
+
+    /* Place instant into request */
+    connsm->chanmap_instant = connsm->event_cntr + connsm->slave_latency + 6 + 
1;
+    htole16(pyld + BLE_LL_CONN_CHMAP_LEN, connsm->chanmap_instant);
+
+    /* Set scheduled flag */
+    connsm->csmflags.cfbit.chanmap_update_scheduled = 1;
+}
+
+/**
  * Called to make a connection update request LL control PDU
  *  
  * Context: Link Layer 
@@ -633,6 +654,18 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm 
*connsm, uint8_t *dptr,
         }
     }
 
+    /* 
+     * If we are a master and we currently performing a channel map
+     * update procedure we need to return an error
+     */ 
+    if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) &&
+        (connsm->csmflags.cfbit.chanmap_update_scheduled)) {
+        rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
+        rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ;
+        rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL;
+        return rsp_opcode;
+    }
+
     /* Process the received connection parameter request */
     rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf,
                                                  BLE_LL_CTRL_CONN_PARM_REQ);
@@ -709,6 +742,32 @@ ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm *connsm, 
uint8_t *dptr,
 }
 
 /**
+ * Called to process a received channel map request control pdu. 
+ *  
+ * Context: Link Layer task 
+ * 
+ * @param connsm 
+ * @param dptr 
+ */
+static void
+ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+    uint16_t instant;
+    uint16_t conn_events;
+
+    /* If instant is in the past, we have to end the connection */
+    instant = le16toh(dptr + BLE_LL_CONN_CHMAP_LEN);
+    conn_events = (instant - connsm->event_cntr) & 0xFFFF;
+    if (conn_events >= 32767) {
+        ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED);
+    } else {
+        connsm->chanmap_instant = instant;
+        memcpy(connsm->req_chanmap, dptr, BLE_LL_CONN_CHMAP_LEN);
+        connsm->csmflags.cfbit.chanmap_update_scheduled = 1;
+    }
+}
+
+/**
  * Callback when LL control procedure times out (for a given connection). If 
  * this is called, it means that we need to end the connection because it 
  * has not responded to a LL control request. 
@@ -751,6 +810,10 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int 
ctrl_proc)
             opcode = BLE_LL_CTRL_CONN_UPDATE_REQ;
             ble_ll_ctrl_conn_upd_make(connsm, dptr + 1, NULL);
             break;
+        case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
+            opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ;
+            ble_ll_ctrl_chanmap_req_make(connsm, dptr + 1);
+            break;
         case BLE_LL_CTRL_PROC_FEATURE_XCHG:
             if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
                 opcode = BLE_LL_CTRL_FEATURE_REQ;
@@ -910,14 +973,16 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int 
ctrl_proc)
             connsm->cur_ctrl_proc = ctrl_proc;
 
             /* Initialize the procedure response timeout */
-            os_callout_func_init(&connsm->ctrl_proc_rsp_timer, 
-                                 &g_ble_ll_data.ll_evq, 
-                                 ble_ll_ctrl_proc_rsp_timer_cb, 
-                                 connsm);
-
-            /* Re-start the timer. Control procedure timeout is 40 seconds */
-            os_callout_reset(&connsm->ctrl_proc_rsp_timer.cf_c, 
-                             OS_TICKS_PER_SEC * BLE_LL_CTRL_PROC_TIMEOUT);
+            if (ctrl_proc != BLE_LL_CTRL_PROC_CHAN_MAP_UPD) {
+                os_callout_func_init(&connsm->ctrl_proc_rsp_timer,
+                                     &g_ble_ll_data.ll_evq, 
+                                     ble_ll_ctrl_proc_rsp_timer_cb, 
+                                     connsm);
+
+                /* Re-start timer. Control procedure timeout is 40 seconds */
+                os_callout_reset(&connsm->ctrl_proc_rsp_timer.cf_c, 
+                                 OS_TICKS_PER_SEC * BLE_LL_CTRL_PROC_TIMEOUT);
+            }
         }
     }
 
@@ -1055,6 +1120,11 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct 
os_mbuf *om)
     case BLE_LL_CTRL_CONN_UPDATE_REQ:
         rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr, rspbuf);
         break;
+    case BLE_LL_CTRL_CHANNEL_MAP_REQ:
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+            ble_ll_ctrl_rx_chanmap_req(connsm, dptr);
+        }
+        break;
     case BLE_LL_CTRL_LENGTH_REQ:
         /* Extract parameters and check if valid */
         if (ble_ll_ctrl_len_proc(connsm, dptr)) {
@@ -1092,7 +1162,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct 
os_mbuf *om)
     case BLE_LL_CTRL_UNKNOWN_RSP:
         ble_ll_ctrl_proc_unk_rsp(connsm, dptr);
         break;
-
     case BLE_LL_CTRL_FEATURE_REQ:
         if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
             rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf);
@@ -1103,7 +1172,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct 
os_mbuf *om)
             rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
         }
         break;
-
     /* XXX: check to see if ctrl procedure was running? Do we care? */
     case BLE_LL_CTRL_FEATURE_RSP:
         /* Stop the control procedure */
@@ -1113,11 +1181,9 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct 
os_mbuf *om)
             ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
         }
         break;
-
     case BLE_LL_CTRL_VERSION_IND:
         rsp_opcode = ble_ll_ctrl_rx_version_ind(connsm, dptr, rspbuf + 1);
         break;
-
     case BLE_LL_CTRL_SLAVE_FEATURE_REQ:
         if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
             rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf);
@@ -1127,9 +1193,7 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct 
os_mbuf *om)
             rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
         }
         break;
-
     /* XXX: remember to check if feature supported. Implement! */
-    case BLE_LL_CTRL_CHANNEL_MAP_REQ:
     case BLE_LL_CTRL_ENC_REQ:
     case BLE_LL_CTRL_START_ENC_REQ:
     case BLE_LL_CTRL_PAUSE_ENC_REQ:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c 
b/net/nimble/controller/src/ble_ll_hci.c
index 5412698..a508871 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -229,6 +229,32 @@ ble_ll_hci_is_event_enabled(int bitpos)
 }
 
 /**
+ * Called to determine if the reply to the command should be a command 
complete 
+ * event or a command status event. 
+ * 
+ * @param ocf 
+ * 
+ * @return int 0: return command complete; 1: return command status event
+ */
+static int
+ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
+{
+    int rc;
+
+    switch (ocf) {
+    case BLE_HCI_OCF_LE_RD_REM_FEAT:
+    case BLE_HCI_OCF_LE_CREATE_CONN:
+    case BLE_HCI_OCF_LE_CONN_UPDATE:
+        rc = 1;
+        break;
+    default:
+        rc = 0;
+        break;
+    }
+    return rc;
+}
+
+/**
  * Process a LE command sent from the host to the controller. The HCI command 
  * has a 3 byte command header followed by data. The header is: 
  *  -> opcode (2 bytes)
@@ -246,6 +272,7 @@ static int
 ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
 {
     int rc;
+    uint8_t cmdlen;
     uint8_t len;
     uint8_t *rspbuf;
 
@@ -255,6 +282,12 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, 
uint8_t *rsplen)
     /* Get length from command */
     len = cmdbuf[sizeof(uint16_t)];
 
+    /* Check the length to make sure it is valid */
+    cmdlen = g_ble_hci_le_cmd_len[ocf];
+    if ((cmdlen != 0xFF) && (len != cmdlen)) {
+        goto ll_hci_le_cmd_exit;
+    }
+
     /* 
      * The command response pointer points into the same buffer as the
      * command data itself. That is fine, as each command reads all the data
@@ -267,35 +300,23 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, 
uint8_t *rsplen)
 
     switch (ocf) {
     case BLE_HCI_OCF_LE_SET_EVENT_MASK:
-        if (len == BLE_HCI_SET_LE_EVENT_MASK_LEN) {
-            rc = ble_ll_hci_set_le_event_mask(cmdbuf);
-        }
+        rc = ble_ll_hci_set_le_event_mask(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_RD_BUF_SIZE:
-        if (len == BLE_HCI_RD_BUF_SIZE_LEN) {
-            rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen);
-        }
+        rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen);
         break;
     case BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT:
-        if (len == 0) {
-            rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen);
-        }
+        rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen);
         break;
     case BLE_HCI_OCF_LE_SET_RAND_ADDR:
-        if (len == BLE_DEV_ADDR_LEN) {
-            rc = ble_ll_set_random_addr(cmdbuf);
-        }
+        rc = ble_ll_set_random_addr(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_SET_ADV_PARAMS:
         /* Length should be one byte */
-        if (len == BLE_HCI_SET_ADV_PARAM_LEN) {
-            rc = ble_ll_adv_set_adv_params(cmdbuf);
-        }
+        rc = ble_ll_adv_set_adv_params(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR:
-        if (len == 0) {
-            rc = ble_ll_adv_read_txpwr(rspbuf, rsplen);
-        }
+        rc = ble_ll_adv_read_txpwr(rspbuf, rsplen);
         break;
     case BLE_HCI_OCF_LE_SET_ADV_DATA:
         if (len > 0) {
@@ -311,87 +332,65 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, 
uint8_t *rsplen)
         break;
     case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
         /* Length should be one byte */
-        if (len == BLE_HCI_SET_ADV_ENABLE_LEN) {
-            rc = ble_ll_adv_set_enable(cmdbuf);
-        }
+        rc = ble_ll_adv_set_enable(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_SET_SCAN_ENABLE:
-        if (len == BLE_HCI_SET_SCAN_ENABLE_LEN) {
-            rc = ble_ll_scan_set_enable(cmdbuf);
-        }
+        rc = ble_ll_scan_set_enable(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_SET_SCAN_PARAMS:
-        /* Length should be one byte */
-        if (len == BLE_HCI_SET_SCAN_PARAM_LEN) {
-            rc = ble_ll_scan_set_scan_params(cmdbuf);
-        }
+        rc = ble_ll_scan_set_scan_params(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_CREATE_CONN:
-        if (len == BLE_HCI_CREATE_CONN_LEN) {
-            rc = ble_ll_conn_create(cmdbuf);
-        }
-        /* This is a hack; command status gets sent instead of cmd complete */
-        rc += (BLE_ERR_MAX + 1);
+        rc = ble_ll_conn_create(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
-        if (len == 0) {
-            rc = ble_ll_conn_create_cancel();
-        }
+        rc = ble_ll_conn_create_cancel();
         break;
     case BLE_HCI_OCF_LE_CLEAR_WHITE_LIST:
-        if (len == 0) {
-            rc = ble_ll_whitelist_clear();
-        }
+        rc = ble_ll_whitelist_clear();
         break;
     case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE:
-        if (len == 0) {
-            rc = ble_ll_whitelist_read_size(rspbuf, rsplen);
-        }
+        rc = ble_ll_whitelist_read_size(rspbuf, rsplen);
         break;
     case BLE_HCI_OCF_LE_ADD_WHITE_LIST:
-        if (len == BLE_HCI_CHG_WHITE_LIST_LEN) {
-            rc = ble_ll_whitelist_add(cmdbuf + 1, cmdbuf[0]);
-        }
+        rc = ble_ll_whitelist_add(cmdbuf + 1, cmdbuf[0]);
         break;
     case BLE_HCI_OCF_LE_RMV_WHITE_LIST:
-        if (len == BLE_HCI_CHG_WHITE_LIST_LEN) {
-            rc = ble_ll_whitelist_rmv(cmdbuf + 1, cmdbuf[0]);
-        }
+        rc = ble_ll_whitelist_rmv(cmdbuf + 1, cmdbuf[0]);
         break;
     case BLE_HCI_OCF_LE_CONN_UPDATE:
-        if (len == BLE_HCI_CONN_UPDATE_LEN) {
-            rc = ble_ll_conn_hci_update(cmdbuf);
-        }
-        /* This is a hack; command status gets sent instead of cmd complete */
-        rc += (BLE_ERR_MAX + 1);
+        rc = ble_ll_conn_hci_update(cmdbuf);
+        break;
+    case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS:
+        rc = ble_ll_conn_hci_set_chan_class(cmdbuf);
+        break;
+    case BLE_HCI_OCF_LE_RD_CHAN_MAP:
+        rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, rspbuf, rsplen);
         break;
-
-        /* XXX: implement */
     case BLE_HCI_OCF_LE_RD_REM_FEAT:
-        if (len == BLE_HCI_CONN_RD_REM_FEAT_LEN) {
-            rc = ble_ll_conn_read_rem_features(cmdbuf);
-        }
-        /* This is a hack; command status gets sent instead of cmd complete */
-        rc += (BLE_ERR_MAX + 1);
+        rc = ble_ll_conn_hci_read_rem_features(cmdbuf);
         break;
-
     case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR:
-        if (len == BLE_HCI_CONN_PARAM_NEG_REPLY_LEN) {
-            rc = ble_ll_conn_hci_param_reply(cmdbuf, 0);
-        }
+        rc = ble_ll_conn_hci_param_reply(cmdbuf, 0);
         break;
-
     case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR:
-        if (len == BLE_HCI_CONN_PARAM_REPLY_LEN) {
-            rc = ble_ll_conn_hci_param_reply(cmdbuf, 1);
-        }
+        rc = ble_ll_conn_hci_param_reply(cmdbuf, 1);
         break;
-
     default:
         rc = BLE_ERR_UNKNOWN_HCI_CMD;
         break;
     }
 
+    /* 
+     * This code is here because we add 256 to the return code to denote
+     * that the reply to this command should be command status (as opposed to
+     * command complete).
+     */ 
+ll_hci_le_cmd_exit:
+    if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) {
+        rc += (BLE_ERR_MAX + 1);
+    }
+
     return rc;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/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 4dc16a9..f141a22 100644
--- a/net/nimble/host/include/host/host_hci.h
+++ b/net/nimble/host/include/host/host_hci.h
@@ -32,6 +32,8 @@ int host_hci_cmd_disconnect(uint16_t handle, uint8_t reason);
 int host_hci_cmd_rd_rem_version(uint16_t handle);
 int host_hci_cmd_rd_local_version(void);
 int host_hci_cmd_read_rssi(uint16_t handle);
+int host_hci_cmd_le_set_host_chan_class(uint8_t *new_chan_map);
+int host_hci_cmd_le_rd_chanmap(uint16_t handle);
 int host_hci_cmd_le_set_scan_rsp_data(uint8_t *data, uint8_t len);
 int host_hci_cmd_le_set_adv_data(uint8_t *data, uint8_t len);
 int host_hci_cmd_le_set_adv_params(struct hci_adv_params *adv);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/host/src/host_dbg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_dbg.c b/net/nimble/host/src/host_dbg.c
index e1c99a8..a009a15 100644
--- a/net/nimble/host/src/host_dbg.c
+++ b/net/nimble/host/src/host_dbg.c
@@ -251,6 +251,17 @@ host_hci_dbg_cmd_complete_disp(uint8_t *evdata, uint8_t 
len)
             break;
         }
         break;
+    case BLE_HCI_OGF_LE:
+        switch (ocf) {
+        case BLE_HCI_OCF_LE_RD_CHAN_MAP:
+            BLE_HS_LOG(DEBUG, " handle=%u chanmap=%x.%x.%x.%x.%x", 
+                       le16toh(evdata + 4), evdata[6], evdata[7], evdata[8],
+                       evdata[9], evdata[10]);
+            break;
+        default:
+            break;
+        }
+        break;
     default:
         break;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/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
index 500f3cc..ac8c67e 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -641,6 +641,42 @@ host_hci_cmd_le_conn_param_neg_reply(struct 
hci_conn_param_neg_reply *hcn)
 }
 
 /**
+ * Read the channel map for a given connection.
+ * 
+ * @param handle 
+ * 
+ * @return int 
+ */
+int
+host_hci_cmd_le_rd_chanmap(uint16_t handle)
+{
+    int rc;
+    uint8_t cmd[BLE_HCI_RD_CHANMAP_LEN];
+
+    htole16(cmd, handle);
+    rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_RD_CHAN_MAP,
+                              BLE_HCI_RD_CHANMAP_LEN, cmd);
+    return rc;
+}
+
+/**
+ * Set the channel map in the controller
+ * 
+ * @param chanmap 
+ * 
+ * @return int 
+ */
+int
+host_hci_cmd_le_set_host_chan_class(uint8_t *chanmap)
+{
+    int rc;
+
+    rc = host_hci_le_cmd_send(BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS,
+                              BLE_HCI_SET_HOST_CHAN_CLASS_LEN, chanmap);
+    return rc;
+}
+
+/**
  * Read the RSSI for a given connection handle
  * 
  * NOTE: OGF=0x05 OCF=0x0005 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/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 77834ec..2978eb2 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -49,6 +49,12 @@
 /* NOTE: 0x07 not defined in specification  */
 #define BLE_HCI_OGF_LE                      (0x08)
 
+/* 
+ * Number of LE commands. NOTE: this is really just used to size the array
+ * containing the lengths of the LE commands.
+ */
+#define BLE_HCI_NUM_LE_CMDS                 (48)
+
 /* List of OCF for Link Control commands (OGF=0x01) */
 #define BLE_HCI_OCF_DISCONNECT_CMD          (0x0006)
 #define BLE_HCI_OCF_RD_REM_VER_INFO         (0x001D)
@@ -299,6 +305,12 @@
 /* --- LE connection update (OCF 0x0013) */
 #define BLE_HCI_CONN_UPDATE_LEN             (14)
 
+/* --- LE set host channel classification command (OCF 0x0014) */
+#define BLE_HCI_SET_HOST_CHAN_CLASS_LEN     (5)
+
+/* --- LE read channel map command (OCF 0x0015) */
+#define BLE_HCI_RD_CHANMAP_LEN              (2)
+
 /* --- LE read remote features (OCF 0x0016) */
 #define BLE_HCI_CONN_RD_REM_FEAT_LEN        (2)
 
@@ -595,4 +607,7 @@ struct hci_data_hdr
 #define BLE_HCI_PB_FIRST_FLUSH              2
 #define BLE_HCI_PB_FULL                     3
 
+/* External data structures */
+extern const uint8_t g_ble_hci_le_cmd_len[BLE_HCI_NUM_LE_CMDS];
+
 #endif /* H_BLE_HCI_COMMON_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/net/nimble/src/hci_common.c
----------------------------------------------------------------------
diff --git a/net/nimble/src/hci_common.c b/net/nimble/src/hci_common.c
new file mode 100644
index 0000000..e30e071
--- /dev/null
+++ b/net/nimble/src/hci_common.c
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 "os/os.h"
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+
+/* 
+ * Lengths for commands. NOTE: 0xFF is a special case and means that there
+ * is no fixed length for the command or is a command that we have not
+ * implemented.
+ */ 
+const uint8_t g_ble_hci_le_cmd_len[BLE_HCI_NUM_LE_CMDS] = 
+{
+    0,                                  /* 0x0000: reserved */
+    BLE_HCI_SET_LE_EVENT_MASK_LEN,      /* 0x0001: set event mask */
+    BLE_HCI_RD_BUF_SIZE_LEN,            /* 0x0002: read buffer size */
+    0,                                  /* 0x0003: read local supp features */
+    0,                                  /* 0x0004: not defined */
+    BLE_DEV_ADDR_LEN,                   /* 0x0005: set random address */
+    BLE_HCI_SET_ADV_PARAM_LEN,          /* 0x0006: set advertising parameters 
*/
+    0,                                  /* 0x0007: read adv chan tx power */
+    0xFF,                               /* 0x0008: set advertising data */
+    0xFF,                               /* 0x0009: set scan rsp data */
+    BLE_HCI_SET_ADV_ENABLE_LEN,         /* 0x000A: set advertising enable */
+    BLE_HCI_SET_SCAN_PARAM_LEN,         /* 0x000B: set scan parameters */
+    BLE_HCI_SET_SCAN_ENABLE_LEN,        /* 0x000C: set scan enable */
+    BLE_HCI_CREATE_CONN_LEN,            /* 0x000D: create connection */
+    0,                                  /* 0x000E: create connection cancel*/
+    0,                                  /* 0x000F: read whitelist size */
+    0,                                  /* 0x0010: clear white list */
+    BLE_HCI_CHG_WHITE_LIST_LEN,         /* 0x0011: add to white list */
+    BLE_HCI_CHG_WHITE_LIST_LEN,         /* 0x0012: remove from white list */
+    BLE_HCI_CONN_UPDATE_LEN,            /* 0x0013: connection update */
+    BLE_HCI_SET_HOST_CHAN_CLASS_LEN,    /* 0x0014: set host chan class */
+    sizeof(uint16_t),                   /* 0x0015: read channel map */
+    BLE_HCI_CONN_RD_REM_FEAT_LEN,       /* 0x0016: read remote features */
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    BLE_HCI_CONN_PARAM_REPLY_LEN,       /* 0x0020: conn param reply */
+    BLE_HCI_CONN_PARAM_NEG_REPLY_LEN,   /* 0x0021: conn param neg reply */
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,                               /* 0x002F: Read max data length */
+};
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/9e54d5f5/project/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/project/bletest/src/main.c b/project/bletest/src/main.c
index 6c24e64..0000ffa 100755
--- a/project/bletest/src/main.c
+++ b/project/bletest/src/main.c
@@ -110,7 +110,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_CFG_CONN_SPVN_TMO       (1000)  /* 20 seconds */
 #define BLETEST_CFG_MIN_CE_LEN          (6)    
 #define BLETEST_CFG_MAX_CE_LEN          (BLETEST_CFG_CONN_ITVL)
-#define BLETEST_CFG_CONCURRENT_CONNS    (16)
+#define BLETEST_CFG_CONCURRENT_CONNS    (1)
 
 /* BLETEST variables */
 #undef BLETEST_ADV_PKT_NUM
@@ -378,9 +378,10 @@ bletest_init_initiator(void)
 void
 bletest_execute_initiator(void)
 {
-//    int i;
+    int i;
     int rc;
     uint16_t handle;
+    uint8_t new_chan_map[5];
 
     /* 
      * Determine if there is an active connection for the current handle
@@ -413,22 +414,33 @@ bletest_execute_initiator(void)
             }
         }
     } else {
-#if 0
         if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
-            for (i = 0; i < g_bletest_current_conns; ++i) {
-                if (ble_ll_conn_find_active_conn(i + 1)) {
-                    /* Ask for version information */
-                    host_hci_cmd_read_rssi(i+1);
-                    host_hci_outstanding_opcode = 0;
-
-                    #if 0
-                        bletest_send_conn_update(1);
-                    #endif
-                }   
+            if ((g_bletest_state == 1) || (g_bletest_state == 3)) {
+                for (i = 0; i < g_bletest_current_conns; ++i) {
+                    if (ble_ll_conn_find_active_conn(i + 1)) {
+                        host_hci_cmd_le_rd_chanmap(i+1);
+                        host_hci_outstanding_opcode = 0;
+                    }   
+                }
+            } else if (g_bletest_state == 2) {
+                new_chan_map[0] = 0;
+                new_chan_map[1] = 0x3;
+                new_chan_map[2] = 0;
+                new_chan_map[3] = 0;
+                new_chan_map[4] = 0;
+                host_hci_cmd_le_set_host_chan_class(new_chan_map);
+                host_hci_outstanding_opcode = 0;
+            } else {
+                for (i = 0; i < g_bletest_current_conns; ++i) {
+                    if (ble_ll_conn_find_active_conn(i + 1)) {
+                        host_hci_cmd_read_rssi(i+1);
+                        host_hci_outstanding_opcode = 0;
+                    }   
+                }
             }
+            ++g_bletest_state;
             g_next_os_time = os_time_get() + OS_TICKS_PER_SEC * 5;
         }
-#endif
     }
 }
 #endif


Reply via email to