Ver código fonte

add: 添加通用的nimble库,仅依赖nimble库, 平台差异在各bsp中实现

Wendal Chen 3 anos atrás
pai
commit
a6d67e6da5

+ 34 - 0
components/nimble/inc/luat_nimble.h

@@ -0,0 +1,34 @@
+
+#ifndef LUAT_NUMBLE_H
+#define LUAT_NUMBLE_H
+#include "luat_base.h"
+#include "luat_msgbus.h"
+
+
+/** Bluetooth Adapter State */
+typedef enum
+{
+    BT_STATE_OFF,
+    BT_STATE_ON,
+    BT_STATE_CONNECTED,
+    BT_STATE_DISCONNECT,
+} bt_state_t;
+
+
+typedef enum
+{
+    BT_MODE_BLE_SERVER,
+    BT_MODE_BLE_CLIENT,
+    BT_MODE_BLE_BEACON,
+    BT_MODE_BLE_MESH,
+} bt_mode_t;
+
+int luat_nimble_trace_level(int level);
+
+int luat_nimble_init(uint8_t uart_idx, char* name, int mode);
+int luat_nimble_deinit();
+
+int luat_nimble_server_send(int id, char* data, size_t len);
+
+#endif
+

+ 120 - 0
components/nimble/src/luat_lib_nimble.c

