Просмотр исходного кода

【添加】增加Profile及应用示例

EvalZero 6 лет назад
Родитель
Сommit
0c3d7e89b9

+ 72 - 0
SConscript

@@ -31,6 +31,7 @@ src += Split('''
     nimble/host/src/ble_gap.c
     nimble/host/src/ble_gattc.c
     nimble/host/src/ble_gatts.c
+    nimble/host/src/ble_gatts_lcl.c
     nimble/host/src/ble_hs_adv.c
     nimble/host/src/ble_hs_atomic.c
     nimble/host/src/ble_hs.c
@@ -66,6 +67,7 @@ src += Split('''
     nimble/host/src/ble_uuid.c
     nimble/host/services/ans/src/ble_svc_ans.c
     nimble/host/services/bas/src/ble_svc_bas.c
+    nimble/host/services/bleuart/src/ble_svc_uart.c
     nimble/host/services/gap/src/ble_svc_gap.c
     nimble/host/services/gatt/src/ble_svc_gatt.c
     nimble/host/services/ias/src/ble_svc_ias.c
@@ -90,6 +92,7 @@ src += Split('''
     porting/npl/rtthread/src/modlog.c
     porting/npl/rtthread/src/nimble_port_rtthread.c
     porting/npl/rtthread/src/npl_os_rtthread.c
+    porting/npl/rtthread/src/npl_shell.c
     ''')
 
 if GetDepend(['NIMBLE_BSP_NRF52']):
@@ -143,6 +146,26 @@ if GetDepend(['NIMBLE_CTLR']):
         porting/nimble/src/hal_timer.c
         """)
 
+# central sample
+if GetDepend(['NIMBLE_SAMPLE_CENTRAL']):
+    path += [cwd + '/apps/blecent/src']
+    
+    src += Split("""
+        apps/blecent/src/blecent.c
+        apps/blecent/src/misc.c
+        apps/blecent/src/peer.c
+        """)
+
+# blecsc sensor
+if GetDepend(['NIMBLE_SAMPLE_BLECSC']):
+    path += [cwd + '/apps/blecsc/src']
+
+    src += Split("""
+        apps/blecsc/src/blecsc_sens.c
+        apps/blecsc/src/gatt_svr.c
+        """)
+
+
 # peripheral heart-rate sample
 if GetDepend(['NIMBLE_SAMPLE_PER_HR']):
     path += [cwd + '/apps/blehr/src']
@@ -152,6 +175,55 @@ if GetDepend(['NIMBLE_SAMPLE_PER_HR']):
         apps/blehr/src/gatt_svr.c
         """)
 
+# bleprph sample
+if GetDepend(['NIMBLE_SAMPLE_PERIPHERAL']):
+    path += [cwd + '/apps/bleprph/src']
+    
+    src += Split("""
+        apps/bleprph/src/bleprph.c
+        apps/bleprph/src/gatt_svr.c
+        apps/bleprph/src/misc.c
+        """)
+
+# bletest
+if GetDepend(['NIMBLE_SAMPLE_BLETEST']):
+    path += [cwd + '/apps/bletest/src']
+
+    src += Split("""
+        apps/bletest/src/bletest_hci.c
+        apps/bletest/src/bletest.c
+        """)
+
+# bleuart
+if GetDepend(['NIMBLE_SAMPLE_BLEUART']):
+    path += [cwd + '/apps/bleuart/src']
+
+    src += Split("""
+        apps/bleuart/src/bleuart.c
+        """)
+
+# btshell
+if GetDepend(['NIMBLE_SAMPLE_BTSHELL']):
+    path += [cwd + '/apps/btshell/src']
+
+    src += Split("""
+        apps/btshell/src/btshell.c
+        apps/btshell/src/cmd_gatt.c
+        apps/btshell/src/cmd_l2cap.c
+        apps/btshell/src/cmd.c
+        apps/btshell/src/gatt_svr.c
+        apps/btshell/src/misc.c
+        apps/btshell/src/parse.c
+        """)
+
+# ble external advertiser sample
+if GetDepend(['NIMBLE_SAMPLE_EXT_ADVERTISER']):
+    path += [cwd + '/apps/ext_advertiser/src']
+
+    src += Split("""
+        apps/ext_advertiser/src/ext_advertiser.c
+        """)
+
 # beacon sample
 if GetDepend(['NIMBLE_SAMPLE_BEACON']):
     src += Glob('apps/ibeacon/src/ibeacon.c')

+ 11 - 15
apps/blecent/src/main.c → apps/blecent/src/blecent.c

@@ -19,17 +19,16 @@
 
 #include <assert.h>
 #include <string.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
+
+#include <rtthread.h>
 
 /* BLE */
 #include "nimble/ble.h"
-#include "controller/ble_ll.h"
 #include "host/ble_hs.h"
 #include "host/util/util.h"
 
-/* RAM HCI transport. */
-#include "transport/ram/ble_hci_ram.h"
+/* HCI transport. */
+#include "nimble/ble_hci_trans.h"
 
 /* Mandatory services. */
 #include "services/gap/ble_svc_gap.h"
@@ -204,7 +203,7 @@ blecent_on_disc_complete(const struct peer *peer, int status, void *arg)
      * list of services, characteristics, and descriptors that the peer
      * supports.
      */
-    MODLOG_DFLT(ERROR, "Service discovery complete; status=%d "
+    MODLOG_DFLT(INFO, "Service discovery complete; status=%d "
                        "conn_handle=%d\n", status, peer->conn_handle);
 
     /* Now perform three concurrent GATT procedures against the peer: read,
@@ -484,6 +483,7 @@ blecent_on_sync(void)
     blecent_scan();
 }
 
+extern int nimble_ble_enable(void);
 /**
  * main
  *
@@ -491,14 +491,10 @@ blecent_on_sync(void)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(void)
+int blecent_entry(void)
 {
     int rc;
 
-    /* Initialize OS */
-    sysinit();
-
     /* Configure the host. */
     ble_hs_cfg.reset_cb = blecent_on_reset;
     ble_hs_cfg.sync_cb = blecent_on_sync;
@@ -512,10 +508,10 @@ main(void)
     rc = ble_svc_gap_device_name_set("nimble-blecent");
     assert(rc == 0);
 
-    /* os start should never return. If it does, this should be an error */
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
-    }
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
 
     return 0;
 }
+
+MSH_CMD_EXPORT_ALIAS(blecent_entry, blecent, "bluetooth centrol role sample");

+ 1 - 1
apps/blecent/src/blecent.h

@@ -20,7 +20,7 @@
 #ifndef H_BLECENT_
 #define H_BLECENT_
 
-#include "os/mynewt.h"
+#include "nimble/ble.h"
 #include "modlog/modlog.h"
 #ifdef __cplusplus
 extern "C" {

+ 37 - 37
apps/blecent/src/misc.c

@@ -33,7 +33,7 @@ print_bytes(const uint8_t *bytes, int len)
     int i;
 
     for (i = 0; i < len; i++) {
-        MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
+        MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
     }
 }
 
@@ -45,7 +45,7 @@ print_mbuf(const struct os_mbuf *om)
     colon = 0;
     while (om != NULL) {
         if (colon) {
-            MODLOG_DFLT(DEBUG, ":");
+            MODLOG_DFLT(INFO, ":");
         } else {
             colon = 1;
         }
@@ -72,7 +72,7 @@ print_uuid(const ble_uuid_t *uuid)
 {
     char buf[BLE_UUID_STR_LEN];
 
-    MODLOG_DFLT(DEBUG, "%s", ble_uuid_to_str(uuid, buf));
+    MODLOG_DFLT(INFO, "%s", ble_uuid_to_str(uuid, buf));
 }
 
 /**
@@ -81,16 +81,16 @@ print_uuid(const ble_uuid_t *uuid)
 void
 print_conn_desc(const struct ble_gap_conn_desc *desc)
 {
-    MODLOG_DFLT(DEBUG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ",
+    MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ",
                 desc->conn_handle, desc->our_ota_addr.type,
                 addr_str(desc->our_ota_addr.val));
-    MODLOG_DFLT(DEBUG, "our_id_addr_type=%d our_id_addr=%s ",
+    MODLOG_DFLT(INFO, "our_id_addr_type=%d our_id_addr=%s ",
                 desc->our_id_addr.type, addr_str(desc->our_id_addr.val));
-    MODLOG_DFLT(DEBUG, "peer_ota_addr_type=%d peer_ota_addr=%s ",
+    MODLOG_DFLT(INFO, "peer_ota_addr_type=%d peer_ota_addr=%s ",
                 desc->peer_ota_addr.type, addr_str(desc->peer_ota_addr.val));
-    MODLOG_DFLT(DEBUG, "peer_id_addr_type=%d peer_id_addr=%s ",
+    MODLOG_DFLT(INFO, "peer_id_addr_type=%d peer_id_addr=%s ",
                 desc->peer_id_addr.type, addr_str(desc->peer_id_addr.val));
-    MODLOG_DFLT(DEBUG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+    MODLOG_DFLT(INFO, "conn_itvl=%d conn_latency=%d supervision_timeout=%d "
                 "encrypted=%d authenticated=%d bonded=%d",
                 desc->conn_itvl, desc->conn_latency,
                 desc->supervision_timeout,
@@ -108,102 +108,102 @@ print_adv_fields(const struct ble_hs_adv_fields *fields)
     int i;
 
     if (fields->flags != 0) {
-        MODLOG_DFLT(DEBUG, "    flags=0x%02x\n", fields->flags);
+        MODLOG_DFLT(INFO, "    flags=0x%02x\n", fields->flags);
     }
 
     if (fields->uuids16 != NULL) {
-        MODLOG_DFLT(DEBUG, "    uuids16(%scomplete)=",
+        MODLOG_DFLT(INFO, "    uuids16(%scomplete)=",
                     fields->uuids16_is_complete ? "" : "in");
         for (i = 0; i < fields->num_uuids16; i++) {
             print_uuid(&fields->uuids16[i].u);
-            MODLOG_DFLT(DEBUG, " ");
+            MODLOG_DFLT(INFO, " ");
         }
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->uuids32 != NULL) {
-        MODLOG_DFLT(DEBUG, "    uuids32(%scomplete)=",
+        MODLOG_DFLT(INFO, "    uuids32(%scomplete)=",
                     fields->uuids32_is_complete ? "" : "in");
         for (i = 0; i < fields->num_uuids32; i++) {
             print_uuid(&fields->uuids32[i].u);
-            MODLOG_DFLT(DEBUG, " ");
+            MODLOG_DFLT(INFO, " ");
         }
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->uuids128 != NULL) {
-        MODLOG_DFLT(DEBUG, "    uuids128(%scomplete)=",
+        MODLOG_DFLT(INFO, "    uuids128(%scomplete)=",
                     fields->uuids128_is_complete ? "" : "in");
         for (i = 0; i < fields->num_uuids128; i++) {
             print_uuid(&fields->uuids128[i].u);
-            MODLOG_DFLT(DEBUG, " ");
+            MODLOG_DFLT(INFO, " ");
         }
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->name != NULL) {
         assert(fields->name_len < sizeof s - 1);
         memcpy(s, fields->name, fields->name_len);
         s[fields->name_len] = '\0';
-        MODLOG_DFLT(DEBUG, "    name(%scomplete)=%s\n",
+        MODLOG_DFLT(INFO, "    name(%scomplete)=%s\n",
                     fields->name_is_complete ? "" : "in", s);
     }
 
     if (fields->tx_pwr_lvl_is_present) {
-        MODLOG_DFLT(DEBUG, "    tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
+        MODLOG_DFLT(INFO, "    tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
     }
 
     if (fields->slave_itvl_range != NULL) {
-        MODLOG_DFLT(DEBUG, "    slave_itvl_range=");
+        MODLOG_DFLT(INFO, "    slave_itvl_range=");
         print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->svc_data_uuid16 != NULL) {
-        MODLOG_DFLT(DEBUG, "    svc_data_uuid16=");
+        MODLOG_DFLT(INFO, "    svc_data_uuid16=");
         print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->public_tgt_addr != NULL) {
-        MODLOG_DFLT(DEBUG, "    public_tgt_addr=");
+        MODLOG_DFLT(INFO, "    public_tgt_addr=");
         u8p = fields->public_tgt_addr;
         for (i = 0; i < fields->num_public_tgt_addrs; i++) {
-            MODLOG_DFLT(DEBUG, "public_tgt_addr=%s ", addr_str(u8p));
+            MODLOG_DFLT(INFO, "public_tgt_addr=%s ", addr_str(u8p));
             u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
         }
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->appearance_is_present) {
-        MODLOG_DFLT(DEBUG, "    appearance=0x%04x\n", fields->appearance);
+        MODLOG_DFLT(INFO, "    appearance=0x%04x\n", fields->appearance);
     }
 
     if (fields->adv_itvl_is_present) {
-        MODLOG_DFLT(DEBUG, "    adv_itvl=0x%04x\n", fields->adv_itvl);
+        MODLOG_DFLT(INFO, "    adv_itvl=0x%04x\n", fields->adv_itvl);
     }
 
     if (fields->svc_data_uuid32 != NULL) {
-        MODLOG_DFLT(DEBUG, "    svc_data_uuid32=");
+        MODLOG_DFLT(INFO, "    svc_data_uuid32=");
         print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->svc_data_uuid128 != NULL) {
-        MODLOG_DFLT(DEBUG, "    svc_data_uuid128=");
+        MODLOG_DFLT(INFO, "    svc_data_uuid128=");
         print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->uri != NULL) {
-        MODLOG_DFLT(DEBUG, "    uri=");
+        MODLOG_DFLT(INFO, "    uri=");
         print_bytes(fields->uri, fields->uri_len);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 
     if (fields->mfg_data != NULL) {
-        MODLOG_DFLT(DEBUG, "    mfg_data=");
+        MODLOG_DFLT(INFO, "    mfg_data=");
         print_bytes(fields->mfg_data, fields->mfg_data_len);
-        MODLOG_DFLT(DEBUG, "\n");
+        MODLOG_DFLT(INFO, "\n");
     }
 }

+ 13 - 15
apps/blecsc/src/main.c → apps/blecsc/src/blecsc_sens.c

@@ -22,8 +22,8 @@
 #include <stdio.h>
 #include <errno.h>
 
-#include "os/mynewt.h"
-#include "console/console.h"
+#include <rtthread.h>
+
 #include "config/config.h"
 #include "nimble/ble.h"
 #include "host/ble_hs.h"
@@ -53,7 +53,7 @@ static uint8_t blecsc_addr_type;
 static const char *device_name = "blecsc_sensor";
 
 /* Measurement and notification timer */
-static struct os_callout blecsc_measure_timer;
+static struct ble_npl_callout blecsc_measure_timer;
 
 /* Variable holds current CSC measurement state */
 static struct ble_csc_measurement_state csc_measurement_state;
@@ -183,11 +183,11 @@ blecsc_simulate_speed_and_cadence()
 
 /* Run CSC measurement simulation and notify it to the client */
 static void
-blecsc_measurement(struct os_event *ev)
+blecsc_measurement(struct ble_npl_event *ev)
 {
     int rc;
 
-    rc = os_callout_reset(&blecsc_measure_timer, OS_TICKS_PER_SEC);
+    rc = ble_npl_callout_reset(&blecsc_measure_timer, RT_TICK_PER_SECOND);
     assert(rc == 0);
 
     blecsc_simulate_speed_and_cadence();
@@ -269,6 +269,7 @@ blecsc_on_sync(void)
     blecsc_advertise();
 }
 
+extern struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
 /*
  * main
  *
@@ -277,21 +278,18 @@ blecsc_on_sync(void)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(void)
+int blecsc_sens_entry(void)
 {
     int rc;
 
-    /* Initialize OS */
-    sysinit();
 
     /* Initialize the NimBLE host configuration */
     ble_hs_cfg.sync_cb = blecsc_on_sync;
 
     /* Initialize measurement and notification timer */
-    os_callout_init(&blecsc_measure_timer, os_eventq_dflt_get(),
+    ble_npl_callout_init(&blecsc_measure_timer, nimble_port_get_dflt_eventq(),
                     blecsc_measurement, NULL);
-    rc = os_callout_reset(&blecsc_measure_timer, OS_TICKS_PER_SEC);
+    rc = ble_npl_callout_reset(&blecsc_measure_timer, RT_TICK_PER_SECOND);
     assert(rc == 0);
 
     rc = gatt_svr_init(&csc_measurement_state);
@@ -301,10 +299,10 @@ main(void)
     rc = ble_svc_gap_device_name_set(device_name);
     assert(rc == 0);
 
-    /* As the last thing, process events from default event queue */
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
-    }
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
+
     return 0;
 }
 
