Procházet zdrojové kódy

[Add]添加 ble 相关驱动文件。

liangyingjian před 4 roky
rodič
revize
18226a9c20
4 změnil soubory, kde provedl 1795 přidání a 0 odebrání
  1. 220 0
      inc/spi_ble_nimble.h
  2. 520 0
      inc/spi_ble_rw007.h
  3. 685 0
      src/ble_cmd_rw007.c
  4. 370 0
      src/spi_ble_rw007.c

+ 220 - 0
inc/spi_ble_nimble.h

@@ -0,0 +1,220 @@
+#ifndef __SPI_BLE_NIMBLE__
+#define __SPI_BLE_NIMBLE__
+
+#include "rtthread.h"
+
+#define MYNEWT_VAL(x)                           MYNEWT_VAL_ ## x
+
+/* Advertising report */
+#define BLE_HCI_ADV_RPT_EVTYPE_ADV_IND      (0)
+#define BLE_HCI_ADV_RPT_EVTYPE_DIR_IND      (1)
+#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND     (2)
+#define BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND  (3)
+#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP     (4)
+
+/** Connection security state */
+struct ble_gap_sec_state {
+    /** If connection is encrypted */
+    unsigned encrypted:1;
+
+    /** If connection is authenticated */
+    unsigned authenticated:1;
+
+    /** If connection is bonded (security information is stored)  */
+    unsigned bonded:1;
+
+    /** Size of a key used for encryption */
+    unsigned key_size:5;
+};
+
+typedef struct {
+    rt_uint8_t type;
+    rt_uint8_t val[6];
+} ble_addr_t;
+
+/** @brief Connection descriptor */
+struct ble_gap_conn_desc {
+    /** Connection security state */
+    struct ble_gap_sec_state sec_state;
+    /** Local identity address */
+    ble_addr_t our_id_addr;
+    /** Peer identity address */
+    ble_addr_t peer_id_addr;
+    /** Local over-the-air address */
+    ble_addr_t our_ota_addr;
+    /** Peer over-the-air address */
+    ble_addr_t peer_ota_addr;
+    /** Connection handle */
+    rt_uint16_t conn_handle;
+    /** Connection interval */
+    rt_uint16_t conn_itvl;
+    /** Connection latency */
+    rt_uint16_t conn_latency;
+    /** Connection supervision timeout */
+    rt_uint16_t supervision_timeout;
+    /** Connection Role
+     * Possible values BLE_GAP_ROLE_SLAVE or BLE_GAP_ROLE_MASTER
+     */
+    rt_uint8_t role;
+    /** Master clock accuracy */
+    rt_uint8_t master_clock_accuracy;
+};
+
+struct ble_gap_disc_desc {
+    /*** Common fields. */
+    rt_uint8_t event_type;
+    rt_uint8_t length_data;
+    ble_addr_t addr;
+    rt_int8_t rssi;
+    rt_uint8_t *data;
+
+    /***
+     * LE direct advertising report fields; direct_addr is BLE_ADDR_ANY if
+     * direct address fields are not present.
+     */
+    ble_addr_t direct_addr;
+};
+
+struct ble_gap_upd_params {
+    rt_uint16_t itvl_min;
+    rt_uint16_t itvl_max;
+    rt_uint16_t latency;
+    rt_uint16_t supervision_timeout;
+    rt_uint16_t min_ce_len;
+    rt_uint16_t max_ce_len;
+};
+
+struct ble_gap_passkey_params {
+    rt_uint8_t action;
+    rt_uint32_t numcmp;
+};
+
+struct ble_gap_repeat_pairing {
+    /** The handle of the relevant connection. */
+    rt_uint16_t conn_handle;
+
+    /** Properties of the existing bond. */
+    rt_uint8_t cur_key_size;
+    rt_uint8_t cur_authenticated:1;
+    rt_uint8_t cur_sc:1;
+
+    /**
+     * Properties of the imminent secure link if the pairing procedure is
+     * allowed to continue.
+     */
+    rt_uint8_t new_key_size;
+    rt_uint8_t new_authenticated:1;
+    rt_uint8_t new_sc:1;
+    rt_uint8_t new_bonding:1;
+};
+
+struct ble_gap_event {
+    rt_uint8_t type;
+
+    union {
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+        } connect;
+
+        struct {
+            int reason;
+            struct ble_gap_conn_desc conn;
+        } disconnect;
+
+        struct ble_gap_disc_desc disc;
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        struct ble_gap_ext_disc_desc ext_disc;
+#endif
+
+        struct {
+            int reason;
+        } disc_complete;
+
+        struct {
+            int reason;
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+            rt_uint8_t instance;
+
+            rt_uint16_t conn_handle;
+            rt_uint8_t num_ext_adv_events;
+#endif
+        } adv_complete;
+
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+        } conn_update;
+
+        struct {
+            const struct ble_gap_upd_params *peer_params;
+            struct ble_gap_upd_params *self_params;
+            rt_uint16_t conn_handle;
+        } conn_update_req;
+
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+        } term_failure;
+
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+        } enc_change;
+
+        struct {
+            struct ble_gap_passkey_params params;
+
+            rt_uint16_t conn_handle;
+        } passkey;
+
+        struct {
+            struct os_mbuf *om;
+            rt_uint16_t attr_handle;
+            rt_uint16_t conn_handle;
+            rt_uint8_t indication:1;
+        } notify_rx;
+
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+
+            rt_uint16_t attr_handle;
+            rt_uint8_t indication:1;
+        } notify_tx;
+
+        struct {
+            rt_uint16_t conn_handle;
+            rt_uint16_t attr_handle;
+            rt_uint8_t reason;
+            rt_uint8_t prev_notify:1;
+
+            rt_uint8_t cur_notify:1;
+            rt_uint8_t prev_indicate:1;
+            rt_uint8_t cur_indicate:1;
+        } subscribe;
+
+        struct {
+            rt_uint16_t conn_handle;
+            rt_uint16_t channel_id;
+            rt_uint16_t value;
+        } mtu;
+
+        struct {
+            rt_uint16_t conn_handle;
+        } identity_resolved;
+
+        struct ble_gap_repeat_pairing repeat_pairing;
+
+        struct {
+            int status;
+            rt_uint16_t conn_handle;
+            rt_uint8_t tx_phy;
+            rt_uint8_t rx_phy;
+        } phy_updated;
+    };
+};
+
+#endif

+ 520 - 0
inc/spi_ble_rw007.h