@@ -0,0 +1,120 @@
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "luat_malloc.h"
+#include "luat_spi.h"
+
+#include "luat_nimble.h"
+
+#define LUAT_LOG_TAG "nimble"
+#include "luat_log.h"
+
+static uint32_t nimble_mode = 0;
+
+static int l_nimble_init(lua_State* L) {
+    int rc = 0;
+    size_t len = 0;
+    const char* name = NULL;
+    if(lua_isstring(L, 1)) {
+        name = luaL_checklstring(L, 1, &len);
+    }
+    LLOGD("init name %s mode %d", name, nimble_mode);
+    rc = luat_nimble_init(0xFF, name, nimble_mode);
+    if (rc) {
+        lua_pushboolean(L, 0);
+        lua_pushinteger(L, rc);
+        return 2;
+    }
+    else {
+        lua_pushboolean(L, 1);
+        return 1;
+    }
+}
+
+static int l_nimble_deinit(lua_State* L) {
+    int rc = 0;
+    rc = luat_nimble_deinit();
+    if (rc) {
+        lua_pushboolean(L, 0);
+        lua_pushinteger(L, rc);
+        return 2;
+    }
+    else {
+        lua_pushboolean(L, 1);
+        return 1;
+    }
+}
+
+static int l_nimble_debug(lua_State* L) {
+    int level = 0;
+    // if (lua_gettop(L) > 0)
+    //     level = luat_nimble_trace_level(luaL_checkinteger(L, 1));
+    // else
+    //     level = luat_nimble_trace_level(-1);
+    lua_pushinteger(L, level);
+    return 1;
+}
+
+static int l_nimble_server_init(lua_State* L) {
+    LLOGI("nimble.server_init is removed");
+    return 0;
+}
+
+
+static int l_nimble_server_deinit(lua_State* L) {
+    LLOGI("nimble.server_deinit is removed");
+    return 0;
+}
+
+
+static int l_nimble_send_msg(lua_State *L) {
+    int conn_id = luaL_checkinteger(L, 1);
+    int handle_id = luaL_checkinteger(L, 2);
+    size_t len = 0;
+    const char* data = luaL_checklstring(L, 3, &len);
+    int ret = 0;
+    if (len == 0) {
+        LLOGI("send emtry msg? ignored");
+    }
+    else {
+        ret = luat_nimble_server_send(0, data, len);
+    }
+
+    lua_pushboolean(L, ret == 0 ? 1 : 0);
+    lua_pushinteger(L, ret);
+    return 2;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_nimble[] =
+{
+	{ "init",           ROREG_FUNC(l_nimble_init)},
+    { "deinit",         ROREG_FUNC(l_nimble_deinit)},
+    { "debug",          ROREG_FUNC(l_nimble_debug)},
+    { "server_init",    ROREG_FUNC(l_nimble_server_init)},
+    { "server_deinit",  ROREG_FUNC(l_nimble_server_deinit)},
+    { "send_msg",       ROREG_FUNC(l_nimble_send_msg)},
+
+    // 放一些常量
+    { "STATE_OFF",           ROREG_INT(BT_STATE_OFF)},
+    { "STATE_ON",            ROREG_INT(BT_STATE_ON)},
+    { "STATE_CONNECTED",     ROREG_INT(BT_STATE_CONNECTED)},
+    { "STATE_DISCONNECT",    ROREG_INT(BT_STATE_DISCONNECT)},
+
+    // 模式
+    { "MODE_BLE_SERVER",           ROREG_INT(BT_MODE_BLE_SERVER)},
+    { "MODE_BLE_CLIENT",           ROREG_INT(BT_MODE_BLE_CLIENT)},
+    { "MODE_BLE_BEACON",           ROREG_INT(BT_MODE_BLE_BEACON)},
+    { "MODE_BLE_MESH",             ROREG_INT(BT_MODE_BLE_MESH)},
+    { "SERVER",                    ROREG_INT(BT_MODE_BLE_SERVER)},
+    { "CLIENT",                    ROREG_INT(BT_MODE_BLE_CLIENT)},
+    { "BEACON",                    ROREG_INT(BT_MODE_BLE_BEACON)},
+    { "MESH",                      ROREG_INT(BT_MODE_BLE_MESH)},
+
+	{ NULL,             ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_nimble( lua_State *L ) {
+    rotable2_newlib(L, reg_nimble);
+    return 1;
+}
+

+ 749 - 0
components/nimble/src/luat_nimble_mode_ble_server.c

@@ -0,0 +1,749 @@
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "luat_base.h"
+#if (defined(AIR101) || defined(AIR103))
+#include "FreeRTOS.h"
+#else
+#include "freertos/FreeRTOS.h"
+#endif
+
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "host/util/util.h"
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+
+#include "luat_msgbus.h"
+#include "luat_malloc.h"
+#include "luat_nimble.h"
+
+/* BLE */
+#include "nimble/nimble_port.h"
+#include "nimble/nimble_port_freertos.h"
+
+/* Heart-rate configuration */
+#define GATT_HRS_UUID                           0x180D
+#define GATT_HRS_MEASUREMENT_UUID               0x2A37
+#define GATT_HRS_BODY_SENSOR_LOC_UUID           0x2A38
+#define GATT_DEVICE_INFO_UUID                   0x180A
+#define GATT_MANUFACTURER_NAME_UUID             0x2A29
+#define GATT_MODEL_NUMBER_UUID                  0x2A24
+
+/** GATT server. */
+#define GATT_SVR_SVC_ALERT_UUID               0x1811
+#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID   0x2A47
+#define GATT_SVR_CHR_NEW_ALERT                0x2A46
+#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID   0x2A48
+#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID      0x2A45
+#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT        0x2A44
+
+// extern uint16_t hrs_hrm_handle;
+
+typedef void (*TaskFunction_t)( void * );
+
+struct ble_hs_cfg;
+struct ble_gatt_register_ctxt;
+
+static void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+static int gatt_svr_init(void);
+
+static const char *manuf_name = "LuatOS";
+static const char *model_num = "BLE Demo";
+static uint16_t hrs_hrm_handle;
+static uint16_t g_ble_attr_indicate_handle;
+static uint16_t g_ble_attr_write_handle;
+static uint16_t g_ble_conn_handle;
+// extern uint16_t g_ble_state;
+
+#define WM_GATT_SVC_UUID      0xFFF0
+#define WM_GATT_INDICATE_UUID 0xFFF1
+#define WM_GATT_WRITE_UUID    0xFFF2
+#define WM_GATT_NOTIFY_UUID    0xFFF3
+
+
+#define LUAT_LOG_TAG "nimble"
+#include "luat_log.h"
+
+static char selfname[32];
+// extern uint16_t g_ble_conn_handle;
+static uint16_t g_ble_state;
+
+typedef struct ble_write_msg {
+    // uint16_t conn_handle,
+    // uint16_t attr_handle,
+    ble_uuid_t* uuid;
+    uint16_t len;
+    char buff[1];
+}ble_write_msg_t;
+
+static int
+gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static int
+gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
+                                struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static int
+gatt_svr_chr_access_func(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+    {
+        /* Service: Heart-rate */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(GATT_HRS_UUID),
+        .characteristics = (struct ble_gatt_chr_def[])
+        { {
+#if 1
+                /* Characteristic: Heart-rate measurement */
+                .uuid = BLE_UUID16_DECLARE(GATT_HRS_MEASUREMENT_UUID),
+                .access_cb = gatt_svr_chr_access_heart_rate,
+                .val_handle = &hrs_hrm_handle,
+                .flags = BLE_GATT_CHR_F_NOTIFY,
+            }, {
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(GATT_HRS_BODY_SENSOR_LOC_UUID),
+                .access_cb = gatt_svr_chr_access_heart_rate,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+#endif
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(WM_GATT_WRITE_UUID),
+                .val_handle = &g_ble_attr_write_handle,
+                .access_cb = gatt_svr_chr_access_func,
+                .flags = BLE_GATT_CHR_F_WRITE,
+            }, {
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(WM_GATT_INDICATE_UUID),
+                .val_handle = &g_ble_attr_indicate_handle,
+                .access_cb = gatt_svr_chr_access_func,
+                .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ,
+            }, {
+                0, /* No more characteristics in this service */
+            },
+        }
+    },
+#if 1
+    {
+        /* Service: Device Information */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(GATT_DEVICE_INFO_UUID),
+        .characteristics = (struct ble_gatt_chr_def[])
+        { {
+                /* Characteristic: * Manufacturer name */
+                .uuid = BLE_UUID16_DECLARE(GATT_MANUFACTURER_NAME_UUID),
+                .access_cb = gatt_svr_chr_access_device_info,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+                /* Characteristic: Model number string */
+                .uuid = BLE_UUID16_DECLARE(GATT_MODEL_NUMBER_UUID),
+                .access_cb = gatt_svr_chr_access_device_info,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+                0, /* No more characteristics in this service */
+            },
+        }
+    },
+#endif
+    {
+        0, /* No more services */
+    },
+};
+
+static int
+gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    /* Sensor location, set to "Chest" */
+    static uint8_t body_sens_loc = 0x01;
+    uint16_t uuid;
+    int rc;
+
+    uuid = ble_uuid_u16(ctxt->chr->uuid);
+
+    if (uuid == GATT_HRS_BODY_SENSOR_LOC_UUID) {
+        rc = os_mbuf_append(ctxt->om, &body_sens_loc, sizeof(body_sens_loc));
+
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    assert(0);
+    return BLE_ATT_ERR_UNLIKELY;
+}
+
+static int
+gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
+                                struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    uint16_t uuid;
+    int rc;
+
+    uuid = ble_uuid_u16(ctxt->chr->uuid);
+
+    if (uuid == GATT_MODEL_NUMBER_UUID) {
+        rc = os_mbuf_append(ctxt->om, model_num, strlen(model_num));
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    if (uuid == GATT_MANUFACTURER_NAME_UUID) {
+        rc = os_mbuf_append(ctxt->om, manuf_name, strlen(manuf_name));
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    assert(0);
+    return BLE_ATT_ERR_UNLIKELY;
+}
+
+static void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+    char buf[BLE_UUID_STR_LEN];
+
+    switch (ctxt->op) {
+    case BLE_GATT_REGISTER_OP_SVC:
+        LLOGD("registered service %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+                    ctxt->svc.handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_CHR:
+        LLOGD("registering characteristic %s with "
+                    "def_handle=%d val_handle=%d\n",
+                    ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+                    ctxt->chr.def_handle,
+                    ctxt->chr.val_handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_DSC:
+        LLOGD("registering descriptor %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+                    ctxt->dsc.handle);
+        break;
+
+    default:
+        assert(0);
+        break;
+    }
+}
+
+static int l_ble_chr_write_cb(lua_State* L, void* ptr) {
+    ble_write_msg_t* wmsg = (ble_write_msg_t*)ptr;
+    rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
+    lua_getglobal(L, "sys_pub");
+    if (lua_isfunction(L, -1)) {
+        lua_pushstring(L, "BLE_GATT_WRITE_CHR");
+        lua_newtable(L);
+        lua_pushlstring(L, wmsg->buff, wmsg->len);
+        lua_call(L, 3, 0);
+    }
+    luat_heap_free(wmsg);
+    return 0;
+}
+
+static int
+gatt_svr_chr_access_func(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    int i = 0;
+    struct os_mbuf *om = ctxt->om;
+    ble_write_msg_t* wmsg;
+    rtos_msg_t msg = {0};
+    LLOGD("gatt_svr_chr_access_func %d %d %d", conn_handle, attr_handle, ctxt->op);
+    switch (ctxt->op) {
+        case BLE_GATT_ACCESS_OP_WRITE_CHR:
+              while(om) {
+                  wmsg = (ble_write_msg_t*)(luat_heap_malloc(sizeof(ble_write_msg_t) + om->om_len - 1));
+                  if (wmsg != NULL) {
+                      wmsg->len = om->om_len;
+                      msg.handler = l_ble_chr_write_cb;
+                      msg.ptr = wmsg;
+                      msg.arg1 = conn_handle;
+                      msg.arg2 = attr_handle;
+                      memcpy(wmsg->buff, om->om_data, om->om_len);
+                      luat_msgbus_put(&msg, 0);
+                  }
+                  om = SLIST_NEXT(om, om_next);
+              }
+              return 0;
+        case BLE_GATT_ACCESS_OP_READ_CHR:
+            return 0;
+        default:
+            assert(0);
+            return BLE_ATT_ERR_UNLIKELY;
+    }
+}
+
+static int gatt_svr_init(void)
+{
+    int rc;
+
+    // ble_svc_gap_init();
+    //ble_gatts_reset();
+    // ble_svc_gatt_init();
+
+    rc = ble_gatts_count_cfg(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_gatts_add_svcs(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+    return 0;
+}
+
+int luat_nimble_server_send(int id, char* data, size_t data_len) {
+    int rc;
+    struct os_mbuf *om;
+
+    if (g_ble_state != BT_STATE_CONNECTED) {
+        //LLOGI("Not connected yet");
+        return -1;
+    }
+
+    om = ble_hs_mbuf_from_flat((const void*)data, (uint16_t)data_len);
+    if (!om) {
+        LLOGE("ble_hs_mbuf_from_flat return NULL!!");
+        return BLE_HS_ENOMEM;
+    }
+    rc = ble_gattc_indicate_custom(g_ble_conn_handle,g_ble_attr_indicate_handle, om);
+    LLOGD("ble_gattc_indicate_custom ret %d", rc);
+    return 0;
+}
+
+
+
+
+// static const char *tag = "NimBLE_BLE_PRPH";
+static int bleprph_gap_event(struct ble_gap_event *event, void *arg);
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
+#else
+static uint8_t own_addr_type;
+#endif
+
+void ble_store_config_init(void);
+
+/**
+ * Logs information about a connection to the console.
+ */
+
+#define ADDR_FMT "%02X%02X%02X%02X%02X%02X"
+#define ADDR_T(addr) addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]
+
+static void
+bleprph_print_conn_desc(struct ble_gap_conn_desc *desc)
+{
+    LLOGI("handle=%d our_ota_addr_type=%d our_ota_addr=" ADDR_FMT, desc->conn_handle, desc->our_ota_addr.type, ADDR_T(desc->our_ota_addr.val));
+    LLOGI(" our_id_addr_type=%d our_id_addr=" ADDR_FMT, desc->our_id_addr.type, ADDR_T(desc->our_id_addr.val));
+    LLOGI(" peer_ota_addr_type=%d peer_ota_addr=" ADDR_FMT, desc->peer_ota_addr.type, ADDR_T(desc->peer_ota_addr.val));
+    LLOGI(" peer_id_addr_type=%d peer_id_addr=" ADDR_FMT, desc->peer_id_addr.type, ADDR_T(desc->peer_id_addr.val));
+    LLOGI(" conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+                "encrypted=%d authenticated=%d bonded=%d\n",
+                desc->conn_itvl, desc->conn_latency,
+                desc->supervision_timeout,
+                desc->sec_state.encrypted,
+                desc->sec_state.authenticated,
+                desc->sec_state.bonded);
+}
+
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+ext_bleprph_advertise(void)
+{
+    struct ble_gap_ext_adv_params params;
+    struct os_mbuf *data;
+    uint8_t instance = 1;
+    int rc;
+
+    /* use defaults for non-set params */
+    memset (&params, 0, sizeof(params));
+
+    /* enable connectable advertising */
+    params.connectable = 1;
+    params.scannable = 1;
+    params.legacy_pdu = 1;
+
+    /* advertise using random addr */
+    params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
+
+    params.primary_phy = BLE_HCI_LE_PHY_1M;
+    params.secondary_phy = BLE_HCI_LE_PHY_2M;
+    //params.tx_power = 127;
+    params.sid = 1;
+
+    params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+    params.itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+
+    /* configure instance 0 */
+    rc = ble_gap_ext_adv_configure(instance, &params, NULL,
+                                   bleprph_gap_event, NULL);
+    assert (rc == 0);
+
+    /* in this case only scan response is allowed */
+
+    /* get mbuf for scan rsp data */
+    data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
+    assert(data);
+
+    /* fill mbuf with scan rsp data */
+    rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
+    assert(rc == 0);
+
+    rc = ble_gap_ext_adv_set_data(instance, data);
+    assert (rc == 0);
+
+    /* start advertising */
+    rc = ble_gap_ext_adv_start(instance, 0, 0);
+    assert (rc == 0);
+}
+#else
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+bleprph_advertise(void)
+{
+    struct ble_gap_adv_params adv_params;
+    struct ble_hs_adv_fields fields;
+    const char *name;
+    int rc;
+
+    /**
+     *  Set the advertisement data included in our advertisements:
+     *     o Flags (indicates advertisement type and other general info).
+     *     o Advertising tx power.
+     *     o Device name.
+     *     o 16-bit service UUIDs (alert notifications).
+     */
+
+    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 assigning 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;
+
+    name = ble_svc_gap_device_name();
+    fields.name = (uint8_t *)name;
+    fields.name_len = strlen(name);
+    fields.name_is_complete = 1;
+
+    fields.uuids16 = (ble_uuid16_t[]) {
+        BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
+    };
+    fields.num_uuids16 = 1;
+    fields.uuids16_is_complete = 1;
+
+    rc = ble_gap_adv_set_fields(&fields);
+    if (rc != 0) {
+        LLOGE("error setting advertisement data; rc=%d\n", rc);
+        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(own_addr_type, NULL, BLE_HS_FOREVER,
+                           &adv_params, bleprph_gap_event, NULL);
+    if (rc != 0) {
+        LLOGE("error enabling advertisement; rc=%d\n", rc);
+        return;
+    }
+}
+#endif
+
+/**
+ * The nimble host executes this callback when a GAP event occurs.  The
+ * application associates a GAP event callback with each connection that forms.
+ * bleprph 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; unused by
+ *                                  bleprph.
+ *
+ * @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
+bleprph_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. */
+        LLOGI("connection %s; status=%d ",
+                    event->connect.status == 0 ? "established" : "failed",
+                    event->connect.status);
+        if (event->connect.status == 0) {
+            g_ble_conn_handle = event->connect.conn_handle;
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            if (rc == 0)
+                bleprph_print_conn_desc(&desc);
+            g_ble_state = BT_STATE_CONNECTED;
+        }
+        else {
+            g_ble_state = BT_STATE_DISCONNECT;
+        }
+        // LLOGI("\n");
+
+        if (event->connect.status != 0) {
+            /* Connection failed; resume advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+            ext_bleprph_advertise();
+#else
+            bleprph_advertise();
+#endif
+        }
+        return 0;
+
+    case BLE_GAP_EVENT_DISCONNECT:
+        g_ble_state = BT_STATE_DISCONNECT;
+        LLOGI("disconnect; reason=%d ", event->disconnect.reason);
+        bleprph_print_conn_desc(&event->disconnect.conn);
+        // LLOGI("\n");
+
+        /* Connection terminated; resume advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+        ext_bleprph_advertise();
+#else
+        bleprph_advertise();
+#endif
+        return 0;
+
+    case BLE_GAP_EVENT_CONN_UPDATE:
+        /* The central has updated the connection parameters. */
+        LLOGI("connection updated; status=%d ", event->conn_update.status);
+        rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
+        if (rc == 0)
+            bleprph_print_conn_desc(&desc);
+        // LLOGI("\n");
+        return 0;
+
+    case BLE_GAP_EVENT_ADV_COMPLETE:
+        LLOGI("advertise complete; reason=%d", event->adv_complete.reason);
+#if !CONFIG_EXAMPLE_EXTENDED_ADV
+        bleprph_advertise();
+#endif
+        return 0;
+
+    case BLE_GAP_EVENT_ENC_CHANGE:
+        /* Encryption has been enabled or disabled for this connection. */
+        LLOGI("encryption change event; status=%d ",
+                    event->enc_change.status);
+        rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
+        if (rc == 0)
+            bleprph_print_conn_desc(&desc);
+        // LLOGI("\n");
+        return 0;
+
+    case BLE_GAP_EVENT_SUBSCRIBE:
+        LLOGI("subscribe event; conn_handle=%d attr_handle=%d "
+                    "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
+                    event->subscribe.conn_handle,
+                    event->subscribe.attr_handle,
+                    event->subscribe.reason,
+                    event->subscribe.prev_notify,
+                    event->subscribe.cur_notify,
+                    event->subscribe.prev_indicate,
+                    event->subscribe.cur_indicate);
+        return 0;
+
+    case BLE_GAP_EVENT_MTU:
+        LLOGI("mtu update event; conn_handle=%d cid=%d mtu=%d\n",
+                    event->mtu.conn_handle,
+                    event->mtu.channel_id,
+                    event->mtu.value);
+        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;
+
+    case BLE_GAP_EVENT_PASSKEY_ACTION:
+        LLOGI("PASSKEY_ACTION_EVENT started");
+#if 0
+        struct ble_sm_io pkey = {0};
+        int key = 0;
+
+        if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
+            pkey.action = event->passkey.params.action;
+            pkey.passkey = 123456; // This is the passkey to be entered on peer
+            // LLOGI("Enter passkey %d on the peer side", pkey.passkey);
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_DISP result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
+            LLOGI("Passkey on device's display: %d", event->passkey.params.numcmp);
+            LLOGI("Accept or reject the passkey through console in this format -> key Y or key N");
+            pkey.action = event->passkey.params.action;
+            // if (scli_receive_key(&key)) {
+            //     pkey.numcmp_accept = key;
+            // } else {
+            //     pkey.numcmp_accept = 0;
+            //     ESP_LOGE(tag, "Timeout! Rejecting the key");
+            // }
+            pkey.numcmp_accept = 1;
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_NUMCMP result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
+            static uint8_t tem_oob[16] = {0};
+            pkey.action = event->passkey.params.action;
+            for (int i = 0; i < 16; i++) {
+                pkey.oob[i] = tem_oob[i];
+            }
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_OOB result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
+            LLOGI("Passkey on device's display: %d", event->passkey.params.numcmp);
+            LLOGI("Enter the passkey through console in this format-> key 123456");
+            pkey.action = event->passkey.params.action;
+            // if (scli_receive_key(&key)) {
+            //     pkey.passkey = key;
+            // } else {
+            //     pkey.passkey = 0;
+            //     ESP_LOGE(tag, "Timeout! Passing 0 as the key");
+            // }
+            pkey.passkey = event->passkey.params.numcmp;
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_INPUT result: %d\n", rc);
+        }
+#endif
+        return 0;
+    }
+
+    return 0;
+}
+
+static void
+bleprph_on_reset(int reason)
+{
+    g_ble_state = BT_STATE_OFF;
+    LLOGE("Resetting state; reason=%d", reason);
+    //app_adapter_state_changed_callback(WM_BT_STATE_OFF);
+}
+
+
+static void
+bleprph_on_sync(void)
+{
+    int rc;
+
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+    /* Generate a non-resolvable private address. */
+    ble_app_set_addr();
+#endif
+
+    /* Make sure we have proper identity address set (public preferred) */
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+    rc = ble_hs_util_ensure_addr(1);
+#else
+    rc = ble_hs_util_ensure_addr(0);
+#endif
+    assert(rc == 0);
+
+    /* Figure out address to use while advertising (no privacy for now) */
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    if (rc != 0) {
+        LLOGE("error determining address type; rc=%d", rc);
+        return;
+    }
+
+    /* Printing ADDR */
+    uint8_t addr_val[6] = {0};
+    rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
+
+    LLOGI("Device Address: " ADDR_FMT, ADDR_T(addr_val));
+    ble_gatts_start();
+    //print_addr(addr_val);
+    // LLOGI("\n");
+    /* Begin advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+    ext_bleprph_advertise();
+#else
+    bleprph_advertise();
+#endif
+
+    if (g_ble_state == BT_STATE_OFF)
+        g_ble_state = BT_STATE_ON;
+}
+
+
+
+int luat_nimble_init_server(uint8_t uart_idx, char* name, int mode) {
+    int rc = 0;
+    nimble_port_init();
+
+    if (name == NULL || strlen(name) == 0) {
+        if (selfname[0] == 0) {
+            memcpy(selfname, "LuatOS", strlen("LuatOS") + 1);
+        }
+    }
+    else {
+        memcpy(selfname, name, strlen(name) + 1);
+    }
+
+    /* Set the default device name. */
+    if (strlen(selfname))
+        rc = ble_svc_gap_device_name_set((const char*)selfname);
+
+
+    /* Initialize the NimBLE host configuration. */
+    ble_hs_cfg.reset_cb = bleprph_on_reset;
+    ble_hs_cfg.sync_cb = bleprph_on_sync;
+    ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
+    ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+    ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
+    ble_hs_cfg.sm_sc = 0;
+
+
+    ble_svc_gap_init();
+    ble_svc_gatt_init();
+
+    rc = gatt_svr_init();
+    LLOGD("gatt_svr_init rc %d", rc);
+
+    /* XXX Need to have template for store */
+    ble_store_config_init();
+
+    return 0;
+}
+