+MSH_CMD_EXPORT_ALIAS(blecsc_sens_entry, blecsc_sens, "bluetooth cycle sensor sample");

+ 1 - 2
apps/blecsc/src/gatt_svr.c

@@ -20,7 +20,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
-#include "os/mynewt.h"
+#include <rtthread.h>
 #include "host/ble_hs.h"
 #include "host/ble_uuid.h"
 #include "blecsc_sens.h"
@@ -382,4 +382,3 @@ gatt_svr_init(struct ble_csc_measurement_state * csc_measurement_state)
 
     return 0;
 }
-

+ 4 - 3
apps/blehr/src/blehr.c

@@ -31,7 +31,7 @@
 static bool notify_state;
 static uint16_t notify_conn_handle;
 
-static const char *device_name = "rtt_blehr_sensor";
+static const char *device_name = "blehr_sensor";
 
 static int blehr_gap_event(struct ble_gap_event *event, void *arg);
 
@@ -238,8 +238,9 @@ static int ble_hr(void)
     rc = ble_svc_gap_device_name_set(device_name);
     RT_ASSERT(rc == 0);
 
-    nimble_ble_enable();
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
     
     return 0;
 }
-MSH_CMD_EXPORT_ALIAS(ble_hr, ble_hr, "bluetoooth peripheral heartrate");
+MSH_CMD_EXPORT_ALIAS(ble_hr, ble_hr, "bluetoooth heartrate senson sample");

+ 7 - 34
apps/bleprph/src/main.c → apps/bleprph/src/bleprph.c

@@ -21,13 +21,8 @@
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
-#include "hal/hal_gpio.h"
-#include "console/console.h"
-#include "hal/hal_system.h"
-#include "config/config.h"
-#include "split/split.h"
+
+#include <rtthread.h>
 
 /* BLE */
 #include "nimble/ble.h"
@@ -297,14 +292,10 @@ bleprph_on_sync(void)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(void)
+int bleprph_entry(void)
 {
     int rc;
 
-    /* Initialize OS */
-    sysinit();
-
     /* Initialize the NimBLE host configuration. */
     ble_hs_cfg.reset_cb = bleprph_on_reset;
     ble_hs_cfg.sync_cb = bleprph_on_sync;
@@ -322,26 +313,8 @@ main(void)
     phy_init();
 #endif
 
-    conf_load();
-
-    /* If this app is acting as the loader in a split image setup, jump into
-     * the second stage application instead of starting the OS.
-     */
-#if MYNEWT_VAL(SPLIT_LOADER)
-    {
-        void *entry;
-        rc = split_app_go(&entry, true);
-        if (rc == 0) {
-            hal_system_start(entry);
-        }
-    }
-#endif
-
-    /*
-     * As the last thing, process events from default event queue.
-     */
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
-    }
-    return 0;
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
 }
+
+MSH_CMD_EXPORT_ALIAS(bleprph_entry, bleprph, "bluetooth peripheral role sample");

+ 0 - 1
apps/bleprph/src/gatt_svr.c

@@ -20,7 +20,6 @@
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
-#include "bsp/bsp.h"
 #include "host/ble_hs.h"
 #include "host/ble_uuid.h"
 #include "bleprph.h"

+ 79 - 109
apps/bletest/src/main.c → apps/bletest/src/bletest.c

@@ -19,36 +19,24 @@
 
 #include <assert.h>
 #include <string.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
-#include "hal/hal_bsp.h"
-#include "hal/hal_gpio.h"
-#include "hal/hal_flash.h"
-#include "console/console.h"
-#include "shell/shell.h"
-#include "stats/stats.h"
-#include "flash_map/flash_map.h"
 
 /* BLE */
 #include "nimble/ble.h"
 #include "nimble/ble_hci_trans.h"
 #include "nimble/hci_common.h"
 #include "host/ble_hs.h"
-#include "controller/ble_ll.h"
-#include "controller/ble_ll_hci.h"
-#include "controller/ble_ll_conn.h"
-#include "controller/ble_ll_scan.h"
-#include "controller/ble_ll_adv.h"
 
-/* RAM HCI transport. */
-#include "transport/ram/ble_hci_ram.h"
+#include "nimble/nimble_npl.h"
+#include "nimble/npl_shell.h"
 
 /* XXX: An app should not include private headers from a library.  The bletest
  * app uses some of nimble's internal details for logging.
  */
-#include "../src/ble_hs_priv.h"
+#include "ble_hs_priv.h"
 #include "bletest_priv.h"
 
+#include <rtthread.h>
+
 #define BLETEST_TASK_PRIO               5
 
 /* For LED toggling */
@@ -57,6 +45,7 @@ int g_led_pin;
 /* A buffer for host advertising data */
 uint8_t g_host_adv_data[BLE_HCI_MAX_ADV_DATA_LEN];
 uint8_t g_host_adv_len;
+static uint8_t _g_dev_addr[BLE_DEV_ADDR_LEN];
 
 /* Some application configurations */
 #define BLETEST_ROLE_NONE               (0)
@@ -64,6 +53,8 @@ uint8_t g_host_adv_len;
 #define BLETEST_ROLE_SCANNER            (2)
 #define BLETEST_ROLE_INITIATOR          (3)
 
+#define MYNEWT_VAL_BLETEST_ROLE BLETEST_ROLE_ADVERTISER
+
 #if MYNEWT_VAL(BLETEST_ROLE) == BLETEST_ROLE_ADVERTISER
 #define BLETEST_CFG_ROLE                BLETEST_ROLE_ADVERTISER
 #endif
@@ -174,8 +165,7 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
 /* Test packet config */
 #define BLETEST_CFG_RAND_PKT_SIZE       (1)
 #define BLETEST_CFG_SUGG_DEF_TXOCTETS   (251)
-#define BLETEST_CFG_SUGG_DEF_TXTIME     \
-    ble_ll_pdu_tx_time_get(BLETEST_CFG_SUGG_DEF_TXOCTETS + 4, BLE_PHY_1M)
+#define BLETEST_CFG_SUGG_DEF_TXTIME     (2000)
 
 /* Test configurations. One of these should be set to 1 */
 #if !defined(BLETEST_CONCURRENT_CONN_TEST) && !defined(BLETEST_THROUGHPUT_TEST)
@@ -189,10 +179,10 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
 #define BLETEST_STACK_SIZE              (256)
 uint32_t g_next_os_time;
 int g_bletest_state;
-struct os_eventq g_bletest_evq;
-struct os_callout g_bletest_timer;
-struct os_task bletest_task;
-bssnz_t os_stack_t bletest_stack[BLETEST_STACK_SIZE];
+struct ble_npl_eventq g_bletest_evq;
+struct ble_npl_callout g_bletest_timer;
+//struct ble_npl_task bletest_task;
+//bssnz_t os_stack_t bletest_stack[BLETEST_STACK_SIZE];
 uint32_t g_bletest_conn_end;
 int g_bletest_start_update;
 uint32_t g_bletest_conn_upd_time;