@@ -0,0 +1,520 @@
+#ifndef __SPI_BLE_RW007__
+#define __SPI_BLE_RW007__
+
+#include "rtthread.h"
+#include <string.h>
+#include <stdint.h>
+
+#include "spi_ble_nimble.h"
+
+#define BLE_MAC_LEN                 6
+#define BLE_MAX_DATA_LEN            1520
+
+#define member_offset(type, member) ((unsigned long)(&((type *)0)->member))
+
+typedef enum
+{
+    RW007_BLE_RESP_TYPE_CMD,
+    RW007_BLE_RESP_TYPE_NOTIFY,
+}rw007_ble_resp_type_t;
+
+typedef enum
+{
+    RW007_BLE_REQ_TYPE_INIT = 1,
+    RW007_BLE_REQ_TYPE_ADDR_GET,
+    RW007_BLE_REQ_TYPE_CONN_INFO_GET,
+    RW007_BLE_REQ_TYPE_CONN_UPD_PARAMS,
+    RW007_BLE_REQ_TYPE_SCAN,
+    RW007_BLE_REQ_TYPE_STOP_SCAN,
+    RW007_BLE_REQ_TYPE_CONNECT,
+    RW007_BLE_REQ_TYPE_DISCONN,
+    RW007_BLE_REQ_TYPE_GATT_DIS_FULL,
+    RW007_BLE_REQ_TYPE_MTU_EXCHANGE,
+    RW007_BLE_REQ_TYPE_NOTIFYCHANGE,
+    RW007_BLE_REQ_TYPE_WRITE,
+    RW007_BLE_REQ_TYPE_READ,
+    RW007_BLE_REQ_TYPE_NOTIFYCHANGE_BY_UUID,
+    RW007_BLE_REQ_TYPE_WRITE_BY_UUID,
+    RW007_BLE_REQ_TYPE_READ_BY_UUID,
+} rw007_ble_req_type_t;
+
+typedef enum
+{
+    RW007_BLE_RSP_TYPE_INIT = 0x50,
+    RW007_BLE_RSP_TYPE_ADDR_GET,
+    RW007_BLE_RSP_TYPE_CONN_INFO_GET,
+    RW007_BLE_RSP_TYPE_CONN_UPD_PARAMS,
+    RW007_BLE_RSP_TYPE_SCAN,
+    RW007_BLE_RSP_TYPE_CONNECT,
+    RW007_BLE_RSP_TYPE_DISCONN,
+    RW007_BLE_RSP_TYPE_GATT_DIS_FULL,
+    RW007_BLE_RSP_TYPE_GATTC_SRV,
+    RW007_BLE_RSP_TYPE_GATTC_CHR,
+    RW007_BLE_RSP_TYPE_GATTC_DSC,
+    RW007_BLE_RSP_TYPE_MTU_EXCHANGE,
+    RW007_BLE_RSP_TYPE_NOTIFY,
+    RW007_BLE_RSP_TYPE_WRITE,
+    RW007_BLE_RSP_TYPE_READ,
+    RW007_BLE_RSP_TYPE_MAX,
+} rw007_ble_rsp_type_t;
+
+typedef enum
+{
+    RW007_BLE_NTF_TYPE_CONN_UPD = 0xA0,
+    RW007_BLE_NTF_TYPE_CONN_UPD_PARAMS,
+    RW007_BLE_NTF_TYPE_DISC,
+    RW007_BLE_NTF_TYPE_CONNECT,
+    RW007_BLE_NTF_TYPE_DISCONN,
+    RW007_BLE_NTF_TYPE_MTU_EXCHANGE,
+    RW007_BLE_NTF_TYPE_DISC_COMPLETE,
+    RW007_BLE_NTF_TYPE_ADV_COMPLETE,
+    RW007_BLE_NTF_TYPE_SUBSCRIBE,
+    RW007_BLE_NTF_TYPE_NOTIFY_RX,
+    RW007_BLE_NTF_TYPE_MAX
+} rw007_ble_ntf_type_t;
+#define RW007_BLE_INIT_ROLE_PERIPHERAL      1
+#define RW007_BLE_INIT_ROLE_CENTRAL         2
+
+/* Bluetooth Device address type */
+#define RW007_BLE_ADDR_PUBLIC      (0x00)
+#define RW007_BLE_ADDR_RANDOM      (0x01)
+#define RW007_BLE_ADDR_PUBLIC_ID   (0x02)
+#define RW007_BLE_ADDR_RANDOM_ID   (0x03)
+
+/** Type of UUID */
+enum {
+    /** 16-bit UUID (BT SIG assigned) */
+    BLE_UUID_TYPE_16 = 16,
+    /** 32-bit UUID (BT SIG assigned) */
+    BLE_UUID_TYPE_32 = 32,
+    /** 128-bit UUID */
+    BLE_UUID_TYPE_128 = 128,
+};
+
+typedef struct
+{
+    uint8_t type;
+    uint8_t reserved;
+    uint16_t reserved2;
+    union {
+        uint16_t uuid16;
+        uint32_t uuid32;
+        uint8_t uuid128[16];
+    } uuid;
+} rw007_ble_uuid_t;
+
+typedef struct
+{
+    uint8_t type;
+    uint8_t val[6];
+} rw007_ble_addr_t;
+
+typedef struct
+{
+    uint16_t start_handle;
+    uint16_t end_handle;
+    rw007_ble_uuid_t uuid;
+} rw007_ble_svc_t;
+
+typedef struct
+{
+    uint16_t def_handle;
+    uint16_t val_handle;
+    uint8_t properties;
+    uint8_t reserved;
+    uint16_t reserved2;
+    rw007_ble_uuid_t uuid;
+} rw007_ble_chr_t;
+
+typedef struct
+{
+    uint16_t handle;
+    uint16_t reserved;
+    rw007_ble_uuid_t uuid;
+} rw007_ble_dsc_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t reserved;
+    rw007_ble_svc_t svc;
+} rw007_ble_svc_rsp_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t attr_handle;
+    rw007_ble_chr_t chr;
+} rw007_ble_chr_rsp_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t attr_handle;
+    rw007_ble_dsc_t dsc;
+} rw007_ble_dsc_rsp_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t attr_handle;
+    rw007_ble_uuid_t uuid;
+    uint16_t status;
+    uint16_t reserved;
+} rw007_ble_write_rsp_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t attr_handle;
+    rw007_ble_uuid_t uuid;
+    uint16_t status;
+    uint16_t length;
+    // NOTE: packed below data
+} rw007_ble_read_rsp_t;
+
+typedef struct
+{
+    uint16_t conn_handle;
+    uint16_t atrr_handle;
+    rw007_ble_uuid_t uuid;
+    uint16_t status;
+    uint16_t reserved;
+} rw007_ble_notifychange_rsp_t;
+
+struct rw007_ble_write_by_uuid
+{
+    rt_uint16_t conn_handle;
+    rt_uint16_t data_len;
+    rw007_ble_uuid_t uuid;
+    rt_uint8_t data[0];
+};
+
+struct rw007_ble_read_by_uuid
+{
+    uint16_t conn_handle;
+    uint16_t reserved;
+    rw007_ble_uuid_t uuid;
+};
+
+struct rw007_ble_get_addr
+{
+    rt_uint8_t public_id_addr[6];
+    rt_uint8_t random_id_addr[6];
+};
+
+struct rw007_ble_notify_change_by_uuid
+{
+    rt_uint16_t conn_handle;
+    rt_uint16_t char_value;
+    rw007_ble_uuid_t uuid;
+};
+
+struct rw007_ble_scan_params
+{
+    rt_uint8_t limited; // 1/0
+    rt_uint8_t passive; // 1/0
+    rt_uint8_t filter; // 0 disable /1 wl /2 inta /3 1+2
+    rt_uint32_t duration;
+    rt_uint16_t interval;
+    rt_uint16_t window;
+};
+
+struct rw007_ble_req
+{
+    rt_uint16_t req_type;
+    rt_uint16_t len;
+    union
+    {
+        rt_uint32_t int_value;
+        ble_addr_t addr;
+        struct rw007_ble_get_addr get_addr;
+        struct rw007_ble_notify_change_by_uuid notify_change;
+        rt_uint8_t bytes[BLE_MAX_DATA_LEN];
+    } value;
+};
+
+/**
+ * below is rw007 upload(notify response) packet type
+*/
+
+struct rw007_ble_conn_desc
+{
+     /** If connection is encrypted */
+    uint8_t encrypted:1;
+
+    /** If connection is authenticated */
+    uint8_t authenticated:1;
+
+    /** If connection is bonded (security information is stored)  */
+    uint8_t bonded:1;
+
+    /** Size of a key used for encryption */
+    uint8_t key_size:5;
+
+    /** Connection Role
+     * Possible values BLE_GAP_ROLE_SLAVE or BLE_GAP_ROLE_MASTER
+     */
+    uint8_t role;
+
+    /** Connection handle */
+    uint16_t conn_handle;
+
+    /** Connection interval */
+    uint16_t conn_itvl;
+
+    /** Connection latency */
+    uint16_t conn_latency;
+
+    /** Connection supervision timeout */
+    uint16_t supervision_timeout;
+
+    uint8_t our_id_type;
+    uint8_t our_ota_type;
+    uint8_t peer_id_type;
+    uint8_t peer_ota_type;
+    uint8_t our_id_addr[6];
+    uint8_t our_ota_addr[6];
+    uint8_t peer_id_addr[6];
+    uint8_t peer_ota_addr[6];
+};
+
+struct rw007_ble_gap_event_connect
+{
+    uint8_t event_type;
+    uint8_t reserved;
+
+    uint16_t conn_handle;
+    int32_t status;
+    // NOTE: below conn_disc
+    // struct rw007_ble_conn_desc conn_disc;
+};
+
+struct rw007_ble_gap_event_disconnect
+{
+    uint8_t event_type;
+    uint8_t reserved;
+    uint16_t reserved2;
+
+    int32_t reason;
+
+    // NOTE: below conn_disc
+    // struct rw007_ble_conn_desc conn_disc;
+};
+
+struct rw007_ble_gap_event_discov
+{
+    uint8_t event_type;
+    uint8_t discov_type;
+    uint8_t length_data;
+    int8_t rssi;
+
+    uint8_t addr_type;
+    uint8_t direct_type;
+
+    uint8_t addr[6];
+
+    /***
+     * LE direct advertising report fields; direct_addr is BLE_ADDR_ANY if
+     * direct address fields are not present.
+     */
+    uint8_t direct_addr[6];
+
+    uint16_t reserved;
+    // NOTE: below fields are buffer data fields
+};
+
+struct rw007_ble_gap_event_conn_upd
+{
+    uint8_t event_type;
+    uint8_t reserved;
+    uint16_t conn_handle;
+
+    int32_t status;
+
+    // NOTE: below conn_disc
+    // struct rw007_ble_conn_desc conn_disc;
+};
+
+struct rw007_ble_gap_event_discov_complete
+{
+    uint8_t event_type;
+    uint8_t reserved;
+    uint8_t reserved2;
+
+    int32_t reason;
+};
+
+struct rw007_ble_gap_event_adv_complete
+{
+    uint8_t event_type;
+    uint8_t reserved;
+    uint8_t reserved2;
+
+    int32_t reason;
+};
+
+struct rw007_ble_gap_event_notify_rx
+{
+    uint8_t event_type;
+    /**
+     * Whether the received command is a notification or an
+     * indication;
+     *     o 0: Notification;
+     *     o 1: Indication.
+     */
+    uint8_t indication;
+
+    /** The handle of the relevant ATT attribute. */
+    uint16_t attr_handle;
+
+    /** The handle of the relevant connection. */
+    uint16_t conn_handle;
+
+    uint16_t length_data;
+    // NOTE: below is the buffer data
+};
+
+struct rw007_ble_gap_event_subscribe
+{
+    uint8_t event_type;
+    uint8_t reserved;
+
+    /** The handle of the relevant connection. */
+    uint16_t conn_handle;
+
+    /** The value handle of the relevant characteristic. */
+    uint16_t attr_handle;
+
+    /** One of the BLE_GAP_SUBSCRIBE_REASON codes. */
+    uint8_t reason;
+
+    /** Whether the peer was previously subscribed to notifications. */
+    uint8_t prev_notify:1;
+
+    /** Whether the peer is currently subscribed to notifications. */
+    uint8_t cur_notify:1;
+
+    /** Whether the peer was previously subscribed to indications. */
+    uint8_t prev_indicate:1;
+
+    /** Whether the peer is currently subscribed to indications. */
+    uint8_t cur_indicate:1;
+    uint8_t reserved4:4;
+};
+
+struct rw007_ble_gap_event_mtu_update
+{
+    uint8_t event_type;
+    uint8_t reserved;
+
+    /** The handle of the relevant connection. */
+    uint16_t conn_handle;
+
+    /**
+     * Indicates the channel whose MTU has been updated; either
+     * BLE_L2CAP_CID_ATT or the ID of a connection-oriented channel.
+     */
+    uint16_t channel_id;
+
+    /* The channel's new MTU. */
+    uint16_t value;
+};
+
+struct rw007_ble_resp
+{
+    rt_uint16_t resp_type;    // rw007_BLE_RESP_TYPE_CMD / RW007_BLE_RESP_TYPE_NOTIFY
+    rt_uint16_t cmd;
+    rt_uint16_t len;
+    rt_uint16_t result;
+    rt_uint8_t data[BLE_MAX_DATA_LEN];
+};
+
+typedef void (*rw007_ble_resp_handle_cb)(rt_uint16_t resp_type, void *data, rt_uint16_t size);
+typedef void (*rw007_ble_ntf_handle_cb)(rt_uint16_t ntf_type, void *data, rt_uint16_t size);
+
+void rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle_cb resp_cb);
+void rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle_cb notify_cb);
+
+int rw007_ble_init(rt_uint8_t roles);
+int rw007_ble_addr_get(void);
+int rw007_ble_conn_info_get(rt_uint16_t conn_handle);
+int rw007_ble_conn_update_params(rt_uint16_t conn_handle, struct ble_gap_upd_params *params);
+int rw007_ble_central_init(void);
+int rw007_ble_scan(struct rw007_ble_scan_params *scan_param);
+int rw007_ble_scan_stop(void);
+int rw007_ble_connect(ble_addr_t *addr);
+int rw007_ble_disconnect(rt_uint16_t conn_handle);
+int rw007_ble_gattc_service_get(rt_uint16_t conn_handle);
+int rw007_ble_gattc_characteristic_get(rt_uint16_t conn_handle, rt_uint16_t attr_handle);
+int rw007_ble_gattc_discriptor_get(rt_uint16_t conn_handle, rt_uint16_t attr_handle);
+int rw007_ble_gattc_service_discover(rt_uint16_t conn_handle);
+int rw007_ble_mtu_exchange(rt_uint16_t conn_handle);
+int rw007_ble_gatt_notify_change(rt_uint16_t attr_handle);
+int rw007_ble_gattc_write(rt_uint16_t conn_handle, rt_uint16_t attr_handle, const rt_uint8_t *buf, rt_uint16_t len);
+int rw007_ble_gattc_read(rt_uint16_t conn_handle, rt_uint16_t attr_handle);
+int rw007_ble_gatt_notify_change_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid, uint16_t value);
+int rw007_ble_gattc_write_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid, const rt_uint8_t *buf, rt_uint16_t len);
+int rw007_ble_gattc_read_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid);
+
+static inline void _hexstrtoaddr(char* hexstr, rt_uint8_t addr[])
+{
+    int i, len, pos;
+    rt_uint8_t hexbyte = 0;
+
+    len = strlen(hexstr) + 1;
+    pos = 5;
+
+    for (i = 0; i < len; i++)
+    {
+        if (hexstr[i] >= '0' && hexstr[i] <= '9')
+        {
+            hexbyte <<= 4;
+            hexbyte |= hexstr[i] - '0';
+        }
+        else if (hexstr[i] >= 'a' && hexstr[i] <= 'f')
+        {
+            hexbyte <<= 4;
+            hexbyte |= hexstr[i] - 'a' + 10;
+        }
+        else if (hexstr[i] >= 'A' && hexstr[i] <= 'F')
+        {
+            hexbyte <<= 4;
+            hexbyte |= hexstr[i] - 'A' + 10;
+        }
+        else
+        {
+            addr[pos--] = hexbyte;
+            if (pos < 0) break;
+            hexbyte = 0;
+        }
+    }
+}
+
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+rt_inline void hex_dump(const rt_uint8_t *ptr, rt_size_t buflen)
+{
+    unsigned char *buf = (unsigned char *)ptr;
+    int i, j;
+
+    RT_ASSERT(ptr != RT_NULL);
+
+    for (i = 0; i < buflen; i += 16)
+    {
+        rt_kprintf("%08X: ", i);
+
+        for (j = 0; j < 16; j++)
+            if (i + j < buflen)
+                rt_kprintf("%02X ", buf[i + j]);
+            else
+                rt_kprintf("   ");
+        rt_kprintf(" ");
+
+        for (j = 0; j < 16; j++)
+            if (i + j < buflen)
+                rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+        rt_kprintf("\n");
+    }
+}
+
+#endif

+ 685 - 0
src/ble_cmd_rw007.c

@@ -0,0 +1,685 @@
+#include "spi_ble_rw007.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct ble_cmd_des
+{
+    const char *cmd;
+    int (*fun)(int argc, char *argv[]);
+};
+
+static int ble_cmd_help(int argc, char *argv[]);
+
+static int ble_cmd_init(int argc, char *argv[]);
+static int ble_cmd_get_addr(int argc, char *argv[]);
+static int ble_cmd_get_connect_info(int argc, char *argv[]);
+static int ble_cmd_update_params(int argc, char *argv[]);
+static int ble_cmd_scan(int argc, char *argv[]);
+static int ble_cmd_stop_scan(int argc, char *argv[]);
+static int ble_cmd_connect(int argc, char *argv[]);
+static int ble_cmd_disconnect(int argc, char *argv[]);
+static int ble_cmd_gattc_service_get(int argc, char *argv[]);
+static int ble_cmd_gattc_characteristic_get(int argc, char *argv[]);
+static int ble_cmd_gattc_discriptor_get(int argc, char *argv[]);
+static int ble_cmd_mtu_exchange(int argc, char *argv[]);
+static int ble_cmd_gatt_notify_change(int argc, char *argv[]);
+static int ble_cmd_gattc_write(int argc, char *argv[]);
+static int ble_cmd_gattc_read(int argc, char *argv[]);
+static int ble_cmd_gatt_notify_change_by_uuid(int argc, char *argv[]);
+static int ble_cmd_gattc_write_by_uuid(int argc, char *argv[]);
+static int ble_cmd_gattc_read_by_uuid(int argc, char *argv[]);
+static int ble_cmd_cfgwifi(int argc, char *argv[]);
+
+static const struct ble_cmd_des cmd_tab[] =
+{
+    {"help",            ble_cmd_help},
+    {"init",            ble_cmd_init},
+    {"get_addr",        ble_cmd_get_addr},
+    {"get_con_info",    ble_cmd_get_connect_info},
+    {"update_params",   ble_cmd_update_params},
+    {"scan",            ble_cmd_scan},
+    {"stop_scan",       ble_cmd_stop_scan},
+    {"connect",         ble_cmd_connect},
+    {"disconnect",      ble_cmd_disconnect},
+    {"get_server",      ble_cmd_gattc_service_get},
+    {"get_char",        ble_cmd_gattc_characteristic_get},
+    {"get_disc",        ble_cmd_gattc_discriptor_get},
+    {"mtu_exch",        ble_cmd_mtu_exchange},
+    {"notify",          ble_cmd_gatt_notify_change},
+    {"write",           ble_cmd_gattc_write},
+    {"read",            ble_cmd_gattc_read},
+    {"notify_change",     ble_cmd_gatt_notify_change_by_uuid},
+    {"write_uuid",      ble_cmd_gattc_write_by_uuid},
+    {"read_uuid",       ble_cmd_gattc_read_by_uuid},
+    {"cfgwifi",         ble_cmd_cfgwifi},
+};
+
+static int ble_cmd_help(int argc, char *argv[])
+{
+    rt_kprintf("[rw007_ble command]\n\n");
+    rt_kprintf("rw007_ble help\n");
+    rt_kprintf("rw007_ble init central/peripheral                           Note: init ble mode\n");
+    rt_kprintf("rw007_ble get_addr                                          Note: get ble address\n");
+    rt_kprintf("rw007_ble update_params                                     Note: update connect parameters(no support)\n");
+    rt_kprintf("rw007_ble scan                                              Note: scan ble slave\n");
+    rt_kprintf("rw007_ble stop_scan                                         Note: stop scan\n");
+    rt_kprintf("rw007_ble connect xx:xx:xx:xx:xx:xx                         Note: use slave addr to connect\n");
+    rt_kprintf("rw007_ble disconnect [conn_handle]                          Note: disconnect slave\n");
+    rt_kprintf("rw007_ble get_server                                        Note: discover all server(no support)\n");
+    rt_kprintf("rw007_ble get_char                                          Note: discover all description(no support)\n");
+    rt_kprintf("rw007_ble get_disc                                          Note: discover all characteristic(no support)\n");
+    rt_kprintf("rw007_ble mtu_exch                                          Note: ble mtu exchange(no support)\n");
+    rt_kprintf("rw007_ble notify                                            Note: enable ble notify(no support)\n");
+    rt_kprintf("rw007_ble write                                             Note: ble write data(no support)\n");
+    rt_kprintf("rw007_ble read                                              Note: ble read data(no support)\n");
+    rt_kprintf("rw007_ble notify_change [conn_handle] [UUID] [char_value]   Note: ble notify configure by uuid\n");
+    rt_kprintf("rw007_ble write_uuid [conn_handle] [UUID] [data]            Note: ble write data by uuid\n");
+    rt_kprintf("rw007_ble read_uuid [conn_handle] [UUID]                    Note: ble read data by uuid\n");
+    rt_kprintf("rw007_ble cfgwifi duration_ms                               Note: enable ble configuration wifi\n");
+
+    rt_kprintf("\n");
+    return 0;
+}
+
+static void _print_addr(uint8_t addr[6])
+{
+    const uint8_t *u8p;
+
+    u8p = addr;
+    rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x", u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+}
+
+static void _print_hex(uint8_t *arr, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++)
+    {
+        rt_kprintf("%02x ", arr[i]);
+    }
+}
+
+// recv slave resp cmd handle
+static void rw007_ble_resp_handle(rt_uint16_t resp_type, void *data, rt_uint16_t size)
+{
+    switch(resp_type)
+    {
+        case RW007_BLE_RSP_TYPE_INIT:
+            rt_kprintf("RW007_BLE_RSP_TYPE_INIT\n");
+            break;
+        case RW007_BLE_RSP_TYPE_ADDR_GET:
+        {
+            struct rw007_ble_get_addr *get_addr = (struct rw007_ble_get_addr *)data;
+            rt_kprintf("public_id_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                        get_addr->public_id_addr[5], get_addr->public_id_addr[4],
+                        get_addr->public_id_addr[3], get_addr->public_id_addr[2],
+                        get_addr->public_id_addr[1], get_addr->public_id_addr[0]);
+            rt_kprintf("random_id_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                        get_addr->random_id_addr[5], get_addr->random_id_addr[4],
+                        get_addr->random_id_addr[3], get_addr->random_id_addr[2],
+                        get_addr->random_id_addr[1], get_addr->random_id_addr[0]);
+        }
+            break;
+        case RW007_BLE_RSP_TYPE_CONN_INFO_GET:
+            rt_kprintf("RW007_BLE_RSP_TYPE_CONN_INFO_GET\n");
+            break;
+        case RW007_BLE_RSP_TYPE_CONN_UPD_PARAMS:
+            rt_kprintf("RW007_BLE_RSP_TYPE_CONN_UPD_PARAMS\n");
+            break;
+        case RW007_BLE_RSP_TYPE_SCAN:
+            rt_kprintf("RW007_BLE_RSP_TYPE_SCAN\n");
+            break;
+        case RW007_BLE_RSP_TYPE_CONNECT:
+            rt_kprintf("RW007_BLE_RSP_TYPE_CONNECT\n");
+            break;
+        case RW007_BLE_RSP_TYPE_DISCONN:
+            rt_kprintf("RW007_BLE_RSP_TYPE_DISCONN\n");
+            break;
+        case RW007_BLE_RSP_TYPE_GATT_DIS_FULL:
+            rt_kprintf("RW007_BLE_RSP_TYPE_GATT_DIS_FULL\n");
+            break;
+        case RW007_BLE_RSP_TYPE_GATTC_SRV:
+            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_SRV\n");
+            break;
+        case RW007_BLE_RSP_TYPE_GATTC_CHR:
+            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_CHR\n");
+            break;
+        case RW007_BLE_RSP_TYPE_GATTC_DSC:
+            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_DSC\n");
+            break;
+        case RW007_BLE_RSP_TYPE_MTU_EXCHANGE:
+            rt_kprintf("RW007_BLE_RSP_TYPE_MTU_EXCHANGE\n");
+            break;
+        case RW007_BLE_RSP_TYPE_NOTIFY:
+            rt_kprintf("RW007_BLE_RSP_TYPE_NOTIFY\n");
+            break;
+        case RW007_BLE_RSP_TYPE_WRITE:
+            rt_kprintf("RW007_BLE_RSP_TYPE_WRITE\n");
+            break;
+        case RW007_BLE_RSP_TYPE_READ:
+        {
+            rw007_ble_read_rsp_t *rsp_read;
+            uint8_t *data_read;
+
+            rsp_read = (rw007_ble_read_rsp_t *)data;
+            data_read = (uint8_t*)(rsp_read + 1);
+
+            rt_kprintf("read %s connect:%d attr_handle:%d uuid: ",
+                    rsp_read->status ? "failure" : "successful",
+                    rsp_read->conn_handle, rsp_read->attr_handle);
+            if (rsp_read->uuid.type == BLE_UUID_TYPE_16)
+            {
+                _print_hex((uint8_t*)&rsp_read->uuid, 2);
+            }
+            else if (rsp_read->uuid.type == BLE_UUID_TYPE_32)
+            {
+                _print_hex((uint8_t*)&rsp_read->uuid, 4);
+            }
+            else if (rsp_read->uuid.type == BLE_UUID_TYPE_128)
+            {
+                _print_hex((uint8_t*)&rsp_read->uuid, 16);
+            }
+
+            if (rsp_read->status == 0)
+            {
+                rt_kprintf(" read data:\n");
+                hex_dump(data_read, size - (data_read - (uint8_t*)data));
+            }
+            else
+            {
+                rt_kprintf("\n");
+            }
+        }
+            break;
+        default:
+            rt_kprintf("error response\n");
+            break;
+    }
+}
+
+// recv slave notity handle
+static void rw007_ble_ntf_handle(rt_uint16_t ntf_type, void *data, rt_uint16_t size)
+{
+    switch(ntf_type)
+    {
+        case RW007_BLE_NTF_TYPE_CONN_UPD:
+            rt_kprintf("RW007_BLE_NTF_TYPE_CONN_UPD\n");
+            break;
+        case RW007_BLE_NTF_TYPE_CONN_UPD_PARAMS:
+            rt_kprintf("RW007_BLE_NTF_TYPE_CONN_UPD_PARAMS\n");
+            break;
+        case RW007_BLE_NTF_TYPE_DISC:
+        {
+            struct rw007_ble_gap_event_discov *disc_desc = RT_NULL;
+            char *dicover_data = RT_NULL;
+
+            rt_kprintf("RW007_BLE_NTF_TYPE_DISCOVER\n");
+
+            disc_desc = (struct rw007_ble_gap_event_discov *)data;
+            dicover_data = (char*)(disc_desc + 1);
+
+            switch(disc_desc->discov_type)
+            {
+                case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND:
+                    break;
+
+                case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND:
+                    break;
+
+                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND:
+                    break;
+
+                case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND:
+                    break;
+
+                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP:
+                    break;
+            }
+
+            rt_kprintf("received advertisement; event_type=%d rssi=%d addr_type=%d addr=",
+                                                                    disc_desc->discov_type,
+                                                                    disc_desc->rssi,
+                                                                    disc_desc->addr_type);
+            rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x\n", disc_desc->addr[5], disc_desc->addr[4],
+                                                          disc_desc->addr[3], disc_desc->addr[2],
+                                                          disc_desc->addr[1], disc_desc->addr[0]);
+            rt_kprintf("mfg_data = ");
+            for (int i = 0; i < disc_desc->length_data; i++)
+            {
+                rt_kprintf("%02x ", dicover_data[i]);
+            }
+            rt_kprintf("\n\n");
+            break;
+        }
+        case RW007_BLE_NTF_TYPE_CONNECT:
+        {
+            struct rw007_ble_gap_event_connect *connect_event;
+            struct rw007_ble_conn_desc *conn_desc;
+
+            rt_kprintf("RW007_BLE_NTF_TYPE_CONNECT\n");
+
+            connect_event = (struct rw007_ble_gap_event_connect *)data;
+            conn_desc = (struct rw007_ble_conn_desc*)(connect_event + 1);
+
+            rt_kprintf("connect event status: %d, conn_handle: %d\n", connect_event->status, connect_event->conn_handle);
+            rt_kprintf("our_id_type:%d our_id_addr: ", conn_desc->our_id_type);
+            _print_addr(conn_desc->our_id_addr);
+            rt_kprintf("\npeer_id_type:%d peer_id_addr: ", conn_desc->peer_id_type);
+            _print_addr(conn_desc->peer_id_addr);
+            rt_kprintf("\nconn_itv:%d, conn_latency:%d, conn_suptout:%d, role:%d\n", conn_desc->conn_itvl,
+                                conn_desc->conn_latency, conn_desc->supervision_timeout, conn_desc->role);
+            break;
+        }
+        case RW007_BLE_NTF_TYPE_DISCONN:
+            rt_kprintf("RW007_BLE_NTF_TYPE_DISCONN\n");
+            break;
+        case RW007_BLE_NTF_TYPE_MTU_EXCHANGE:
+            rt_kprintf("RW007_BLE_NTF_TYPE_MTU_EXCHANGE\n");
+            break;
+        case RW007_BLE_NTF_TYPE_DISC_COMPLETE:
+            rt_kprintf("RW007_BLE_NTF_TYPE_DISC_COMPLETE\n");
+            break;
+        case RW007_BLE_NTF_TYPE_ADV_COMPLETE:
+            rt_kprintf("RW007_BLE_NTF_TYPE_ADV_COMPLETE\n");
+            break;
+        case RW007_BLE_NTF_TYPE_SUBSCRIBE:
+            rt_kprintf("RW007_BLE_NTF_TYPE_SUBSCRIBE\n");
+            break;
+        case RW007_BLE_NTF_TYPE_NOTIFY_RX:
+        {
+            struct rw007_ble_gap_event_notify_rx *notify_rx;
+
+            rt_kprintf("RW007_BLE_NTF_TYPE_NOTIFY_RX\n");
+
+            notify_rx = (struct rw007_ble_gap_event_notify_rx *)data;
+            rt_kprintf("conn_handle:%d, attr_handle:%d, rcv (%s) length:%d, data:\n",
+                    notify_rx->conn_handle, notify_rx->attr_handle,
+                    notify_rx->indication ? "indication":"notification", notify_rx->length_data);
+            hex_dump((const rt_uint8_t *)(notify_rx + 1), notify_rx->length_data);
+            break;
+        }
+        default:
+            rt_kprintf("error notify\n");
+            break;
+    }
+}
+
+static int ble_cmd_init(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+
+    rt_uint8_t roles = 0;
+    if(argc < 3)
+        return -1;
+
+    if (rt_strcmp("central", argv[2]) == 0)
+    {
+        rt_kprintf("start ble central\n");
+        roles = RW007_BLE_INIT_ROLE_CENTRAL;
+    }
+    else if(rt_strcmp("Peripheral", argv[2]) == 0)
+    {
+        rt_kprintf("start ble Peripheral\n");
+        roles = RW007_BLE_INIT_ROLE_PERIPHERAL;
+    }
+    else
+    {
+        return -1;
+    }
+    rw007_ble_init(roles);
+
+    rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle);
+    rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle);
+    return 0;
+}
+
+static int ble_cmd_get_addr(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+
+    rw007_ble_addr_get();
+    return 0;
+}
+
+static int ble_cmd_get_connect_info(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    // rw007_ble_conn_info_get(connect_event.connect.conn_handle);
+    return 0;
+}
+
+static int ble_cmd_update_params(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    // struct rw007_ble_conn_update_params params;
+
+    /* TODO */
+
+    // rw007_ble_conn_update_params(connect_event.connect.conn_handle, &params);
+    return 0;
+}
+
+static int ble_cmd_scan(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    struct rw007_ble_scan_params scan_param;
+
+    scan_param.limited = 0;
+    scan_param.passive = 0;
+    scan_param.filter = 0; // 0 disable /1 wl /2 inta /3 1+2
+    scan_param.duration = 3000;
+    scan_param.interval = 0;
+    scan_param.window = 0;
+
+    rw007_ble_scan(&scan_param);
+    return 0;
+}
+
+static int ble_cmd_stop_scan(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    rw007_ble_scan_stop();
+    return 0;
+}
+
+static int ble_cmd_connect(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    ble_addr_t addr;
+
+    addr.type = RW007_BLE_ADDR_PUBLIC;
+
+    rt_kprintf("str_addr: %s\n", argv[2]);
+
+    _hexstrtoaddr(argv[2], addr.val);
+
+    rt_kprintf("mac addr: %2x:%2x:%2x:%2x:%2x:%2x\n", addr.val[0], addr.val[1],
+                                                      addr.val[2], addr.val[3],
+                                                      addr.val[4], addr.val[5]);
+
+    rw007_ble_connect(&addr);
+    return 0;
+}
+
+static int ble_cmd_disconnect(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    rt_uint16_t conn_handle = 0;
+    conn_handle = atoi(argv[2]);
+
+    rw007_ble_disconnect(conn_handle);
+
+    return 0;
+}
+
+static int ble_cmd_gattc_service_get(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    // rw007_ble_gatt_discover_full(connect_event.connect.conn_handle);
+    return 0;
+}
+
+static int ble_cmd_gattc_characteristic_get(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    return 0;
+}
+
+static int ble_cmd_gattc_discriptor_get(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    // rw007_ble_mtu_exchange(connect_event.connect.conn_handle);
+    return 0;
+}
+
+static int ble_cmd_mtu_exchange(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    return 0;
+}
+
+static int ble_cmd_gatt_notify_change(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    return 0;
+}
+
+static int ble_cmd_gattc_write(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    return 0;
+}
+
+static int ble_cmd_gattc_read(int argc, char *argv[])
+{
+    rt_kprintf("%d - %s\n", __LINE__, __FUNCTION__);
+    return 0;
+}
+
+static int ble_cmd_gatt_notify_change_by_uuid(int argc, char *argv[])
+{
+    uint16_t conn_handle;
+    uint32_t uuidint;
+    rw007_ble_uuid_t uuid;
+    int rc;
+    int value;
+    int uuidlen;
+
+    if (argc < 5)
+    {
+        rt_kprintf("argc < 5\n");
+        return -1;
+    }
+
+    conn_handle = atoi(argv[2]);
+
+    uuidlen = strlen(argv[3]);
+
+    if (4 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_16;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid16 = uuidint & 0xFFFFu;
+    }
+    else if (8 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_32;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid32 = uuidint & 0xFFFFFFFFu;
+    }
+    else if (32 == uuidlen) {
+        int i;
+
+        uuid.type = BLE_UUID_TYPE_128;
+        for (i = 0; i < 16; i++) {
+            sscanf(&argv[3][i * 2], "%02x", &uuidint);
+            uuid.uuid.uuid128[15 - i] = uuidint & 0xFFu;
+        }
+    }
+    else {
+        rt_kprintf("uuid:%s input error\n", argv[3]);
+        return -1;
+    }
+
+    value = atoi(argv[4]);
+    rt_kprintf("notifychange conn_hanle:%d uuid:%s value:%02x\n", conn_handle, argv[3], value);
+
+    rc = rw007_ble_gatt_notify_change_by_uuid(conn_handle, &uuid, value);
+
+    rt_kprintf("notifychange rc:%d\n", rc);
+    return rc;
+}
+
+static int ble_cmd_gattc_write_by_uuid(int argc, char *argv[])
+{
+    uint16_t conn_handle;
+    uint32_t uuidint;
+    rw007_ble_uuid_t uuid;
+    int rc;
+    int uuidlen;
+    int value_len;
+    int i;
+    uint8_t *value;
+
+    if (argc < 5) {
+        rt_kprintf("argc < 5\n");
+        return -1;
+    }
+
+    conn_handle = atoi(argv[2]);
+
+    uuidlen = strlen(argv[3]);
+
+    if (4 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_16;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid16 = uuidint & 0xFFFFu;
+    }
+    else if (8 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_32;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid32 = uuidint & 0xFFFFFFFFu;
+    }
+    else if (32 == uuidlen) {
+        int i;
+
+        uuid.type = BLE_UUID_TYPE_128;
+        for (i = 0; i < 16; i++) {
+            sscanf(&argv[3][i * 2], "%02x", &uuidint);
+            uuid.uuid.uuid128[15 - i] = uuidint & 0xFFu;
+        }
+    }
+    else {
+        rt_kprintf("uuid:%s input error\n", argv[3]);
+        return -1;
+    }
+
+    value_len = strlen(argv[4]) / 2;
+    value = rt_malloc(value_len);
+    if (!value) {
+        rt_kprintf("value parse failure\n");
+        return -1;
+    }
+    rt_kprintf("data:");
+    for (i = 0; i < value_len; i++) {
+        sscanf(&argv[4][i * 2], "%02x", &uuidint);
+        value[i] = uuidint & 0xFFu;
+        rt_kprintf(" %02x", value[i]);
+    }
+    rt_kprintf("\n");
+
+    rt_kprintf("write conn_hanle:%d uuid:%s\n", conn_handle, argv[3]);
+
+    rc = rw007_ble_gattc_write_by_uuid(conn_handle, &uuid, value, value_len);
+    rt_free(value);
+    rt_kprintf("write rc:%d\n", rc);
+    return rc;
+}
+
+static int ble_cmd_gattc_read_by_uuid(int argc, char *argv[])
+{
+    uint16_t conn_handle;
+    uint32_t uuidint;
+    rw007_ble_uuid_t uuid;
+    int rc;
+    int uuidlen;
+
+    if (argc < 4)
+    {
+        rt_kprintf("argc < 4\n");
+        return -1;
+    }
+
+    conn_handle = atoi(argv[2]);
+
+    uuidlen = strlen(argv[3]);
+
+    if (4 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_16;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid16 = uuidint & 0xFFFFu;
+    }
+    else if (8 == uuidlen) {
+        uuid.type = BLE_UUID_TYPE_32;
+        sscanf(argv[3], "%x", &uuidint);
+        uuid.uuid.uuid32 = uuidint & 0xFFFFFFFFu;
+    }
+    else if (32 == uuidlen) {
+        int i;
+
+        uuid.type = BLE_UUID_TYPE_128;
+        for (i = 0; i < 16; i++) {
+            sscanf(&argv[3][i * 2], "%02x", &uuidint);
+            uuid.uuid.uuid128[15 - i] = uuidint & 0xFFu;
+        }
+    }
+    else {
+        rt_kprintf("uuid:%s input error\n", argv[3]);
+        return -1;
+    }
+
+    rt_kprintf("read conn_hanle:%d uuid:%s\n", conn_handle, argv[3]);
+
+    rc = rw007_ble_gattc_read_by_uuid(conn_handle, &uuid);
+
+    rt_kprintf("read rc:%d\n", rc);
+    return rc;
+}
+
+static int ble_cmd_cfgwifi(int argc, char *argv[])
+{
+    int32_t duration_ms;
+
+    if (argc != 3) return -1;
+
+    duration_ms = atoi(argv[2]);
+
+    // duration_ms == 0 by used default 60second;
+    if (duration_ms < 0) return -2;
+
+    return rw007_ble_cfgwifi(duration_ms);
+}
+
+static int rw007_ble_msh(int argc, char *argv[])
+{
+    int i, result = 0;
+    const struct ble_cmd_des *run_cmd = RT_NULL;
+
+    if (argc == 1)
+    {
+        ble_cmd_help(argc, argv);
+        return 0;
+    }
+
+    /* find fun */
+    for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[0]); i++)
+    {
+        if (rt_strcmp(cmd_tab[i].cmd, argv[1]) == 0)
+        {
+            run_cmd = &cmd_tab[i];
+            break;
+        }
+    }
+
+    /* not find fun, print help */
+    if (run_cmd == RT_NULL)
+    {
+        ble_cmd_help(argc, argv);
+        return 0;
+    }
+
+    /* run fun */
+    if (run_cmd->fun != RT_NULL)
+    {
+        result = run_cmd->fun(argc, argv);
+    }
+
+    if (result)
+    {
+        ble_cmd_help(argc, argv);
+    }
+    return 0;
+}
+
+#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
+FINSH_FUNCTION_EXPORT_ALIAS(rw007_ble_msh, __cmd_rw007_ble, ble command.);
+#endif