@@ -381,9 +371,9 @@ bletest_init_adv_instances(void)
 
         adv.own_addr_type = bletest_multi_adv_instances[i-1].adv_own_addr_type;
         if (adv.own_addr_type == BLE_HCI_ADV_OWN_ADDR_PUBLIC) {
-            addr = g_dev_addr;
+            addr = _g_dev_addr;
         } else {
-            memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
+            memcpy(rand_addr, _g_dev_addr, BLE_DEV_ADDR_LEN);
             rand_addr[5] |= 0xc0;
             rand_addr[0] = i;
             /*
@@ -454,7 +444,7 @@ bletest_init_advertising(uint8_t instance, int8_t txpwr)
     /* If we are using a random address, we need to set it */
     adv.own_addr_type = BLETEST_CFG_ADV_OWN_ADDR_TYPE;
     if (adv.own_addr_type & 1) {
-        memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
+        memcpy(rand_addr, _g_dev_addr, BLE_DEV_ADDR_LEN);
         rand_addr[5] |= 0xc0;
         if (BLETEST_CFG_MULTI_ADV_RANDOM_OWN == 1) {
             addr = rand_addr;
@@ -465,7 +455,7 @@ bletest_init_advertising(uint8_t instance, int8_t txpwr)
             addr = rand_addr;
         }
     } else {
-        addr = g_dev_addr;
+        addr = _g_dev_addr;
     }
 
     /* Set advertising parameters */
@@ -544,13 +534,13 @@ bletest_init_advertising(void)
     /* If we are using a random address, we need to set it */
     adv.own_addr_type = BLETEST_CFG_ADV_OWN_ADDR_TYPE;
     if (adv.own_addr_type & 1) {
-        memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
+        memcpy(rand_addr, _g_dev_addr, BLE_DEV_ADDR_LEN);
         rand_addr[5] |= 0xc0;
         rc = bletest_hci_le_set_rand_addr(rand_addr);
         assert(rc == 0);
         addr = rand_addr;
     } else {
-        addr = g_dev_addr;
+        addr = _g_dev_addr;
     }
 
     /* Set advertising parameters */
@@ -629,7 +619,7 @@ bletest_init_scanner(void)
 {
     int rc;
     uint8_t own_addr_type;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
+    uint8_t buf[BLE_HCI_SET_SCAN_PARAM_LEN];
     uint8_t add_whitelist;
 
     own_addr_type = BLETEST_CFG_SCAN_OWN_ADDR_TYPE;
@@ -640,7 +630,10 @@ bletest_init_scanner(void)
                                                BLETEST_CFG_SCAN_FILT_POLICY,
                                                buf, sizeof buf);
     assert(rc == 0);
-    rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+    rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                                BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
+                                                buf, sizeof(buf));
+    assert(rc == 0);
     if (rc == 0) {
         add_whitelist = BLETEST_CFG_SCAN_FILT_POLICY;
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
@@ -669,7 +662,7 @@ bletest_execute_scanner(void)
     int rc;
 
     /* Enable scanning */
-    if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
+    if ((int32_t)(ble_npl_time_get() - g_next_os_time) >= 0) {
         if (g_bletest_state) {
             rc = bletest_hci_le_set_scan_enable(0, BLETEST_CFG_FILT_DUP_ADV);
             assert(rc == 0);
@@ -716,7 +709,7 @@ bletest_init_initiator(void)
 
     /* If we are using a random address, we need to set it */
     if (hcc->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-        memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
+        memcpy(rand_addr, _g_dev_addr, BLE_DEV_ADDR_LEN);
         rand_addr[5] |= 0xc0;
         rc = bletest_hci_le_set_rand_addr(rand_addr);
         assert(rc == 0);
@@ -754,7 +747,7 @@ bletest_execute_initiator(void)
      */
     if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
         handle = g_bletest_current_conns + 1;
-        if (ble_ll_conn_find_active_conn(handle)) {
+        if (ble_hs_conn_find(handle)) {
             /* Set LED to slower blink rate */
             g_bletest_led_rate = OS_TICKS_PER_SEC;
 
@@ -764,9 +757,6 @@ bletest_execute_initiator(void)
             /* Ask for remote used features */
             rc = bletest_hci_le_read_rem_used_feat(handle);
 
-            /* Scanning better be stopped! */
-            assert(ble_ll_scan_enabled() == 0);
-
             /* Add to current connections */
             if (!rc) {
                 ++g_bletest_current_conns;
@@ -775,20 +765,18 @@ bletest_execute_initiator(void)
                 if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
                     /* restart initiating */
                     g_bletest_cur_peer_addr[5] += 1;
-                    g_dev_addr[5] += 1;
+                    _g_dev_addr[5] += 1;
                     bletest_init_initiator();
                 }
             }
         } else {
-            if (ble_ll_scan_enabled() == 0) {
-                bletest_hci_le_create_connection(&g_cc);
-            }
+            bletest_hci_le_create_connection(&g_cc);
         }
     } else {
-        if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
+        if ((int32_t)(ble_npl_time_get() - g_next_os_time) >= 0) {
             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)) {
+                    if (ble_hs_conn_find(i + 1)) {
                         bletest_hci_le_rd_chanmap(i+1);
                     }
                 }
@@ -803,7 +791,7 @@ bletest_execute_initiator(void)
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
                 struct hci_start_encrypt hsle;
                 for (i = 0; i < g_bletest_current_conns; ++i) {
-                    if (ble_ll_conn_find_active_conn(i + 1)) {
+                    if (ble_hs_conn_find(i + 1)) {
                         hsle.connection_handle = i + 1;
                         hsle.encrypted_diversifier = g_bletest_EDIV;
                         hsle.random_number = g_bletest_RAND;
@@ -817,7 +805,7 @@ bletest_execute_initiator(void)
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
                 struct hci_start_encrypt hsle;
                 for (i = 0; i < g_bletest_current_conns; ++i) {
-                    if (ble_ll_conn_find_active_conn(i + 1)) {
+                    if (ble_hs_conn_find(i + 1)) {
                         hsle.connection_handle = i + 1;
                         hsle.encrypted_diversifier = g_bletest_EDIV;
                         hsle.random_number = ~g_bletest_RAND;
@@ -829,7 +817,7 @@ bletest_execute_initiator(void)
 #endif
             } else {
                 for (i = 0; i < g_bletest_current_conns; ++i) {
-                    if (ble_ll_conn_find_active_conn(i + 1)) {
+                    if (ble_hs_conn_find(i + 1)) {
                         ble_hs_hci_util_read_rssi(i+1, &rssi);
                     }
                 }
@@ -839,7 +827,7 @@ bletest_execute_initiator(void)
             if (g_bletest_state > 9) {
                 g_bletest_state = 9;
             }
-            g_next_os_time = os_time_get() + OS_TICKS_PER_SEC * 3;
+            g_next_os_time = ble_npl_time_get() + OS_TICKS_PER_SEC * 3;
         }
     }
 }
@@ -928,7 +916,7 @@ bletest_execute_advertiser(void)
     /* See if we should start advertising again */
     if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
         handle = g_bletest_current_conns + 1;
-        if (ble_ll_conn_find_active_conn(handle)) {
+        if (ble_hs_conn_find(handle)) {
             /* Set LED to slower blink rate */
             g_bletest_led_rate = OS_TICKS_PER_SEC;
 
@@ -939,10 +927,6 @@ bletest_execute_advertiser(void)
                 g_bletest_handle = handle;
             }
 #endif
-
-            /* advertising better be stopped! */
-            assert(ble_ll_adv_enabled() == 0);
-
             /* Send the remote used features command */
             rc = bletest_hci_le_read_rem_used_feat(handle);
             if (rc) {
@@ -956,7 +940,7 @@ bletest_execute_advertiser(void)
             }
 
             /* set conn update time */
-            g_bletest_conn_upd_time = os_time_get() + (OS_TICKS_PER_SEC * 5);
+            g_bletest_conn_upd_time = ble_npl_time_get() + (OS_TICKS_PER_SEC * 5);
             g_bletest_start_update = 1;
 
             /* Add to current connections */
@@ -966,7 +950,7 @@ bletest_execute_advertiser(void)
             if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
                 /* restart initiating */
                 g_bletest_cur_peer_addr[5] += 1;
-                g_dev_addr[5] += 1;
+                _g_dev_addr[5] += 1;
 #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
                 bletest_init_advertising(0,0);
                 bletest_hci_le_set_multi_adv_enable(1, 0);
@@ -977,13 +961,11 @@ bletest_execute_advertiser(void)
             }
         } else {
             /* If we failed to start advertising we should keep trying */
-            if (ble_ll_adv_enabled() == 0) {
 #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
-                bletest_hci_le_set_multi_adv_enable(1, 0);
+            bletest_hci_le_set_multi_adv_enable(1, 0);
 #else
-                bletest_hci_le_set_adv_enable(1);
+            bletest_hci_le_set_adv_enable(1);
 #endif
-            }
         }
     }
 #if 0
@@ -997,7 +979,7 @@ bletest_execute_advertiser(void)
 
 #if (BLETEST_CONCURRENT_CONN_TEST == 1)
     /* See if it is time to hand a data packet to the connection */
-    if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
+    if ((int32_t)(ble_npl_time_get() - g_next_os_time) >= 0) {
 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
         /* Do we need to send a LTK reply? */
         mask = 1;
@@ -1019,7 +1001,7 @@ bletest_execute_advertiser(void)
                     g_last_handle_used = 1;
                 }
                 handle = g_last_handle_used;
-                if (ble_ll_conn_find_active_conn(handle)) {
+                if (ble_hs_conn_find(handle)) {
                     om = bletest_send_packet(handle);
                     if (om) {
                         /* Increment last handle used */
@@ -1030,7 +1012,7 @@ bletest_execute_advertiser(void)
                 }
             }
         }
-        g_next_os_time = os_time_get() + OS_TICKS_PER_SEC;
+        g_next_os_time = ble_npl_time_get() + OS_TICKS_PER_SEC;
     }
 #endif
 
@@ -1070,9 +1052,9 @@ void
 bletest_execute(void)
 {
     /* Toggle LED at set rate */
-    if ((int32_t)(os_time_get() - g_bletest_next_led_time) >= 0) {
-        hal_gpio_toggle(LED_BLINK_PIN);
-        g_bletest_next_led_time = os_time_get() + g_bletest_led_rate;
+    if ((int32_t)(ble_npl_time_get() - g_bletest_next_led_time) >= 0) {
+        // hal_gpio_toggle(LED_BLINK_PIN);
+        g_bletest_next_led_time = ble_npl_time_get() + g_bletest_led_rate;
     }
 #if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
     bletest_execute_advertiser();
@@ -1091,13 +1073,13 @@ bletest_execute(void)
  * @param arg
  */
 void
-bletest_timer_cb(struct os_event *ev)
+bletest_timer_cb(struct ble_npl_event *ev)
 {
     /* Call the bletest code */
     bletest_execute();
 
     /* Re-start the timer (run every 10 msecs) */
-    os_callout_reset(&g_bletest_timer, OS_TICKS_PER_SEC / 100);
+    ble_npl_callout_reset(&g_bletest_timer, OS_TICKS_PER_SEC / 100);
 }
 
 /**
@@ -1116,10 +1098,10 @@ bletest_task_handler(void *arg)
     g_bletest_led_rate = OS_TICKS_PER_SEC / 20;
 
     /* Wait one second before starting test task */
-    os_time_delay(OS_TICKS_PER_SEC);
+    ble_npl_time_delay(OS_TICKS_PER_SEC);
 
     /* Initialize the host timer */
-    os_callout_init(&g_bletest_timer, &g_bletest_evq, bletest_timer_cb,
+    ble_npl_callout_init(&g_bletest_timer, &g_bletest_evq, bletest_timer_cb,
                     NULL);
 
     ble_hs_dbg_set_sync_state(BLE_HS_SYNC_STATE_GOOD);
@@ -1155,8 +1137,8 @@ bletest_task_handler(void *arg)
 #endif
 
     /* Read unique HW id */
-    rc = hal_bsp_hw_id((void *)&g_bletest_hw_id[0], sizeof(g_bletest_hw_id));
-    assert(rc == 16);
+    // rc = hal_bsp_hw_id((void *)&g_bletest_hw_id[0], sizeof(g_bletest_hw_id));
+    // assert(rc == 16);
     console_printf("HW id=%04x%04x%04x%04x\n",
                    (unsigned int)g_bletest_hw_id[0],
                    (unsigned int)g_bletest_hw_id[1],
@@ -1229,7 +1211,7 @@ bletest_task_handler(void *arg)
     assert(rc == 0);
 
     /* Wait some time before starting */
-    os_time_delay(OS_TICKS_PER_SEC);
+    ble_npl_time_delay(OS_TICKS_PER_SEC);
 
     /* Init state */
     g_bletest_state = 0;
@@ -1246,12 +1228,9 @@ bletest_task_handler(void *arg)
 #endif
 
     bletest_timer_cb(NULL);
-
-    while (1) {
-        os_eventq_run(&g_bletest_evq);
-    }
 }
 
+extern int nimble_ble_enable(void);
 /**
  * main
  *
@@ -1260,22 +1239,21 @@ bletest_task_handler(void *arg)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(void)
+static int bletest(void)
 {
-    int rc;
+    rt_thread_t tid;
 
-    /* Initialize OS */
-    sysinit();
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
 
     /* Dummy device address */
 #if BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER
-    g_dev_addr[0] = 0x00;
-    g_dev_addr[1] = 0x00;
-    g_dev_addr[2] = 0x00;
-    g_dev_addr[3] = 0x88;
-    g_dev_addr[4] = 0x88;
-    g_dev_addr[5] = 0x08;
+    _g_dev_addr[0] = 0x00;
+    _g_dev_addr[1] = 0x00;
+    _g_dev_addr[2] = 0x00;
+    _g_dev_addr[3] = 0x88;
+    _g_dev_addr[4] = 0x88;
+    _g_dev_addr[5] = 0x08;
 
     g_bletest_cur_peer_addr[0] = 0x00;
     g_bletest_cur_peer_addr[1] = 0x00;
@@ -1284,12 +1262,12 @@ main(void)
     g_bletest_cur_peer_addr[4] = 0x99;
     g_bletest_cur_peer_addr[5] = 0x09;
 #else
-    g_dev_addr[0] = 0x00;
-    g_dev_addr[1] = 0x00;
-    g_dev_addr[2] = 0x00;
-    g_dev_addr[3] = 0x99;
-    g_dev_addr[4] = 0x99;
-    g_dev_addr[5] = 0x09;
+    _g_dev_addr[0] = 0x00;
+    _g_dev_addr[1] = 0x00;
+    _g_dev_addr[2] = 0x00;
+    _g_dev_addr[3] = 0x99;
+    _g_dev_addr[4] = 0x99;
+    _g_dev_addr[5] = 0x09;
 
     g_bletest_cur_peer_addr[0] = 0x00;
     g_bletest_cur_peer_addr[1] = 0x00;
@@ -1300,24 +1278,16 @@ main(void)
 #endif
 
     /* Set the led pin as an output */
-    g_led_pin = LED_BLINK_PIN;
-    hal_gpio_init_out(g_led_pin, 1);
+    // g_led_pin = LED_BLINK_PIN;
+    // hal_gpio_init_out(g_led_pin, 1);
 
     /* Initialize eventq for bletest task */
-    os_eventq_init(&g_bletest_evq);
-
-    rc = os_task_init(&bletest_task, "bletest", bletest_task_handler, NULL,
-                      BLETEST_TASK_PRIO, OS_WAIT_FOREVER, bletest_stack,
-                      BLETEST_STACK_SIZE);
-    assert(rc == 0);
-
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
-    }
-    /* Never returns */
-
-    /* os start should never return. If it does, this should be an error */
-    assert(0);
+    ble_npl_eventq_init(&g_bletest_evq);
+    
+    tid = rt_thread_create("ble_test", bletest_task_handler, RT_NULL, 1024, 10, 10);
+    if(tid != RT_NULL)
+        rt_thread_startup(tid);
 
-    return rc;
+    return 0;
 }
+MSH_CMD_EXPORT_ALIAS(bletest, bletest, "bluetooth test sample");

+ 123 - 163
apps/bletest/src/bletest_hci.c

@@ -19,19 +19,12 @@
 
 #include <assert.h>
 #include <string.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
 
 /* BLE */
 #include "nimble/ble.h"
 #include "nimble/ble_hci_trans.h"
 #include "nimble/hci_common.h"
 #include "host/ble_hs.h"
-#include "controller/ble_ll.h"
-#include "controller/ble_ll_hci.h"
-#include "controller/ble_ll_conn.h"
-#include "controller/ble_ll_scan.h"
-#include "controller/ble_ll_adv.h"
 
 /* XXX: An app should not include private headers from a library.  The bletest
  * app uses some of nimble's internal details for logging.
@@ -70,18 +63,14 @@ int
 bletest_send_ltk_req_neg_reply(uint16_t handle)
 {
     int rc;
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + sizeof(uint16_t)];
+    uint8_t buf[sizeof(uint16_t)];
     uint16_t ack_conn_handle;
     uint8_t rsplen;
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY,
-                       sizeof(uint16_t), dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, handle);
-    rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, 2, &rsplen);
+    put_le16(buf, handle);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                      BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY),
+                           buf, sizeof(uint16_t), &ack_conn_handle, 2, &rsplen);
     if (rc == 0) {
         if (rsplen != 2) {
             rc = -1;
@@ -91,12 +80,13 @@ bletest_send_ltk_req_neg_reply(uint16_t handle)
     return rc;
 }
 
+extern const uint8_t g_bletest_LTK[];
 int
 bletest_send_ltk_req_reply(uint16_t handle)
 {
     struct hci_lt_key_req_reply hkr;
     uint16_t ack_conn_handle;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LT_KEY_REQ_REPLY_LEN];
+    uint8_t buf[BLE_HCI_LT_KEY_REQ_REPLY_LEN];
     uint8_t ack_params_len;
     int rc;
 
@@ -104,8 +94,10 @@ bletest_send_ltk_req_reply(uint16_t handle)
     swap_buf(hkr.long_term_key, (uint8_t *)g_bletest_LTK, 16);
 
     ble_hs_hci_cmd_build_le_lt_key_req_reply(&hkr, buf, sizeof buf);
-    rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
-                        &ack_params_len);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                      BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
+                           buf, sizeof(buf), &ack_conn_handle,
+                           sizeof(ack_conn_handle), &ack_params_len);
     if (rc != 0) {
         return rc;
     }
@@ -123,24 +115,21 @@ bletest_send_ltk_req_reply(uint16_t handle)
 int
 bletest_hci_reset_ctlr(void)
 {
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
-
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
-                             0, buf);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
+                                        BLE_HCI_OCF_CB_RESET),
+                             NULL, 0, NULL, 0, NULL);
 }
 
 int
 bletest_hci_rd_bd_addr(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_DEV_ADDR_LEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR, 0,
-                       buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_DEV_ADDR_LEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
+                                      BLE_HCI_OCF_IP_RD_BD_ADDR),
+                           NULL, 0, rspbuf, BLE_DEV_ADDR_LEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -157,19 +146,15 @@ int
 bletest_hci_le_encrypt(uint8_t *key, uint8_t *pt)
 {
     int rc;
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_ENCRYPT_LEN];
+    uint8_t buf[BLE_HCI_LE_ENCRYPT_LEN];
     uint8_t rspbuf[16];
     uint8_t rsplen;
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ENCRYPT,
-                       BLE_HCI_LE_ENCRYPT_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    swap_buf(dst, key, BLE_ENC_BLOCK_SIZE);
-    swap_buf(dst + BLE_ENC_BLOCK_SIZE, pt, BLE_ENC_BLOCK_SIZE);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, 16, &rsplen);
+    swap_buf(buf, key, BLE_ENC_BLOCK_SIZE);
+    swap_buf(buf + BLE_ENC_BLOCK_SIZE, pt, BLE_ENC_BLOCK_SIZE);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                      BLE_HCI_OCF_LE_ENCRYPT),
+                           buf, sizeof(buf), rspbuf, 16, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -185,20 +170,15 @@ int
 bletest_hci_le_set_datalen(uint16_t handle, uint16_t txoctets, uint16_t txtime)
 {
     int rc;
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_DATALEN_LEN];
+    uint8_t buf[BLE_HCI_SET_DATALEN_LEN];
     uint8_t rspbuf[2];
     uint8_t rsplen;
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DATA_LEN,
-                       BLE_HCI_SET_DATALEN_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, handle);
-    put_le16(dst + 2, txoctets);
-    put_le16(dst + 4, txtime);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, 2, &rsplen);
+    put_le16(buf, handle);
+    put_le16(buf + 2, txoctets);
+    put_le16(buf + 4, txtime);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DATA_LEN),
+                    buf, sizeof(buf), rspbuf, 2, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -213,31 +193,23 @@ bletest_hci_le_set_datalen(uint16_t handle, uint16_t txoctets, uint16_t txtime)
 int
 bletest_hci_le_write_sugg_datalen(uint16_t txoctets, uint16_t txtime)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_WR_SUGG_DATALEN_LEN];
+    uint8_t buf[BLE_HCI_WR_SUGG_DATALEN_LEN];
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN,
-                       BLE_HCI_WR_SUGG_DATALEN_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, txoctets);
-    put_le16(dst + 2, txtime);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    put_le16(buf, txoctets);
+    put_le16(buf + 2, txtime);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN),
+                            buf, sizeof(buf), NULL, 0, NULL);
 }
 
 int
 bletest_hci_le_rd_sugg_datalen(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_HCI_RD_SUGG_DATALEN_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN, 0,
-                       buf);
-
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_SUGG_DATALEN_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN),
+                            NULL, 0, rspbuf, BLE_HCI_RD_SUGG_DATALEN_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -253,13 +225,11 @@ int
 bletest_hci_rd_local_version(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_HCI_RD_LOC_VER_INFO_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER, 0,
-                       buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_VER_INFO_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER), 
+                            NULL, 0, rspbuf, BLE_HCI_RD_LOC_VER_INFO_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -274,13 +244,11 @@ int
 bletest_hci_rd_local_feat(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT,
-                       0, buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
+                        NULL, 0, rspbuf, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -295,13 +263,11 @@ int
 bletest_hci_rd_local_supp_cmd(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD,
-                       0, buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD),
+                            NULL, 0, rspbuf, BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -323,13 +289,12 @@ bletest_hci_rd_local_supp_cmd(void)
 int
 bletest_hci_le_read_supp_states(void)
 {
-    int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
+    int rc;;
     uint8_t rspbuf[BLE_HCI_RD_SUPP_STATES_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUPP_STATES, 0, buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_SUPP_STATES_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUPP_STATES),
+                            NULL, 0, rspbuf, BLE_HCI_RD_SUPP_STATES_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -344,12 +309,11 @@ int
 bletest_hci_le_rd_max_datalen(void)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN];
     uint8_t rspbuf[BLE_HCI_RD_MAX_DATALEN_RSPLEN];
     uint8_t rsplen;
 
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_MAX_DATA_LEN, 0, buf);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_MAX_DATALEN_RSPLEN, &rsplen);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_MAX_DATA_LEN),
+                            NULL, 0, rspbuf, BLE_HCI_RD_MAX_DATALEN_RSPLEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -393,11 +357,13 @@ int
 bletest_hci_le_set_adv_data(uint8_t *data, uint8_t len)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_DATA_LEN];
+    uint16_t opcode;
+    uint8_t buf[BLE_HCI_SET_ADV_DATA_LEN];
 
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA);
     rc = ble_hs_hci_cmd_build_le_set_adv_data(data, len, buf, sizeof buf);
     assert(rc == 0);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
+    return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
 }
 #endif
 
@@ -405,26 +371,25 @@ bletest_hci_le_set_adv_data(uint8_t *data, uint8_t len)
 int
 bletest_hci_le_start_encrypt(struct hci_start_encrypt *cmd)
 {
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_START_ENCRYPT_LEN];
+    int rc;
+    uint8_t buf[BLE_HCI_LE_START_ENCRYPT_LEN];
 
     ble_hs_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
+    rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                                BLE_HCI_OCF_LE_START_ENCRYPT),
+                                          buf, sizeof(buf));
+    return rc;
 }
 #endif
 
 int
 bletest_hci_le_read_rem_used_feat(uint16_t handle)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_RD_REM_FEAT_LEN];
+    uint8_t buf[BLE_HCI_CONN_RD_REM_FEAT_LEN];
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_REM_FEAT,
-                       BLE_HCI_CONN_RD_REM_FEAT_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, handle);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    put_le16(buf, handle);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_REM_FEAT),
+                            buf, sizeof(buf), NULL, 0, NULL);
 }
 
 #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
@@ -493,11 +458,13 @@ int
 bletest_hci_le_set_adv_params(struct hci_adv_params *adv)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN];
+    uint8_t buf[BLE_HCI_SET_ADV_PARAM_LEN];
 
     rc = ble_hs_hci_cmd_build_le_set_adv_params(adv, buf, sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                                    BLE_HCI_OCF_LE_SET_ADV_PARAMS),
+                                         buf, sizeof(buf));
     }
     return rc;
 }
@@ -506,16 +473,11 @@ bletest_hci_le_set_adv_params(struct hci_adv_params *adv)
 int
 bletest_hci_le_set_rand_addr(uint8_t *addr)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RAND_ADDR_LEN];
-
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RAND_ADDR,
-                       BLE_DEV_ADDR_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
+    uint8_t buf[BLE_HCI_SET_RAND_ADDR_LEN];
 
-    memcpy(dst, addr, BLE_DEV_ADDR_LEN);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    memcpy(buf, addr, BLE_DEV_ADDR_LEN);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RAND_ADDR),
+                                buf, sizeof(buf), NULL, 0, NULL);
 }
 
 #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
@@ -544,49 +506,34 @@ bletest_hci_le_set_multi_rand_addr(uint8_t *addr, uint8_t instance)
 int
 bletest_hci_rd_rem_version(uint16_t handle)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + sizeof(uint16_t)];
+    uint8_t buf[sizeof(uint16_t)];
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_RD_REM_VER_INFO,
-                       sizeof(uint16_t), dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, handle);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    put_le16(buf, handle);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_RD_REM_VER_INFO),
+                                buf, sizeof(buf), NULL, 0, NULL);
 }
 
 int
 bletest_hci_le_set_host_chan_class(uint8_t *chanmap)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
+    uint8_t buf[BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS,
-                       BLE_HCI_SET_HOST_CHAN_CLASS_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    memcpy(dst, chanmap, BLE_HCI_SET_HOST_CHAN_CLASS_LEN);
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    memcpy(buf, chanmap, BLE_HCI_SET_HOST_CHAN_CLASS_LEN);
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
+                                buf, sizeof(buf), NULL, 0, NULL);
 }
 
 int
 bletest_hci_le_rd_chanmap(uint16_t handle)
 {
     int rc;
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_RD_CHANMAP_LEN];
+    uint8_t buf[BLE_HCI_RD_CHANMAP_LEN];
     uint8_t rspbuf[BLE_HCI_RD_CHANMAP_RSP_LEN];
     uint8_t rsplen;
 
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_CHAN_MAP,
-                       BLE_HCI_RD_CHANMAP_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
-
-    put_le16(dst, handle);
-    rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_CHANMAP_RSP_LEN, &rsplen);
+    put_le16(buf, handle);
+    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_CHAN_MAP), 
+                        buf, sizeof(buf), rspbuf, BLE_HCI_RD_CHANMAP_RSP_LEN, &rsplen);
     if (rc != 0) {
         return rc;
     }
@@ -623,35 +570,34 @@ bletest_hci_le_set_multi_adv_enable(uint8_t enable, uint8_t instance)
 int
 bletest_hci_le_set_adv_enable(uint8_t enable)
 {
-    uint8_t *dst;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_ENABLE_LEN];
-
-    dst = buf;
-    ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE,
-                       BLE_HCI_SET_ADV_ENABLE_LEN, dst);
-    dst += BLE_HCI_CMD_HDR_LEN;
+    uint8_t buf[BLE_HCI_SET_ADV_ENABLE_LEN];
 
-    dst[0] = enable;
-    return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
+    buf[0] = enable;
+    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE),
+                            buf, sizeof(buf), NULL, 0, NULL);
 }
 #endif
 
 int
 bletest_hci_le_set_event_mask(uint64_t event_mask)
 {
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_LE_EVENT_MASK_LEN];
+    uint8_t buf[BLE_HCI_SET_LE_EVENT_MASK_LEN];
 
     ble_hs_hci_cmd_build_le_set_event_mask(event_mask, buf, sizeof buf);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
+    return ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                       BLE_HCI_OCF_LE_SET_EVENT_MASK),
+                                       buf, sizeof(buf));
 }
 
 int
 bletest_hci_set_event_mask(uint64_t event_mask)
 {
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_EVENT_MASK_LEN];
+    uint8_t buf[BLE_HCI_SET_EVENT_MASK_LEN];
 
     ble_hs_hci_cmd_build_set_event_mask(event_mask, buf, sizeof buf);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
+    return ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
+                                                  BLE_HCI_OCF_CB_SET_EVENT_MASK2),
+                                       buf, sizeof(buf));
 }
 
 #if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
@@ -687,11 +633,13 @@ int
 bletest_hci_le_set_scan_rsp_data(uint8_t *data, uint8_t len)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_RSP_DATA_LEN];
+    uint16_t opcode;
+    uint8_t buf[BLE_HCI_SET_SCAN_RSP_DATA_LEN];
 
+    opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA);
     rc = ble_hs_hci_cmd_build_le_set_scan_rsp_data(data, len, buf, sizeof buf);
     assert(rc == 0);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
+    return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf));
 }
 #endif
 
@@ -700,13 +648,14 @@ bletest_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 buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
+    uint8_t buf[BLE_HCI_SET_SCAN_PARAM_LEN];
 
     rc = ble_hs_hci_cmd_build_le_set_scan_params(scan_type, scan_itvl,
                                                scan_window, own_addr_type,
                                                filter_policy, buf, sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
+                                        buf, sizeof(buf));
     }
     return rc;
 }
@@ -715,12 +664,14 @@ int
 bletest_hci_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
+    uint8_t buf[BLE_HCI_ADD_WHITE_LIST_LEN];
 
     rc = ble_hs_hci_cmd_build_le_add_to_whitelist(addr, addr_type, buf,
                                                 sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                                    BLE_HCI_OCF_LE_ADD_WHITE_LIST),
+                                         buf, sizeof(buf));
     }
     return rc;
 }
@@ -728,21 +679,27 @@ bletest_hci_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type)
 int
 bletest_hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dups)
 {
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN];
+    uint8_t buf[BLE_HCI_SET_SCAN_ENABLE_LEN];
+
+    ble_hs_hci_cmd_build_le_set_scan_enable(!!enable, !!filter_dups,
+                                            buf, sizeof buf);
+    return ble_hs_hci_cmd_tx_empty_ack(
+            BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
+            buf, sizeof(buf));
 
-    ble_hs_hci_cmd_build_le_set_scan_enable(enable, filter_dups, buf, sizeof buf);
-    return ble_hs_hci_cmd_tx_empty_ack(buf);
 }
 
 int
 bletest_hci_le_create_connection(struct hci_create_conn *hcc)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CREATE_CONN_LEN];
+    uint8_t buf[BLE_HCI_CREATE_CONN_LEN];
 
     rc = ble_hs_hci_cmd_build_le_create_connection(hcc, buf, sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                                    BLE_HCI_OCF_LE_CREATE_CONN),
+                                         buf, sizeof(buf));
     }
     return rc;
 }
@@ -753,7 +710,7 @@ bletest_hci_le_add_resolv_list(uint8_t *local_irk, uint8_t *peer_irk,
 {
     int rc;
     struct hci_add_dev_to_resolving_list padd;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
+    uint8_t buf[BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
 
     padd.addr_type = addr_type;
     memcpy(padd.addr, peer_ident_addr, BLE_DEV_ADDR_LEN);
@@ -761,7 +718,9 @@ bletest_hci_le_add_resolv_list(uint8_t *local_irk, uint8_t *peer_irk,
     swap_buf(padd.peer_irk, peer_irk, 16);
     rc = ble_hs_hci_cmd_build_add_to_resolv_list(&padd, buf, sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                      BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
+                                      buf, sizeof(buf));
     }
     return rc;
 }
@@ -770,13 +729,14 @@ int
 bletest_hci_le_enable_resolv_list(uint8_t enable)
 {
     int rc;
-    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
+    uint8_t buf[BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
 
 
     rc = ble_hs_hci_cmd_build_set_addr_res_en(enable, buf, sizeof buf);
     if (!rc) {
-        rc = ble_hs_hci_cmd_tx_empty_ack(buf);
+        rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
+                                      BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
+                                      buf, sizeof(buf));
     }
     return rc;
 }
-

+ 41 - 0
apps/bleuart/pkg.yml

@@ -0,0 +1,41 @@
+# 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.
+#
+pkg.name: apps/bleuart
+pkg.type: app
+pkg.description: Simple BLE uart application.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/boot/bootutil"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-nimble/nimble/controller"
+    - "@apache-mynewt-nimble/nimble/host"
+    - "@apache-mynewt-nimble/nimble/host/services/gap"
+    - "@apache-mynewt-nimble/nimble/host/services/gatt"
+    - "@apache-mynewt-nimble/nimble/host/store/ram"
+    - "@apache-mynewt-nimble/nimble/transport/ram"
+    - "@apache-mynewt-core/sys/console/full"
+    - "@apache-mynewt-core/sys/log/full"
+    - "@apache-mynewt-core/sys/log/modlog"
+    - "@apache-mynewt-core/sys/stats/full"
+    - "@apache-mynewt-core/libc/baselibc"
+    - "@apache-mynewt-core/mgmt/newtmgr"
+    - "@apache-mynewt-core/mgmt/newtmgr/transport/ble"
+    - "@apache-mynewt-nimble/nimble/host/services/bleuart"

+ 227 - 0
apps/bleuart/src/bleuart.c

@@ -0,0 +1,227 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+/* BLE */
+#include "nimble/ble.h"
+#include "host/ble_hs.h"
+#include "host/ble_hs_adv.h"
+#include "host/ble_uuid.h"
+#include "host/ble_att.h"
+#include "host/ble_gap.h"
+#include "host/ble_gatt.h"
+#include "host/ble_l2cap.h"
+#include "host/ble_sm.h"
+
+/* bluetooth transport. */
+#include "nimble/ble_hci_trans.h"
+
+/* Mandatory services. */
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+
+/* Newtmgr include */
+#include "bleuart/bleuart.h"
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+static int bleuart_gap_event(struct ble_gap_event *event, void *arg);
+
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+bleuart_advertise(void)
+{
+    struct ble_gap_adv_params adv_params;
+    struct ble_hs_adv_fields fields;
+    int rc;
+
+    /*
+     *  Set the advertisement data included in our advertisements:
+     *     o Flags (indicates advertisement type and other general info).
+     *     o Advertising tx power.
+     *     o 128 bit UUID
+     */
+
+    memset(&fields, 0, sizeof fields);
+
+    /* Advertise two flags:
+     *     o Discoverability in forthcoming advertisement (general)
+     *     o BLE-only (BR/EDR unsupported).
+     */
+    fields.flags = BLE_HS_ADV_F_DISC_GEN |
+                   BLE_HS_ADV_F_BREDR_UNSUP;
+
+    /* Indicate that the TX power level field should be included; have the
+     * stack fill this value automatically.  This is done by assiging the
+     * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
+     */
+    fields.tx_pwr_lvl_is_present = 1;
+    fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+    fields.uuids128 = BLE_UUID128(&gatt_svr_svc_uart_uuid.u);
+    fields.num_uuids128 = 1;
+    fields.uuids128_is_complete = 1;
+
+    rc = ble_gap_adv_set_fields(&fields);
+    if (rc != 0) {
+        return;
+    }
+
+    memset(&fields, 0, sizeof fields);
+    fields.name = (uint8_t *)ble_svc_gap_device_name();
+    fields.name_len = strlen((char *)fields.name);
+    fields.name_is_complete = 1;
+
+    rc = ble_gap_adv_rsp_set_fields(&fields);
+    if (rc != 0) {
+        return;
+    }
+
+    /* Begin advertising. */
+    memset(&adv_params, 0, sizeof adv_params);
+    adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+    adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
+    rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER,
+                           &adv_params, bleuart_gap_event, NULL);
+    if (rc != 0) {
+        return;
+    }
+}
+
+/**
+ * The nimble host executes this callback when a GAP event occurs.  The
+ * application associates a GAP event callback with each connection that forms.
+ * bleuart uses the same callback for all connections.
+ *
+ * @param event                 The type of event being signalled.
+ * @param ctxt                  Various information pertaining to the event.
+ * @param arg                   Application-specified argument; unuesd by
+ *                                  bleuart.
+ *
+ * @return                      0 if the application successfully handled the
+ *                                  event; nonzero on failure.  The semantics
+ *                                  of the return code is specific to the
+ *                                  particular GAP event being signalled.
+ */
+static int
+bleuart_gap_event(struct ble_gap_event *event, void *arg)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    switch (event->type) {
+    case BLE_GAP_EVENT_CONNECT:
+        /* A new connection was established or a connection attempt failed. */
+        if (event->connect.status == 0) {
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            assert(rc == 0);
+            bleuart_set_conn_handle(event->connect.conn_handle);
+        }
+
+        if (event->connect.status != 0) {
+            /* Connection failed; resume advertising. */
+            bleuart_advertise();
+        }
+        return 0;
+
+    case BLE_GAP_EVENT_DISCONNECT:
+        /* Connection terminated; resume advertising. */
+        bleuart_advertise();
+        return 0;
+
+
+    case BLE_GAP_EVENT_ADV_COMPLETE:
+        /* Advertising terminated; resume advertising. */
+        bleuart_advertise();
+        return 0;
+
+    case BLE_GAP_EVENT_REPEAT_PAIRING:
+        /* We already have a bond with the peer, but it is attempting to
+         * establish a new secure link.  This app sacrifices security for
+         * convenience: just throw away the old bond and accept the new link.
+         */
+
+        /* Delete the old bond. */
+        rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
+        assert(rc == 0);
+        ble_store_util_delete_peer(&desc.peer_id_addr);
+
+        /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
+         * continue with the pairing operation.
+         */
+        return BLE_GAP_REPEAT_PAIRING_RETRY;
+    }
+
+    return 0;
+}
+
+static void
+bleuart_on_sync(void)
+{
+    /* Begin advertising. */
+    bleuart_advertise();
+}
+
+/**
+ * main
+ *
+ * The main task for the project. This function initializes the packages,
+ * then starts serving events from default event queue.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int bleuart_entry(void)
+{
+    int rc;
+    static int init_flag = 0;
+
+    if (init_flag == 0)
+    {
+        init_flag = 1;
+
+        /* Initialize the BLE host. */
+        ble_hs_cfg.sync_cb = bleuart_on_sync;
+        ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+        rc = bleuart_gatt_svr_init();
+        assert(rc == 0);
+
+        /* Set the default device name. */
+        rc = ble_svc_gap_device_name_set("Mynewt_BLEuart");
+        assert(rc == 0);
+
+        /* startup bluetooth host stack*/
+        ble_hs_thread_startup();
+    }
+
+    bleuart_init();
+
+    return 0;
+}
+
+MSH_CMD_EXPORT_ALIAS(bleuart_entry, bleuart, "bluetooth uart sample");

+ 25 - 0
apps/bleuart/syscfg.yml

@@ -0,0 +1,25 @@
+# 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.
+#
+
+syscfg.vals:
+    # Disable unused roles; bleuart is a peripheral-only app.
+    BLE_ROLE_OBSERVER: 0
+    BLE_ROLE_CENTRAL: 0
+
+    # Default task settings
+    OS_MAIN_STACK_SIZE: 336

+ 188 - 23
apps/btshell/src/main.c → apps/btshell/src/btshell.c

@@ -21,13 +21,8 @@
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
 #include "log/log.h"
 #include "stats/stats.h"
-#include "bsp/bsp.h"
-#include "hal/hal_gpio.h"
-#include "console/console.h"
 #include "btshell.h"
 #include "cmd.h"
 
@@ -55,6 +50,8 @@
 #include "../src/ble_hs_atomic_priv.h"
 #include "../src/ble_hs_hci_priv.h"
 
+#include "nimble/npl_shell.h"
+
 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
 #define BTSHELL_MAX_SVCS               32
 #define BTSHELL_MAX_CHRS               64
@@ -106,7 +103,7 @@ struct os_mbuf_pool sdu_os_mbuf_pool;
 static struct os_mempool sdu_coc_mbuf_mempool;
 #endif
 
-static struct os_callout btshell_tx_timer;
+static struct ble_npl_callout btshell_tx_timer;
 struct btshell_tx_data_s
 {
     uint16_t tx_num;
@@ -1227,7 +1224,7 @@ btshell_on_l2cap_update(uint16_t conn_handle, int status, void *arg)
 }
 
 static void
-btshell_tx_timer_cb(struct os_event *ev)
+btshell_tx_timer_cb(struct ble_npl_event *ev)
 {
     int i;
     uint8_t len;
@@ -1279,7 +1276,7 @@ btshell_tx_timer_cb(struct os_event *ev)
     if (btshell_tx_data.tx_num) {
         timeout = (int32_t)btshell_tx_data.tx_rate;
         timeout = (timeout * OS_TICKS_PER_SEC) / 1000;
-        os_callout_reset(&btshell_tx_timer, timeout);
+        ble_npl_callout_reset(&btshell_tx_timer, timeout);
     }
 }
 
@@ -1838,7 +1835,7 @@ btshell_tx_start(uint16_t handle, uint16_t len, uint16_t rate, uint16_t num)
     btshell_tx_data.tx_len = len;
     btshell_tx_data.tx_handle = handle;
 
-    os_callout_reset(&btshell_tx_timer, 0);
+    ble_npl_callout_reset(&btshell_tx_timer, 0);
 
     return 0;
 }
@@ -2164,6 +2161,8 @@ btshell_init_ext_adv_restart(void)
 #endif
 }
 
+extern int nimble_ble_enable(void);
+extern struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
 /**
  * main
  *
@@ -2172,18 +2171,10 @@ btshell_init_ext_adv_restart(void)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(int argc, char **argv)
+int btshell_init(void)
 {
     int rc;
 
-#ifdef ARCH_sim
-    mcu_sim_parse_args(argc, argv);
-#endif
-
-    /* Initialize OS */
-    sysinit();
-
     /* Initialize some application specific memory pools. */
     rc = os_mempool_init(&btshell_svc_pool, BTSHELL_MAX_SVCS,
                          sizeof (struct btshell_svc), btshell_svc_mem,
@@ -2236,16 +2227,190 @@ main(int argc, char **argv)
     /* Create a callout (timer).  This callout is used by the "tx" btshell
      * command to repeatedly send packets of sequential data bytes.
      */
-    os_callout_init(&btshell_tx_timer, os_eventq_dflt_get(),
+    ble_npl_callout_init(&btshell_tx_timer, nimble_port_get_dflt_eventq(),
                     btshell_tx_timer_cb, NULL);
 
     btshell_init_ext_adv_restart();
 
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
+
+    return 0;
+}
+
+/**
+ * Bluetooth shell porting on RT-Thread
+ */ 
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+
+#define BTSHELL_RX_FIFO_SIZE 256
+
+#define ESC_KEY                 0x1B
+#define BACKSPACE_KEY           0x08
+#define DELECT_KEY              0x7F
+
+struct shell_console
+{
+    struct rt_semaphore *rx_end;
+    struct rt_ringbuffer *rx_fifo;
+    rt_err_t (*old_rx_ind)(rt_device_t dev, rt_size_t size);
+};
+
+static struct shell_console btshell_console;
+
+static rt_err_t uart_console_rx_ind(rt_device_t dev, rt_size_t size)
+{
+    uint8_t ch;
+    rt_size_t i;
+
+    for (i = 0; i < size; i++)
+    {
+        /* read a char */
+        if (rt_device_read(dev, 0, &ch, 1))
+        {
+            rt_ringbuffer_put_force(btshell_console.rx_fifo, &ch, 1);
+            rt_sem_release(btshell_console.rx_end);
+        }
+    }
+
+    return RT_EOK;
+}
+
+static int rt_btshell_init(void)
+{
+    rt_base_t level;
+    rt_device_t uart_console;
+
+    /* create semaphore for the end of char recived */
+    btshell_console.rx_end = rt_sem_create("btshell", 0, RT_IPC_FLAG_FIFO);
+    if (btshell_console.rx_end == RT_NULL)
+    {
+        goto __exit;
+    }
+
+    /* create recived fifo */
+    btshell_console.rx_fifo = rt_ringbuffer_create(BTSHELL_RX_FIFO_SIZE);
+    if (btshell_console.rx_fifo == RT_NULL)
+    {
+        goto __exit;
+    }
+
+    level = rt_hw_interrupt_disable();
+    uart_console = rt_console_get_device();
+    if(uart_console)
+    {
+        /* back uart console old indicate callback */
+        btshell_console.old_rx_ind = uart_console->rx_indicate;
+        rt_device_set_rx_indicate(uart_console, uart_console_rx_ind);
+    }
+    rt_hw_interrupt_enable(level);
+
+    return RT_EOK;
+
+__exit:
+    if (btshell_console.rx_end != RT_NULL)
+    {
+        rt_sem_delete(btshell_console.rx_end);
+        btshell_console.rx_end = RT_NULL;
     }
-    /* os start should never return. If it does, this should be an error */
-    assert(0);
+
+    if (btshell_console.rx_fifo != RT_NULL)
+    {
+        rt_ringbuffer_destroy(btshell_console.rx_fifo);
+        btshell_console.rx_fifo = RT_NULL;
+    }
+
+    return -RT_ERROR;
+}
+
+static void rt_btshell_deinit(void)
+{
+    rt_base_t level;
+    rt_device_t uart_console;
+
+    level = rt_hw_interrupt_disable();
+    uart_console = rt_console_get_device();
+    if(uart_console)
+    {
+        rt_device_set_rx_indicate(uart_console, btshell_console.old_rx_ind);
+    }
+    rt_hw_interrupt_enable(level);
+
+    if (btshell_console.rx_end != RT_NULL)
+    {
+        rt_sem_delete(btshell_console.rx_end);
+        btshell_console.rx_end = RT_NULL;
+    }
+
+    if (btshell_console.rx_fifo != RT_NULL)
+    {
+        rt_ringbuffer_destroy(btshell_console.rx_fifo);
+        btshell_console.rx_fifo = RT_NULL;
+    }
+}
+
+static char uart_console_getchar(void)
+{
+    char ch;
+
+    rt_sem_take(btshell_console.rx_end, RT_WAITING_FOREVER);
+    rt_ringbuffer_getchar(btshell_console.rx_fifo, (rt_uint8_t *)&ch);
+
+    return ch;
+}
+
+static void rt_btshell_parser(void)
+{
+    char ch;
+    char cur_line[FINSH_CMD_SIZE] = { 0 };
+    rt_size_t cur_line_len = 0;
+
+    rt_kprintf("======== Welcome to enter bluetooth shell mode ========\n");
+    rt_kprintf("Press 'ESC' to exit.\n");
+    /* process user input */
+    while (ESC_KEY != (ch = uart_console_getchar()))
+    {
+        if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
+        {
+            if (cur_line_len)
+            {
+                cur_line[--cur_line_len] = 0;
+                rt_kprintf("\b \b");
+            }
+            continue;
+        }
+        else if (ch == '\r' || ch == '\n')
+        {
+            cur_line[cur_line_len++] = '\0';
+            rt_kprintf("\n");
+            shell_process_command(cur_line);
+            cur_line_len = 0;
+        }
+        else
+        {
+            rt_kprintf("%c", ch);
+            cur_line[cur_line_len++] = ch;
+        }
+    }
+    rt_kprintf("\n");
+}
+
+static int btshell_entry(int argc, char *argv[])
+{
+    static int btshell_init_flag = 0;
+
+    if (btshell_init_flag == 0)
+    {
+        btshell_init();
+        btshell_init_flag = 1;
+    }
+    rt_btshell_init();
+    rt_btshell_parser();
+    rt_btshell_deinit();
 
     return 0;
 }
+
+MSH_CMD_EXPORT_ALIAS(btshell_entry, btshell, "bluetooth shell mode");

+ 0 - 1
apps/btshell/src/btshell.h

@@ -21,7 +21,6 @@
 #define H_BTSHELL_PRIV_
 
 #include <inttypes.h>
-#include "os/mynewt.h"
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
 #include "modlog/modlog.h"

+ 3 - 6
apps/btshell/src/cmd.c

@@ -21,8 +21,6 @@
 #include <inttypes.h>
 #include <errno.h>
 #include <string.h>
-#include "os/mynewt.h"
-#include "bsp/bsp.h"
 
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
@@ -35,14 +33,13 @@
 #include "services/gatt/ble_svc_gatt.h"
 #include "../src/ble_hs_priv.h"
 
-#include "console/console.h"
-#include "shell/shell.h"
-
 #include "cmd.h"
 #include "btshell.h"
 #include "cmd_gatt.h"
 #include "cmd_l2cap.h"
 
+#include "nimble/npl_shell.h"
+
 #define BTSHELL_MODULE "btshell"
 
 int
@@ -3153,6 +3150,7 @@ static const struct shell_cmd_help phy_read_help = {
     .usage = NULL,
     .params = phy_read_params,
 };
+#endif
 
 /*****************************************************************************
  * $host-enable                                                              *
@@ -3411,7 +3409,6 @@ static const struct shell_cmd_help gatt_write_help = {
     .usage = NULL,
     .params = gatt_write_params,
 };
-#endif
 
 #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
 #if MYNEWT_VAL(SHELL_CMD_HELP)

+ 2 - 2
apps/btshell/src/cmd_gatt.c

@@ -20,15 +20,15 @@
 #include <inttypes.h>
 #include <errno.h>
 
-#include "bsp/bsp.h"
 #include "host/ble_hs_mbuf.h"
 #include "host/ble_gap.h"
 #include "services/gatt/ble_svc_gatt.h"
-#include "console/console.h"
 #include "btshell.h"
 #include "cmd.h"
 #include "cmd_gatt.h"
 
+#include "nimble/npl_shell.h"
+
 #define CMD_BUF_SZ      256
 static bssnz_t uint8_t cmd_buf[CMD_BUF_SZ];
 

+ 1 - 1
apps/btshell/src/cmd_l2cap.c

@@ -22,11 +22,11 @@
 
 #include "host/ble_gap.h"
 #include "host/ble_l2cap.h"
-#include "console/console.h"
 #include "btshell.h"
 #include "cmd.h"
 #include "cmd_l2cap.h"
 
+#include "nimble/npl_shell.h"
 
 /*****************************************************************************
  * $l2cap-update                                                             *

+ 2 - 2
apps/btshell/src/gatt_svr.c

@@ -19,13 +19,13 @@
 
 #include <assert.h>
 #include <string.h>
-#include "bsp/bsp.h"
-#include "console/console.h"
 #include "host/ble_hs.h"
 #include "host/ble_uuid.h"
 #include "host/ble_gatt.h"
 #include "btshell.h"
 
+#include "nimble/npl_shell.h"
+
 /* 0000xxxx-8c26-476f-89a7-a108033a69c7 */
 #define PTS_UUID_DECLARE(uuid16)                                \
     ((const ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT(   \

+ 2 - 1
apps/btshell/src/misc.c

@@ -17,12 +17,13 @@
  * under the License.
  */
 
-#include "console/console.h"
 #include "host/ble_uuid.h"
 #include "host/ble_gap.h"
 
 #include "btshell.h"
 
+#include "nimble/npl_shell.h"
+
 /**
  * Utility function to log an array of bytes.
  */

+ 2 - 1
apps/btshell/src/parse.c

@@ -23,13 +23,14 @@
 #include <stdarg.h>
 #include <errno.h>
 #include <assert.h>
-#include "console/console.h"
 #include "host/ble_hs.h"
 #include "host/ble_uuid.h"
 #include "host/ble_eddystone.h"
 #include "cmd.h"
 #include "btshell.h"
 
+#include "nimble/npl_shell.h"
+
 #define CMD_MAX_ARGS        16
 
 static char *cmd_args[CMD_MAX_ARGS][2];

+ 6 - 11
apps/ext_advertiser/src/main.c → apps/ext_advertiser/src/ext_advertiser.c

@@ -22,8 +22,7 @@
 #include <stdio.h>
 #include <errno.h>
 
-#include "os/mynewt.h"
-#include "console/console.h"
+#include "nimble/npl_shell.h"
 #include "config/config.h"
 #include "nimble/ble.h"
 #include "host/ble_hs.h"
@@ -445,20 +444,16 @@ on_sync(void)
  *
  * @return int NOTE: this function should never return!
  */
-int
-main(void)
+int ext_advertiser_entry(void)
 {
-    /* Initialize OS */
-    sysinit();
-
     console_printf("Extended Advertising sample application\n");
 
     /* Set sync callback */
     ble_hs_cfg.sync_cb = on_sync;
 
-    /* As the last thing, process events from default event queue */
-    while (1) {
-        os_eventq_run(os_eventq_dflt_get());
-    }
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
+
     return 0;
 }
+MSH_CMD_EXPORT_ALIAS(ext_advertiser_entry, ext_advertiser, "bluetooth external advertiser sample");

+ 3 - 5
apps/ibeacon/src/ibeacon.c

@@ -51,8 +51,6 @@ static void ble_app_on_sync(void)
     ble_app_advertise();
 }
 
-extern int nimble_ble_enable(void);
-
 static int ble_ibeacon(void)
 {
     static int init_flag = 0;
@@ -63,9 +61,9 @@ static int ble_ibeacon(void)
 
     ble_hs_cfg.sync_cb = ble_app_on_sync;
 
-    /* Enable bluetooth stack */
-    nimble_ble_enable();
+    /* startup bluetooth host stack*/
+    ble_hs_thread_startup();
 
     return 0;
 }
-MSH_CMD_EXPORT_ALIAS(ble_ibeacon, ble_ibeacon, "bluetoooth ibeacon");
+MSH_CMD_EXPORT_ALIAS(ble_ibeacon, ble_ibeacon, "bluetoooth ibeacon sample");

+ 1 - 1
nimble/host/services/bleuart/include/bleuart/bleuart.h

@@ -24,7 +24,7 @@
 extern "C" {
 #endif
 
-void
+int
 bleuart_init(void);
 int
 bleuart_svc_register(void);

+ 175 - 26
nimble/host/services/bleuart/src/bleuart.c → nimble/host/services/bleuart/src/ble_svc_uart.c

@@ -27,7 +27,25 @@
 #include "host/ble_uuid.h"
 #include "bleuart/bleuart.h"
 #include "os/endian.h"
-#include "console/console.h"
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+
+#define MYNEWT_VAL_BLEUART_MAX_INPUT 128
+
+#define ESC_KEY                      0x1B
+#define BACKSPACE_KEY                0x08
+#define DELECT_KEY                   0x7F
+
+static void bleuart_deinit(void);
+    
+struct bleuart_console
+{
+    struct rt_semaphore *rx_end;
+    struct rt_ringbuffer *rx_fifo;
+    rt_err_t (*old_rx_ind)(rt_device_t dev, rt_size_t size);
+};
 
 /* ble uart attr read handle */
 uint16_t g_bleuart_attr_read_handle;
@@ -38,6 +56,9 @@ uint16_t g_bleuart_attr_write_handle;
 /* Pointer to a console buffer */
 char *console_buf;
 
+/* ble uart console */
+static struct bleuart_console bleuart;
+
 uint16_t g_console_conn_handle;
 /**
  * The vendor specific "bleuart" service consists of one write no-rsp characteristic
@@ -102,10 +123,10 @@ gatt_svr_chr_access_uart_write(uint16_t conn_handle, uint16_t attr_handle,
     switch (ctxt->op) {
         case BLE_GATT_ACCESS_OP_WRITE_CHR:
               while(om) {
-                  console_write((char *)om->om_data, om->om_len);
+                  rt_device_write(rt_console_get_device(), 0, (char *)om->om_data, om->om_len);
                   om = SLIST_NEXT(om, om_next);
               }
-              console_write("\n", 1);
+              rt_device_write(rt_console_get_device(), 0, "\n", 1);
               return 0;
         default:
             assert(0);
@@ -138,29 +159,69 @@ err:
     return rc;
 }
 
+static rt_err_t bleuart_rx_ind(rt_device_t dev, rt_size_t size)
+{
+    uint8_t ch;
+    int i;
+
+    for(i = 0; i < size; i++)
+    {
+        /* read a char */
+        if (rt_device_read(dev, 0, &ch, 1))
+        {
+            rt_ringbuffer_put_force(bleuart.rx_fifo, &ch, 1);
+            rt_sem_release(bleuart.rx_end);
+        }
+    }
+
+    return RT_EOK;
+}
+
+static uint8_t bleuart_read(void)
+{
+    uint8_t ch;
+
+    rt_sem_take(bleuart.rx_end, RT_WAITING_FOREVER);
+    rt_ringbuffer_getchar(bleuart.rx_fifo, &ch);
+
+    return ch;
+}
+
 /**
  * Reads console and sends data over BLE
  */
-static void
-bleuart_uart_read(void)
+static void bleuart_uart_proc(void)
 {
-    int rc;
-    int off;
-    int full_line;
+    int off = 0;
+    char ch;
     struct os_mbuf *om;
 
-    off = 0;
-    while (1) {
-        rc = console_read(console_buf + off,
-                          MYNEWT_VAL(BLEUART_MAX_INPUT) - off, &full_line);
-        if (rc <= 0 && !full_line) {
-            continue;
-        }
-        off += rc;
-        if (!full_line) {
-            continue;
-        }
+    rt_kprintf("======== Welcome to enter bluetooth uart mode ========\n");
+    rt_kprintf("Press 'ESC' to exit.\n");
+
+    /* process user input */
+    while (ESC_KEY != (ch = bleuart_read()))
+    {
+        if(ch != '\r' && ch != '\n')
+        {
+            if(ch == BACKSPACE_KEY || ch == DELECT_KEY)
+            {
+                if(off)
+                {
+                    console_buf[off--] = 0;
+                    rt_kprintf("\b \b");
+                }
+            }
+            else
+            {
+                console_buf[off++] = ch;
+                rt_kprintf("%c", ch);
+                continue;
+            }
+        }    
 
+        console_buf[off] = '\0';
+        rt_kprintf("\n");
         om = ble_hs_mbuf_from_flat(console_buf, off);
         if (!om) {
             return;
@@ -168,8 +229,9 @@ bleuart_uart_read(void)
         ble_gattc_notify_custom(g_console_conn_handle,
                                 g_bleuart_attr_read_handle, om);
         off = 0;
-        break;
     }
+
+    bleuart_deinit();
 }
 
 /**
@@ -182,22 +244,109 @@ bleuart_set_conn_handle(uint16_t conn_handle) {
     g_console_conn_handle = conn_handle;
 }
 
+static void bleuart_deinit(void)
+{
+    rt_base_t level;
+    rt_device_t uart_console;
+
+    level = rt_hw_interrupt_disable();
+    uart_console = rt_console_get_device();
+    if(uart_console)
+    {
+        rt_device_set_rx_indicate(uart_console, bleuart.old_rx_ind);
+    }
+    rt_hw_interrupt_enable(level);
+
+    if (console_buf != RT_NULL)
+    {
+        rt_free(console_buf);
+        console_buf = RT_NULL;
+    }
+
+    if (bleuart.rx_end != RT_NULL)
+    {
+        rt_sem_delete(bleuart.rx_end);
+        bleuart.rx_end = RT_NULL;
+    }
+
+    if (bleuart.rx_fifo != RT_NULL)
+    {
+        rt_ringbuffer_destroy(bleuart.rx_fifo);
+        bleuart.rx_fifo = RT_NULL;
+    }
+}
+
 /**
  * BLEuart console initialization
  *
  * @param Maximum input
  */
-void
-bleuart_init(void)
+int bleuart_init(void)
 {
     int rc;
+    rt_base_t level;
+    rt_device_t uart_console;
 
     /* Ensure this function only gets called by sysinit. */
     SYSINIT_ASSERT_ACTIVE();
 
-    rc = console_init(bleuart_uart_read);
-    SYSINIT_PANIC_ASSERT(rc == 0);
+    /* create buffer for send */
+    console_buf = rt_malloc(MYNEWT_VAL(BLEUART_MAX_INPUT));
+    if (console_buf == RT_NULL)
+    {
+        rc = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    /* create semaphore for the end of char recived */
+    bleuart.rx_end = rt_sem_create("bleuart", 0, RT_IPC_FLAG_FIFO);
+    if (bleuart.rx_end == RT_NULL)
+    {
+        rc = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    /* create recived fifo */
+    bleuart.rx_fifo = rt_ringbuffer_create(MYNEWT_VAL(BLEUART_MAX_INPUT));
+    if (bleuart.rx_fifo == RT_NULL)
+    {
+        rc = -RT_ENOMEM;
+        goto __exit;
+    }
+
+    level = rt_hw_interrupt_disable();
+    uart_console = rt_console_get_device();
+    if(uart_console)
+    {
+        /* back uart console old indicate callback */
+        bleuart.old_rx_ind = uart_console->rx_indicate;
+        rt_device_set_rx_indicate(uart_console, bleuart_rx_ind);
+    }
+    rt_hw_interrupt_enable(level);
+
+    /* Reads console and sends data over BLE */
+    bleuart_uart_proc();
+
+    return RT_EOK;
+
+__exit:
+    if (console_buf != RT_NULL)
+    {
+        rt_free(console_buf);
+        console_buf = RT_NULL;
+    }
+
+    if (bleuart.rx_end != RT_NULL)
+    {
+        rt_sem_delete(bleuart.rx_end);
+        bleuart.rx_end = RT_NULL;
+    }
+
+    if (bleuart.rx_fifo != RT_NULL)
+    {
+        rt_ringbuffer_destroy(bleuart.rx_fifo);
+        bleuart.rx_fifo = RT_NULL;
+    }
 
-    console_buf = malloc(MYNEWT_VAL(BLEUART_MAX_INPUT));
-    SYSINIT_PANIC_ASSERT(console_buf != NULL);
+    return rc;
 }

+ 3 - 1
nimble/host/src/ble_gatts_lcl.c

@@ -20,10 +20,12 @@
 #include <stddef.h>
 #include <string.h>
 #include "host/ble_uuid.h"
-#include "console/console.h"
 #include "nimble/ble.h"
 #include "ble_hs_priv.h"
 
+#include <rtthread.h>
+
+#define console_printf rt_kprintf
 
 static const char * const ble_gatt_chr_f_names[] = {
     "BROADCAST",

+ 2 - 0
nimble/include/nimble/nimble_npl.h

@@ -165,6 +165,8 @@ uint32_t ble_npl_hw_enter_critical(void);
 
 void ble_npl_hw_exit_critical(uint32_t ctx);
 
+void ble_hs_thread_startup(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 4
porting/nimble/include/syscfg/syscfg.h

@@ -114,19 +114,19 @@
 #endif
 
 #ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER
-#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (0)
+#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL
-#define MYNEWT_VAL_BLE_ROLE_CENTRAL (0)
+#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER
-#define MYNEWT_VAL_BLE_ROLE_OBSERVER (0)
+#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL
-#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (0)
+#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1)
 #endif
 
 #ifndef MYNEWT_VAL_BLE_WHITELIST

+ 87 - 0
porting/npl/rtthread/include/nimble/npl_shell.h

@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Date           Author       Notes
+ * 2019-02-14     ZeroFree     first implementation
+ */
+
+#ifndef __NPL_SHELL_H__
+#define __NPL_SHELL_H__
+
+#include <rtthread.h>
+
+/** @brief Callback called when command is entered.
+ *
+ *  @param argc Number of parameters passed.
+ *  @param argv Array of option strings. First option is always command name.
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+typedef int (*shell_cmd_func_t)(int argc, char *argv[]);
+
+struct shell_param
+{
+    const char *param_name;
+    const char *help;
+};
+
+struct shell_cmd_help
+{
+    const char *summary;
+    const char *usage;
+    const struct shell_param *params;
+};
+
+struct shell_cmd
+{
+    const char *sc_cmd;
+    shell_cmd_func_t sc_cmd_func;
+    const struct shell_cmd_help *help;
+};
+
+struct shell_module
+{
+    const char *name;
+    const struct shell_cmd *commands;
+};
+
+/** @brief Register a shell_module object
+ *
+ *  @param shell_name Module name to be entered in shell console.
+ *
+ *  @param shell_commands Array of commands to register.
+ *  The array should be terminated with an empty element.
+ */
+int shell_register(const char *shell_name,
+                   const struct shell_cmd *shell_commands);
+
+/** @brief Optionally register a default module, to avoid typing it in
+ *  shell console.
+ *
+ *  @param name Module name.
+ */
+void shell_register_default_module(const char *name);
+
+/** @brief Callback to get the current prompt.
+ *
+ *  @returns Current prompt string.
+ */
+typedef const char *(*shell_prompt_function_t)(void);
+
+void shell_process_command(char *line);
+
+#define console_printf rt_kprintf
+
+#define OS_TICKS_PER_SEC RT_TICK_PER_SECOND
+
+#define MYNEWT_VAL_SHELL_CMD_HELP 1
+
+#if MYNEWT
+#include "bsp/bsp.h"
+#else
+#define bssnz_t
+#endif
+
+void console_write(const char *str, int cnt);
+
+#endif

+ 8 - 21
porting/npl/rtthread/src/nimble_port_rtthread.c

@@ -12,7 +12,7 @@
 #include "syscfg/syscfg.h"
 #include "nimble/nimble_port.h"
 
-#define NIMBLE_THRAED_STACK_SIZE (1024 * 2)
+#define NIMBLE_THRAED_STACK_SIZE (1024)
 #define NIMBLE_THREAD_PRIORITY (10)
 
 #if NIMBLE_CFG_CONTROLLER
@@ -21,7 +21,6 @@ static rt_thread_t ll_task_h;
 static rt_thread_t host_task_h;
 
 extern void ble_ll_task(void *arg);
-extern void nimble_port_run(void);
 
 RT_WEAK void __aeabi_assert(const char *expr, const char *file, int line)
 {
@@ -30,8 +29,6 @@ RT_WEAK void __aeabi_assert(const char *expr, const char *file, int line)
 
 int nimble_port_rtthread_init(void)
 {
-    // TODO:
-    // ble_hci_sock_init();
     nimble_port_init();
 
 #if NIMBLE_CFG_CONTROLLER
@@ -41,33 +38,23 @@ int nimble_port_rtthread_init(void)
      * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped
      * since it has compatible prototype.
      */
-    ll_task_h = rt_thread_create("ll", ble_ll_task, NULL, NIMBLE_THRAED_STACK_SIZE, NIMBLE_THREAD_PRIORITY - 1, 10);
+    ll_task_h = rt_thread_create("ll", ble_ll_task, NULL, NIMBLE_THRAED_STACK_SIZE + 256, NIMBLE_THREAD_PRIORITY - 1, 10);
     if (ll_task_h != RT_NULL)
         rt_thread_startup(ll_task_h);
 
 #endif
+}
 
-
-    /* XXX Need to have template for store */
-    // ble_store_ram_init();
-
-    /*
-     * Create task where NimBLE host will run. It is not strictly necessary to
-     * have separate task for NimBLE host, but since something needs to handle
-     * default queue it is just easier to make separate task which does this.
-     */
-    // host_task_h = rt_thread_create("ble", nimble_port_run, NULL, NIMBLE_THRAED_STACK_SIZE, NIMBLE_THREAD_PRIORITY + 1, 10);
-    // if(host_task_h != RT_NULL)
-    //     rt_thread_startup(host_task_h);
-
-    // return 0;
+void ble_hs_thread_entry(void *parameter)
+{
+    nimble_port_run();
 }
 
-int nimble_ble_enable(void)
+void ble_hs_thread_startup(void)
 {
     rt_thread_t tid;
 
-    tid = rt_thread_create("ble", nimble_port_run, NULL, NIMBLE_THRAED_STACK_SIZE, NIMBLE_THREAD_PRIORITY + 1, 10);
+    tid = rt_thread_create("host", ble_hs_thread_entry, NULL, NIMBLE_THRAED_STACK_SIZE, NIMBLE_THREAD_PRIORITY + 1, 10);
     if (tid != RT_NULL)
         rt_thread_startup(tid);
 

+ 0 - 3
porting/npl/rtthread/src/npl_os_rtthread.c

@@ -18,9 +18,6 @@ static ble_npl_error_t npl_rtthread_callout_reset(struct ble_npl_callout *co, bl
 static ble_npl_time_t npl_rtthread_callout_remaining_ticks(struct ble_npl_callout *co, ble_npl_time_t now);
 static ble_npl_error_t npl_rtthread_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks);
 static ble_npl_error_t npl_rtthread_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms);
-static void npl_rtthread_hw_set_isr(int irqn, void (*addr)(void));
-static uint32_t npl_rtthread_hw_enter_critical(void);
-static void npl_rtthread_hw_exit_critical(uint32_t ctx);
 
 void *ble_npl_get_current_task_id(void)
 {

+ 469 - 0
porting/npl/rtthread/src/npl_shell.c

@@ -0,0 +1,469 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Date           Author       Notes
+ * 2019-02-14     ZeroFree     first implementation
+ */
+
+#include <string.h>
+#include "nimble/nimble_npl.h"
+#include "nimble/npl_shell.h"
+
+#include <rtthread.h>
+
+#define SHELL_PROMPT "shell"
+#define SHELL_MAX_MODULES 3
+#define SHELL_PROMPT_SUFFIX "> "
+
+static const char *get_command_and_module(char *argv[], int *module);
+static int set_default_module(const char *name);
+static void print_prompt(void);
+static int get_destination_module(const char *module_str, int len);
+static int show_cmd_help(char *argv[]);
+
+static struct shell_module shell_modules[SHELL_MAX_MODULES];
+static size_t num_of_shell_entities;
+
+static const char *prompt;
+static int default_module = -1;
+
+static shell_cmd_func_t app_cmd_handler;
+static shell_prompt_function_t app_prompt_handler;
+
+void console_write(const char *str, int cnt)
+{
+    rt_device_write(rt_console_get_device(), 0, str, cnt);
+}
+
+int shell_register(const char *module_name, const struct shell_cmd *commands)
+{
+    if (num_of_shell_entities >= SHELL_MAX_MODULES)
+    {
+        console_printf("Max number of modules reached\n");
+        return -1;
+    }
+
+    shell_modules[num_of_shell_entities].name = module_name;
+    shell_modules[num_of_shell_entities].commands = commands;
+    ++num_of_shell_entities;
+
+    return 0;
+}
+
+void shell_register_default_module(const char *name)
+{
+    int result = set_default_module(name);
+
+    if (result != -1)
+    {
+        console_printf("\n");
+        print_prompt();
+    }
+}
+
+static void print_modules(void)
+{
+    int module;
+
+    for (module = 0; module < num_of_shell_entities; module++)
+    {
+        console_printf("%s\n", shell_modules[module].name);
+    }
+}
+
+static void print_module_commands(const int module)
+{
+    const struct shell_module *shell_module = &shell_modules[module];
+    int i;
+
+    console_printf("help\n");
+
+    for (i = 0; shell_module->commands[i].sc_cmd; i++)
+    {
+        console_printf("%-30s", shell_module->commands[i].sc_cmd);
+        if (shell_module->commands[i].help &&
+                shell_module->commands[i].help->summary)
+        {
+            console_printf("%s", shell_module->commands[i].help->summary);
+        }
+        console_printf("\n");
+    }
+}
+
+static int show_help(int argc, char *argv[])
+{
+    int module;
+
+    /* help per command */
+    if ((argc > 2) || ((default_module != -1) && (argc == 2)))
+    {
+        return show_cmd_help(&argv[1]);
+    }
+
+    /* help per module */
+    if ((argc == 2) || ((default_module != -1) && (argc == 1)))
+    {
+        if (default_module == -1)
+        {
+            module = get_destination_module(argv[1], -1);
+            if (module == -1)
+            {
+                console_printf("Illegal module %s\n", argv[1]);
+                return 0;
+            }
+        }
+        else
+        {
+            module = default_module;
+        }
+
+        print_module_commands(module);
+    }
+    else     /* help for all entities */
+    {
+        console_printf("Available modules:\n");
+        print_modules();
+        console_printf("To select a module, enter 'select <module name>'.\n");
+    }
+
+    return 0;
+}
+
+static int set_default_module(const char *name)
+{
+    int module;
+
+    module = get_destination_module(name, -1);
+
+    if (module == -1)
+    {
+        console_printf("Illegal module %s, default is not changed\n", name);
+        return -1;
+    }
+
+    default_module = module;
+
+    return 0;
+}
+
+static int select_module(int argc, char *argv[])
+{
+    if (argc == 1)
+    {
+        default_module = -1;
+    }
+    else
+    {
+        set_default_module(argv[1]);
+    }
+
+    return 0;
+}
+
+static size_t line2argv(char *str, char *argv[], size_t size)
+{
+    size_t argc = 0;
+
+    if (!strlen(str))
+    {
+        return 0;
+    }
+
+    while (*str && *str == ' ')
+    {
+        str++;
+    }
+
+    if (!*str)
+    {
+        return 0;
+    }
+
+    argv[argc++] = str;
+
+    while ((str = strchr(str, ' ')))
+    {
+        *str++ = '\0';
+
+        while (*str && *str == ' ')
+        {
+            str++;
+        }
+
+        if (!*str)
+        {
+            break;
+        }
+
+        argv[argc++] = str;
+
+        if (argc == size)
+        {
+            console_printf("Too many parameters (max %zu)\n", size - 1);
+            return 0;
+        }
+    }
+
+    /* keep it POSIX style where argv[argc] is required to be NULL */
+    argv[argc] = NULL;
+
+    return argc;
+}
+
+static shell_cmd_func_t get_cb(int argc, char *argv[])
+{
+    const char *first_string = argv[0];
+    int module = -1;
+    const struct shell_module *shell_module;
+    const char *command;
+    int i;
+
+    if (!first_string || first_string[0] == '\0')
+    {
+        console_printf("Illegal parameter\n");
+        return NULL;
+    }
+
+    if (!strcmp(first_string, "help"))
+    {
+        return show_help;
+    }
+
+    if (!strcmp(first_string, "select"))
+    {
+        return select_module;
+    }
+
+    if ((argc == 1) && (default_module == -1))
+    {
+        console_printf("Missing parameter\n");
+        return NULL;
+    }
+
+    command = get_command_and_module(argv, &module);
+    if ((module == -1) || (command == NULL))
+    {
+        return NULL;
+    }
+
+    shell_module = &shell_modules[module];
+    for (i = 0; shell_module->commands[i].sc_cmd; i++)
+    {
+        if (!strcmp(command, shell_module->commands[i].sc_cmd))
+        {
+            return shell_module->commands[i].sc_cmd_func;
+        }
+    }
+
+    return NULL;
+}
+
+
+static const char *get_prompt(void)
+{
+    const char *str;
+
+    if (app_prompt_handler)
+    {
+
+        str = app_prompt_handler();
+        if (str)
+        {
+            return str;
+        }
+    }
+
+    if (default_module != -1)
+    {
+        return shell_modules[default_module].name;
+    }
+
+    return prompt;
+}
+
+static void print_prompt(void)
+{
+    console_printf("%s%s", get_prompt(), SHELL_PROMPT_SUFFIX);
+}
+
+static int get_destination_module(const char *module_str, int len)
+{
+    int i;
+
+    for (i = 0; i < num_of_shell_entities; i++)
+    {
+        if (len < 0)
+        {
+            if (!strcmp(module_str, shell_modules[i].name))
+            {
+                return i;
+            }
+        }
+        else
+        {
+            if (!strncmp(module_str, shell_modules[i].name, len))
+            {
+                return i;
+            }
+        }
+    }
+
+    return -1;
+}
+
+/* For a specific command: argv[0] = module name, argv[1] = command name
+ * If a default module was selected: argv[0] = command name
+ */
+static const char *get_command_and_module(char *argv[], int *module)
+{
+    *module = -1;
+
+    if (!argv[0])
+    {
+        console_printf("Unrecognized command\n");
+        return NULL;
+    }
+
+    if (default_module == -1)
+    {
+        if (!argv[1] || argv[1][0] == '\0')
+        {
+            console_printf("Unrecognized command: %s\n", argv[0]);
+            return NULL;
+        }
+
+        *module = get_destination_module(argv[0], -1);
+        if (*module == -1)
+        {
+            console_printf("Illegal module %s\n", argv[0]);
+            return NULL;
+        }
+
+        return argv[1];
+    }
+
+    *module = default_module;
+    return argv[0];
+}
+
+static void print_command_params(const int module, const int command)
+{
+    const struct shell_module *shell_module = &shell_modules[module];
+    const struct shell_cmd *shell_cmd = &shell_module->commands[command];
+    int i;
+
+    if (!(shell_cmd->help && shell_cmd->help->params))
+    {
+        return;
+    }
+
+    for (i = 0; shell_cmd->help->params[i].param_name; i++)
+    {
+        console_printf("%-30s%s\n", shell_cmd->help->params[i].param_name,
+                       shell_cmd->help->params[i].help);
+    }
+}
+
+static int show_cmd_help(char *argv[])
+{
+    const char *command = NULL;
+    int module = -1;
+    const struct shell_module *shell_module = NULL;
+    const struct shell_cmd *cmd;
+    int i;
+
+    command = get_command_and_module(argv, &module);
+    if ((module == -1) || (command == NULL))
+    {
+        return 0;
+    }
+
+    shell_module = &shell_modules[module];
+    for (i = 0; shell_module->commands[i].sc_cmd; i++)
+    {
+        cmd = &shell_module->commands[i];
+
+        if (!strcmp(command, cmd->sc_cmd))
+        {
+
+            if (!cmd->help || (!cmd->help->summary &&
+                               !cmd->help->usage &&
+                               !cmd->help->params))
+            {
+                console_printf("(no help available)\n");
+                return 0;
+            }
+
+            if (cmd->help->summary)
+            {
+                console_printf("Summary:\n");
+                console_printf("%s\n", cmd->help->summary);
+            }
+
+            if (cmd->help->usage)
+            {
+                console_printf("Usage:\n");
+                console_printf("%s\n", cmd->help->usage);
+            }
+
+            if (cmd->help->params)
+            {
+                console_printf("Parameters:\n");
+                print_command_params(module, i);
+            }
+
+            return 0;
+        }
+    }
+
+    console_printf("Unrecognized command: %s\n", argv[0]);
+    return 0;
+}
+
+void shell_process_command(char *line)
+{
+    char *argv[FINSH_CMD_SIZE + 1];
+    shell_cmd_func_t sc_cmd_func;
+    size_t argc_offset = 0;
+    size_t argc;
+
+    argc = line2argv(line, argv, FINSH_CMD_SIZE + 1);
+    if (!argc)
+    {
+        print_prompt();
+        return;
+    }
+
+    sc_cmd_func = get_cb(argc, argv);
+    if (!sc_cmd_func)
+    {
+        if (app_cmd_handler != NULL)
+        {
+            sc_cmd_func = app_cmd_handler;
+        }
+        else
+        {
+            console_printf("Unrecognized command: %s\n", argv[0]);
+            console_printf("Type 'help' for list of available commands\n");
+            print_prompt();
+            return;
+        }
+    }
+
+    /* Allow invoking a cmd with module name as a prefix; a command should
+     * not know how it was invoked (with or without prefix)
+     */
+    if (default_module == -1 && sc_cmd_func != select_module &&
+            sc_cmd_func != show_help)
+    {
+        argc_offset = 1;
+    }
+
+    /* Execute callback with arguments */
+    if (sc_cmd_func(argc - argc_offset, &argv[argc_offset]) < 0)
+    {
+        show_cmd_help(argv);
+    }
+
+    print_prompt();
+}