+ 370 - 0
src/spi_ble_rw007.c

@@ -0,0 +1,370 @@
+#include "spi_ble_rw007.h"
+#include "spi_wifi_rw007.h"
+
+struct ble_gap_event connect_event;
+struct ble_gap_conn_desc connect_desc;
+
+rw007_ble_resp_handle_cb resp_handle_cb;
+rw007_ble_ntf_handle_cb ntf_handle_cb;
+
+#define BLE_DISPATCH_MAILBOX_NUM    10
+static struct rt_mailbox _ble_dispatch_mb;
+static rt_uint32_t _ble_dispatch_mb_buffer[BLE_DISPATCH_MAILBOX_NUM];
+#define BLE_DISPATCH_TASK_STACK_SIZE    512
+static rt_uint32_t _ble_dispatch_task_stack[BLE_DISPATCH_TASK_STACK_SIZE / 4];
+static struct rt_thread _ble_dispatch_task_obj;
+
+void rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle_cb resp_cb)
+{
+    resp_handle_cb = resp_cb;
+}
+
+void rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle_cb notify_cb)
+{
+    ntf_handle_cb = notify_cb;
+}
+
+static void rw007_ble_data_input(void *buff, int len)
+{
+    struct rw007_ble_resp *resp = RT_NULL;
+    rt_uint8_t *pos = (rt_uint8_t *)buff;
+    int msglen;
+
+    while (len > 0)
+    {
+        void *pmsgobj;
+
+        resp = (struct rw007_ble_resp *)pos;
+
+        msglen = member_offset(struct rw007_ble_resp, data) + resp->len;
+        pmsgobj = rt_malloc(msglen);
+        if (pmsgobj != NULL)
+        {
+            rt_err_t err;
+
+            memcpy(pmsgobj, resp, msglen);
+
+            err = rt_mb_send(&_ble_dispatch_mb, (rt_ubase_t)pmsgobj);
+            if (err != RT_EOK)
+            {
+                rt_free(pmsgobj);
+                rt_kprintf("ble data input blocking, lost packet type:%d, len:%d\n", resp->resp_type, resp->len);
+            }
+            else
+            {
+                rt_kprintf("ble data input packet resp_type: %d, len: %d\n", resp->resp_type, resp->len);
+            }
+        }
+        else
+        {
+            rt_kprintf("ble data input malloc failure, lost packet type:%d, len:%d\n", resp->resp_type, resp->len);
+        }
+
+        len -= msglen;
+        pos += msglen;
+    }
+}
+
+static void rw007_ble_data_output(void *buff, int len)
+{
+    rw007_ble_send_data(buff, len);
+}
+
+int rw007_ble_init(rt_uint8_t roles)
+{
+    rt_uint32_t len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_INIT;
+    req.value.int_value = roles;
+    req.len = sizeof(rt_uint32_t);
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+
+    return RT_EOK;
+}
+
+int rw007_ble_addr_get(void)
+{
+    rt_uint32_t len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_ADDR_GET;
+    req.len = 0;
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+
+    return RT_EOK;
+}
+
+int rw007_ble_conn_info_get(rt_uint16_t conn_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_conn_update_params(rt_uint16_t conn_handle, struct ble_gap_upd_params *params)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_central_init(void)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_scan(struct rw007_ble_scan_params *scan_param)
+{
+    rt_uint32_t len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_SCAN;
+    req.len = sizeof(struct rw007_ble_scan_params);
+    rt_memcpy((void *)req.value.bytes, (const void *)scan_param, req.len);
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+    return RT_EOK;
+}
+
+int rw007_ble_scan_stop(void)
+{
+    rt_uint32_t len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_STOP_SCAN;
+    req.len = 0;
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+    return RT_EOK;
+}
+
+int rw007_ble_connect(ble_addr_t *addr)
+{
+    int len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_CONNECT;
+    rt_memcpy((void *)&req.value.addr, (const void *)addr, sizeof(ble_addr_t));
+    req.len = sizeof(ble_addr_t);
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+
+    return RT_EOK;
+}
+
+int rw007_ble_disconnect(rt_uint16_t conn_handle)
+{
+    rt_uint32_t len;
+
+    struct rw007_ble_req req;
+
+    req.req_type = RW007_BLE_REQ_TYPE_DISCONN;
+    req.value.int_value = conn_handle;
+    req.len = sizeof(rt_uint32_t);
+
+    len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, len);
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_service_get(rt_uint16_t conn_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_characteristic_get(rt_uint16_t conn_handle, rt_uint16_t attr_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_discriptor_get(rt_uint16_t conn_handle, rt_uint16_t attr_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_service_discover(rt_uint16_t conn_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_mtu_exchange(rt_uint16_t conn_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gatt_notify_change(rt_uint16_t attr_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_write(rt_uint16_t conn_handle, rt_uint16_t attr_handle, const rt_uint8_t *buf, rt_uint16_t len)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_read(rt_uint16_t conn_handle, rt_uint16_t attr_handle)
+{
+    return RT_EOK;
+}
+
+int rw007_ble_gatt_notify_change_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid, rt_uint16_t value)
+{
+    int req_len;
+    struct rw007_ble_req req;
+    struct rw007_ble_notify_change_by_uuid notify_change;
+
+    notify_change.conn_handle = conn_handle;
+    notify_change.char_value = value;
+    notify_change.uuid = *uuid;
+
+    req.req_type = RW007_BLE_REQ_TYPE_NOTIFYCHANGE_BY_UUID;
+    req.len = sizeof(struct rw007_ble_notify_change_by_uuid);
+    rt_memcpy((void *)&req.value.notify_change, (const void *)&notify_change, req.len);
+
+    req_len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, req_len);
+
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_write_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid, const rt_uint8_t *buf, rt_uint16_t len)
+{
+    int req_len;
+    struct rw007_ble_req req;
+    struct rw007_ble_write_by_uuid *write = RT_NULL;
+
+    write = (struct rw007_ble_write_by_uuid *)rt_malloc(sizeof(struct rw007_ble_write_by_uuid) + len);
+
+    if (write == RT_NULL)
+    {
+        return -1;
+    }
+
+    write->conn_handle = conn_handle;
+    write->data_len = len;
+    write->uuid = *uuid;
+    rt_memcpy(write->data, buf, write->data_len);
+
+    req.req_type = RW007_BLE_REQ_TYPE_WRITE_BY_UUID;
+    req.len = sizeof(struct rw007_ble_write_by_uuid) + write->data_len;
+    rt_memcpy((void *)&req.value.bytes, (const void *)write, req.len);
+
+    req_len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, req_len);
+
+    rt_free(write);
+    write = RT_NULL;
+    return RT_EOK;
+}
+
+int rw007_ble_gattc_read_by_uuid(rt_uint16_t conn_handle, const rw007_ble_uuid_t *uuid)
+{
+    int req_len;
+    struct rw007_ble_req req;
+    struct rw007_ble_read_by_uuid *read_req;
+
+    read_req = (struct rw007_ble_read_by_uuid *)rt_malloc(sizeof(struct rw007_ble_read_by_uuid));
+    if (read_req == RT_NULL)
+    {
+        return -1;
+    }
+
+    read_req->conn_handle = conn_handle;
+    read_req->reserved = 0;
+    read_req->uuid = *uuid;
+    req.req_type = RW007_BLE_REQ_TYPE_READ_BY_UUID;
+    req.len = sizeof(struct rw007_ble_read_by_uuid);
+    rt_memcpy((void *)&req.value.bytes, (const void *)read_req, req.len);
+    req_len = member_offset(struct rw007_ble_req, value) + req.len;
+
+    rw007_ble_data_output((void *)&req, req_len);
+    rt_free(read_req);
+
+    return RT_EOK;
+}
+
+static void _ble_dispatch_task(void *parameter)
+{
+    for (;;)
+    {
+        rt_err_t err;
+        rt_ubase_t pmsgobj = 0;
+        struct rw007_ble_resp *resp = RT_NULL;
+
+        err = rt_mb_recv(&_ble_dispatch_mb, &pmsgobj, RT_WAITING_FOREVER);
+        if (err != RT_EOK) continue;
+
+        resp = (struct rw007_ble_resp *)pmsgobj;
+
+        if(resp->resp_type == RW007_BLE_RESP_TYPE_CMD)
+        {
+            if(resp_handle_cb)
+            {
+                resp_handle_cb(resp->cmd, resp->data, resp->len);
+            }
+        }
+        else if(resp->resp_type == RW007_BLE_RESP_TYPE_NOTIFY)
+        {
+            if(ntf_handle_cb)
+            {
+                ntf_handle_cb(resp->cmd, resp->data, resp->len);
+            }
+        }
+
+        rt_free(resp);
+    }
+}
+
+static int _ble_dispatch_init(void)
+{
+    rt_err_t err;
+
+    err = rt_mb_init(&_ble_dispatch_mb,
+                    "bledp",
+                    _ble_dispatch_mb_buffer,
+                    BLE_DISPATCH_MAILBOX_NUM,
+                    RT_IPC_FLAG_PRIO);
+    if (err != RT_EOK) {
+        rt_kprintf("ble dispatch mailbox init failure\n");
+        return err;
+    }
+
+    err = rt_thread_init(&_ble_dispatch_task_obj,
+                        "bledp",
+                        _ble_dispatch_task, 0,
+                        &_ble_dispatch_task_stack,
+                        BLE_DISPATCH_TASK_STACK_SIZE,
+                        10, 10);
+    if (err != RT_EOK) {
+        rt_kprintf("ble dispatch task init failure\n");
+        return err;
+    }
+
+    err = rt_thread_startup(&_ble_dispatch_task_obj);
+    return err;
+}
+
+static int rw007_spi_ble_init(void)
+{
+    rw007_ble_recv_data_func_reg(rw007_ble_data_input);
+
+    return _ble_dispatch_init();
+}
+INIT_APP_EXPORT(rw007_spi_ble_init);