Explorar o código

[add]bsal pkg

yangjie %!s(int64=4) %!d(string=hai) anos
pai
achega
f889baac1f

+ 66 - 2
README.md

@@ -1,2 +1,66 @@
-# bsal
-蓝牙协议栈抽象层
+# BSAL
+
+## 1.  BSAL 软件包介绍
+
+BSAL (Bluetooth Stack Abstract Layer)软件包是由 RT-Thread 针对不同 蓝牙协议栈接口实现的,目前支持的 协议栈有:nimble,realtek等协议栈 。
+
+### 1.1 背景介绍
+
+Bluetooth Stack Abstract Layer 蓝牙协议栈抽象层。用于适配各家协议栈以及底层卡片。
+
+主要在协议栈基础之上封装一层抽象层接口。
+
+# 2. BSAL 使用说明
+
+BSAL 配置如下图所示:
+
+![img](./doc/figures/menuconfig.png)
+
+选择需要生成的角色(默认选择Peripheral即可):
+
+- Peripheral role:       
+- Central role
+- Broadcaster role
+- Observer role
+
+选择不同的示例可以实现不同的APP功能:
+
+- Battery service     单battery servcie 测试sample
+- battery and blufi service  两个profile servic(blufi 配网, bas)测试sample
+
+再选择对应的协议栈:
+
+- nimble   (nimble 协议栈适配层)
+- realtek  (realtek 协议栈适配层)
+- empty_stack   (移植协议栈模板)
+
+# 3. BSAL 依赖
+
+BSAL 依赖对应的协议栈,比如nimble,需要先有nimble+RTT的sample工程,首先确保可以跑对应协议栈的原生的sample。再试着添加BSAL层跑sample
+
+每个sample对应一个cmd:
+
+- battery service: bsal_bas_app
+- battery and blufi service: bsal_bas_blufi_app
+
+输入对应的cmd即可
+
+# 4. 测试验证工具
+
+输入cmd bsal_bas_blufi_app 启动sample
+
+手机下载nRF Connect 工具(apple使用lightblue)
+
+[nRF Connect](https://github.com/NordicSemiconductor/Android-nRF-Connect/releases)
+
+搜索广播看到如下界面
+
+![image-20200618164034578](./doc/figures/adv.png)
+
+点击connect连接上之后:
+
+![image-20200618164126725](./doc/figures/srv_table.png)
+
+可以看到battery service和0xffff配网blufi service
+
+说明sample运行成功。

+ 63 - 0
SConscript

@@ -0,0 +1,63 @@
+from building import *
+import rtconfig
+
+cwd = GetCurrentDir()
+path = [cwd]
+src = []
+
+path += [
+    cwd + '/inc']
+
+# Host stack
+src += Split('''
+    src/bsal.c
+    ''')
+
+if GetDepend(['PKG_BSAL_SRV_BAS']):
+	path += [cwd + '/profiles/service/basl_bas']
+	src += Split("""
+		profiles/service/basl_bas/bsal_srv_bas.c
+		""")
+		
+if GetDepend(['PKG_BSAL_SRV_BLUFI']):
+	path += [cwd + '/profiles/service/bsal_blufi']
+	src += Split("""
+		profiles/service/bsal_blufi/bsal_srv_blufi.c
+		""")
+		
+if GetDepend(['PKG_BSAL_SAMPLE_BAS_ONLY']):
+	src += Split("""
+		samples/ble_bas_only_app.c
+		""")
+elif GetDepend(['PKG_BSAL_SAMPLE_BAS_BLUFI_COMBINE']):
+    src += Split("""
+		samples/ble_bas_blufi_app.c
+		""")
+
+		
+if GetDepend(['PKG_BSAL_NIMBLE_STACK']):
+	path += [cwd + '/port/nimble']
+	src += Split("""
+		port/nimble/bsal_nimble.c
+		port/nimble/bsal_osif.c
+		""")
+		
+elif GetDepend(['PKG_BSAL_RTK_STACK']):
+	path += [cwd + '/port/realtek']
+	src += Split("""
+		port/realtek/bsal_rtk.c
+		port/realtek/bsal_osif.c
+		""")
+		
+elif GetDepend(['PKG_BSAL_EMPTY_STACK']):
+	path += [cwd + '/port/empty_stack']
+	src += Split("""
+		port/empty_stack/bsal_osal_empty.c
+		port/empty_stack/bsal_stack_empty.c
+		""")
+	
+LOCAL_CCFLAGS = ''
+    
+group = DefineGroup('bsal', src, depend = ['PKG_USING_BSAL'], CPPPATH = path, LOCAL_CCFLAGS = LOCAL_CCFLAGS)
+
+Return('group')

+ 435 - 0
doc/RT-Thread BSAL软件包介绍及移植指南.md

@@ -0,0 +1,435 @@
+
+
+# RT-Thread BSAL软件包介绍及移植指南
+
+## 1.  BSAL 软件包介绍
+
+BSAL (Bluetooth Stack Abstract Layer)软件包是由 RT-Thread 针对不同 蓝牙协议栈接口实现的,目前支持的 协议栈有:nimble,realtek等协议栈 。
+
+### 1.1 背景介绍
+
+Bluetooth Stack Abstract Layer 蓝牙协议栈抽象层。用于适配各家协议栈以及底层卡片。
+
+主要在协议栈基础之上封装一层抽象层接口。
+
+#### 1.1.1 具体问题介绍
+
+- 各家厂商都有自己独有的协议栈,协议栈接口之间不通用。
+- 根据SIG标准的profile,各家都基于自家协议栈实现代码,工作量比较大而不通用。
+- 基于ble profile的代码,大部分厂家的代码都是开放的。
+- BLE GATT的操作比较统一,适合整合成一套统一的接口。
+- GAP抽象接口行为一致,但各家接口都不统一
+- 各家的profile和ble相关的app代码只能适配自家代码
+- 基于开源协议栈的接口,也不够通用
+
+基于这些问题,我们推出BSAL层接口,为了兼容多家MCU的协议栈和方便后续拓展性。
+
+### 1.2 应用场景
+
+#### 1.2.1 应用场景框架
+
+针对该接口的使用场景,总结出以下几个应用场景:
+
+- 点对点自定义协议栈蓝牙GATT透传自定义协议(这种profile自定义,只需要数据传输过去即可,完成数据收发)通常作为service端。
+- 基于BLE 标准PROFILE的SIG sample(比如:心率计(HRS), HID设备(HOGP), 设备信息(DIS),电池服务(BAS)通常作为service端, central端比较少,通常central为手机。
+- 基于PB-ADV的MESH协议栈,通常作为broadcaster, observer
+- blufi 配网 对于特定的带有WIFI模块的芯片
+- MCU + BT SOC通信调用,BT SOC作为BSAL层的执行端,MCU作为BSAL的发起端
+
+#### 1.2.2 应用产品
+
+基于上面的API,可以开发出对应的蓝牙应用产品:
+
+- 电子名片(可以用于手机编辑,以及WIFI配网,IOT控制LED小灯等操作)
+- 手机微信小程序控制小车(作为遥控器,控制带有ble的小车系统),作为一个遥控器来控制,可以不用依赖红外那种指向性的,比WIFI省电。
+- 蓝牙遥控器。手机小程序有遥控器界面,来控制带有USB设备的电脑,电视以及等等设备,用蓝牙模拟HID设备。解决的痛点主要是经常遥控器断电,遥控器找不到了。
+- 蓝牙小键盘。带USB的两颗蓝牙卡片,一个做成小键盘,一个做成USB HID device
+- 蓝牙pos机,基于自定义透传协议。
+- 阿里mesh智能家居小灯等设备。
+- micropython对应的python ubluetooth应用。
+- MCU + BT_soc 轻量级的控制的场景
+- 智能穿戴BLE操作,后续会考虑支持BR/EDR的接口操作
+- 智能音响,mesh,A2DP,HFP,ble
+- 自行车码表
+
+### 1.3 软件包的介绍
+
+BSAL作为一层通用层,隔开app和stack之间的接口。因为要尽量兼容各家协议栈的不同类型的接口,所以需要一些额外的开支。当然这个可以在进一步的迭代过程中逐步优化。
+
+#### 1.3.1 框架介绍
+
+![BAL 系统框架图](./figures/bal_framework.jpg)
+
+#### 1.3.2 主要功能介绍
+
+##### 1.3.2.1 适配性
+
+可以适配大部分的厂商的蓝牙协议栈接口,如果接口不适配,也有冗余接口进行拓展适配。
+
+当然如果没有协议栈,可以使用nimble+RTT的方式进行HCI 层对接适配,也是可以使用BSAL上层的接口的。
+
+##### 1.3.2.2 可移植性
+
+可以方便移植到不同平台,BSAL层尽量做到能适配大部分的BLE STACK平台,只做上层逻辑的接口的优化和实现,并不针对某个特定的硬件或者协议栈。
+
+#### 1.3.3 目录结构
+
+BSAL目录结构:
+
+```
+├───docs                      // 相关文档
+├───inc                       // 组件头文件
+│    ├───bsal.h               // bsal总头文件
+│    ├───bsal_app_api.h       // bsalAPP和profile需要调的API接口
+│    ├───bsal_common.h        // bsal通用结构体定义
+│    ├───bsal_int.h           // bsal移植协议栈需要了解的接口
+│    ├───bsal_sig.h           // bsal中根据SIG规定的接口和标准值
+│    ├───bsal_stack_api.h     // bsal协议栈接口API
+│    └───bsal_osif.h          // bsal调用到的OS相关的接口
+├───port                      // 移植适配文件
+│    ├───empty_stack          // 空协议栈平台(给第一次移植需要使用的空模板)
+│    ├───realtek              // REALTEK协议栈适配文件
+│    └───nimble               // NIMBLE协议栈适配源文件
+├───src     
+│    └───bsal.c               //将stack接口封装一层,供profile调用
+├───profile                   // 各种 蓝牙 profile 文件
+│    ├───client               // profile作为主机端的操作源文件
+│    ├───service              // profile作为service端的操作源文件
+│        ├───basl_bas         // battery service 源文件头文件
+│              ├───bsal_srv_bas.h    // bas service 头文件
+│              └───bsal_srv_bas.c    // bas service 源文件
+│        ├───bsal_blufi              // blufi 蓝牙wifi配网
+│              ├───bsal_srv_blufi.h    // bas service 头文件
+│              └───bsal_srv_blufi.c    // bas service 源文件
+├───sample    
+│    ├───ble_bas_only_app.c   // 只有battery servcie的源文件
+│    └───ble_bas_blufi_app.c  // 带有bas和blufi两个profile的源文件
+├───README.md                 //
+└───SConscript                //软件包scons脚本
+```
+
+
+
+#### 1.3.4 配置选项
+
+BSAL 组件配置:
+
+```
+[*] BSAL: The Bluetooth Stack Abstract Layer 
+[ ] Bluetooth Role support --->                         // BLE 支持角色
+[*]      Peripheral role             // perpheral 角色
+[ ]      Central Role                // central 角色
+[ ]      Broadcaster Role            // broadcaster 角色
+[ ]      Observer Role               // Observer role
+(1)     The maximum link of supported ble link          // BLE 最大link数
+[ ]     Bluetooth sample ---->                          // sample
+[ ]                 BLE peripheral                      
+[ ]                   ble battery service sample        // ble battery service sample
+[ ]                   ble bluefi sample                 // ble 配网 sample
+[ ] BSAL STACK SELECT--->                               // 单选
+            ()         RTK                              // 支持realtek的协议栈
+            ()         Nordic softdevice                // 支持nordic的协议栈
+            ()         NIMBLE                           // 支持nimble开源协议栈
+```
+
+配置选项可以选择不同协议栈、不同profile service的支持,以及角色的支持
+
+#### 1.3.5 API接口介绍
+
+API接口主要分为两部分,一部分对于用户来讲,写APP和profile需要知道的接口。还有一部分对于协议栈和蓝牙卡片来讲,需要实现的接口。
+
+##### 1.3.5.1 APP用户接口介绍
+
+对于 用户APP和profile来言,需要了解协议栈初始化接口,以及
+
+````c
+//1. STACK API  应用层调用
+/* stack 根据name 找到stack指针*/
+void *bsal_find_stack_ptr(char *stack_name);
+
+/* stack 初始化,并注册协议栈的callback函数 */
+int bsal_stack_init(void *stack_ptr, void *callback);
+
+/* stack 开始注册profile service , 并注册通用profile的回调函数*/
+void bsal_stack_le_srv_begin(void *stack_ptr, uint8_t num, void *p_fun_cb);
+
+/* stack 结束注册profile service*/
+void bsal_stack_le_srv_end(void *stack_ptr);
+
+/* stack 开始运行*/
+void bsal_stack_startup(void *stack_ptr);
+
+//2. SERVICE API
+/* profile 注册自己的service table,并注册回调函数*/
+typedef BSAL_STATUS(*P_SRV_GENERAL_CB)(void *p_para);
+int  bsal_stack_le_srv_reg_func(void *stack_ptr, void *srv_def, P_SRV_GENERAL_CB *callback);
+
+//3. SERVICE SEND DATA
+/* service 发送NOTIFY数据 */
+int bsal_srv_send_notify_data(void *stack_ptr, uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+
+int bsal_srv_send_ind_data(void *stack_ptr, uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+
+````
+
+#### 1.3.6 使用说明(BLE 流程 for APP)
+
+##### 1.3.6.1 广播使用流程
+
+对于peripheral而言,首先需要打广播
+
+广播样例代码如下:
+
+```c
+//1. 申请一个32byte的数组,用于存放广播内容
+uint8_t tmp_data[32] = {0} ; //must be zero
+//2. 添加广播中的flag
+bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED);
+//3. 添加广播中的名字
+char *adv_name = "rtt_ble";
+bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name);
+//4. 添加广播中的服务内容
+bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE);
+//5. 设置广播内容
+bsal_set_le_adv_data_user(stack_ptr, tmp_data);
+//6. 开始广播
+bsal_stack_start_adv(stack_ptr);
+```
+
+##### 1.3.6.2 profile service 的TX RX使用流程
+
+了解TX RX需要知道一个相对handle和绝对handle。
+
+绝对handle是该ATT在整个project中的绝对地址,BSAL存储的是绝对地址,该地址是惟一的。profile处理的是相对handle,该handle是相对于profile的相对偏移,off_handle就是相对偏移,u_handle就是绝对偏移,
+
+只要保证u_handle唯一即可,这个需要根据 协议栈的callback的接口来定位。
+
+-  service READ REQUEST操作
+
+手机或者central给service 发送READ 数据的时候,以nimble为例
+
+原生stack先唤醒nimble中的回调函数:
+
+```
+nimble_chrs[x].access_cb = bsal_ble_svc_bas_access;
+```
+
+bsal_ble_svc_bas_access这个函数处理的事件:
+
+BLE_GATT_ACCESS_OP_READ_CHR:
+
+这个时候,先从bsal_srv_objs service table中找到回调函数,然后先通知到profile层。
+
+profile对数据进行解析之后,判断是否要通知APP层,对端来读取数据,如果觉得不需要通知,直接返回对应的值即可。
+
+PROFILE如果对于某个值需要进行更新,调用BSAL提供的接口:
+
+```
+//这个接口主要讲数据值写入到att数据库中,方便BSAL读取该值返回给STACK
+int bsal_srv_write_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+```
+
+- service WRITE requst/cmd 操作
+
+手机或者central要给service 写入某个值的时候,以nimble为例:
+
+根据callback中的BLE_GATT_ACCESS_OP_WRITE_CHR事件,由STACK回调上来,
+这个时候,先从bsal_srv_objs service table中找到回调函数,然后先通知到profile层。
+
+PROFILE如果需要存储该值,做对应的处理即可,自行选择什么时候通知上层APP。
+
+write 本质上并没有长度上的限制,由profile决定数据该如何处理即可。
+
+- service notify 操作
+
+service 如果想要主动给client端发数据,client端必须先打开CCCD。 并且service 中的该character需要有notify这个属性。主要打开,service 才可以发数据给client端。
+
+发送调用接口:
+
+```
+int bsal_srv_send_notify_data(void *stack_ptr, uint16_t conn_id, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+```
+
+### 1.4 软件包的使用
+
+可以选择不同的 sample 做对应的 app 应用开发
+
+## 2. 移植指南
+
+### 2.1 STACK 移植接口介绍:
+
+先介绍下协议栈 object 指针内容:
+
+```c
+struct bsal_stack_obj
+{
+   /* stack 是否 ready */
+    bool                       stack_ready_flag;
+    /* stack 主要 OP 操作 */
+    bsal_stack_ops_t           bsal_ops;
+    /* att 数据库 */
+    bsal_gatt_value_entry_t   *db;
+    /* service profile 的数据库,存放 profile 的callback */
+    bsal_srv_callback_t       *bsal_srv_objs;
+
+    /* 存放 static 临时信息: */
+    bsal_stack_info_t          bsal_info;
+    /* gatt index 的handle的全局变量 */
+    uint16_t                   g_att_index;
+    /* 注册的profile的数量 */
+    uint8_t                    srv_num;
+    /* 存放APP注册的stack的回调函数 */
+    void (*app_all_callbak)(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value);
+};
+```
+
+这个结构体是贯穿整个BSAL api体系的指针接口。
+
+协议栈主要需要实现的接口是bsal_ops里面的接口,如下所示:
+
+```c
+struct bsal_stack_ops
+{
+    /* 设置LE 协议栈的参数 (预留,暂时不用实现) */
+    BSAL_STATUS(*le_set_stack_param)(uint32_t value_length, uint8_t *value);         
+    /* 获取LE 协议栈的参数 (预留,暂时不用实现) */
+    BSAL_STATUS(*le_get_stack_param)(uint32_t value_length, uint8_t *value);       
+    /* 获取MAC 地址 */
+    void (*get_mac_address)(uint8_t addr_type, uint8_t *bd_addr);                             /* 协议栈初始化 */
+    void (*init)(uint8_t stack_type);                                                         /* 协议栈启动 */
+    void (*startup)(void);                                                                   /* 设置bond 相关参数*/
+    void (*set_bond_param)(bsal_bond_param_t *value);             
+    /* 获取bond相关的参数*/
+    void (*get_bond_param)(bsal_bond_param_t *value);
+    /*设置广播 相关参数*/
+    void (*le_set_adv_param)(bsal_adv_param_t *adv_param);              
+    /* 获取广播 相关参数*/
+    void (*le_get_adv_param)(bsal_adv_param_t *adv_param);
+    /* 开始广播 */
+    BSAL_STATUS(*le_adv_enable)(bool enable);                           
+    /* 设置GAPS层的参数 */
+    void (*set_gaps_param)(bsal_gaps_param_t *gaps_param);
+    
+    /* 对于service提供的接口*/
+    /* 从相对的service id和offset_handle转换成绝对的唯一的handle*/
+    uint32_t (*cov_handle_to_u_handle)(uint16_t service_id, uint16_t offset_handle);         /* 开始注册service */
+    BSAL_STATUS(*le_srv_reg_begin)(bool is_continue, uint8_t service_num, void *p_func);
+    /* 注册service table*/
+    BSAL_STATUS(*le_srv_reg_fun)(struct bsal_gatt_app_srv_def *p_srv, void *p_func);   
+    /* 结束注册service */
+    BSAL_STATUS(*le_srv_reg_end)(void);
+    /* servcie发送数据 */
+    BSAL_STATUS(*le_srv_send_data)(uint16_t conn_handle, uint16_t service_id, uint16_t offse_handle, uint16_t value_len, const uint8_t *value, uint8_t send_type);
+    /* service 发送数据完成 (预留)*/
+    BSAL_STATUS(*send_notify_complete)(uint32_t credits);   /*TODO*/
+};
+```
+
+这边预留的接口比较多,需要实现的接口如下面介绍的接口,下面接口是必须要实现的,并且要优先实现的,其他接口可以慢慢实现。
+
+- init: 这个完成协议栈的初始化自身的初始化
+- startup: 这个接口实现协议栈开始启动的函数
+- le_srv_send_data: service 端给client端notify数据或者indicate数据。
+
+优先实现上述接口。
+
+其他接口可以按照下面的移植流程中的步骤,慢慢理解实现。
+
+需要提醒的是:对于STACK内部移植,需要了解BLE里面的GATT基本原理,需要有比较详细的了解。
+
+### 2.2 移植流程
+
+以nimble的移植为例 。
+
+#### 2.2.1 步骤一  建工程
+
+先找一个nimble的最简单的,带有battery service 一个profile操作的工程,确保手机可以搜索到battery service。并且可以连接上。最好这个工程能有RTT的支持,
+
+以nimble+nrf52840的工程为例
+
+#### 2.2.2 步骤二 加入 BSAL 移植框架,编译通过
+
+从RTT软件包里面选中BSAL软件包。
+
+![image-20200618155732239](.\figures\image-20200618155732239.png)
+
+scons 加入 empty_stack ,里面的协议栈相关的函数都已经注释掉了,编译通过。
+
+#### 2.2.3 步骤三 实现 init startup
+
+先实现ops 中的 init 和 startup 函数,确保协议栈在BSAL上面初始化和启动正常;
+
+- init :调用移植协议栈的初始化函数。(包含协议栈参数设置,广播参数,bas service 注册)
+- startup:  启动协议栈的函数。
+
+#### 2.2.4 步骤四 实现TX RX流程
+
+**功能实现**
+
+首先用原始service 的service table和adv enable
+
+- 将 gap callback 的函数放到BSAL里面
+- bas service 注册的时候,把APP的callback 通过接口bsal_profile_insert注册到BSAL数据库中
+- 在nimble的READ回调函数中,根据handle来调用对应service的回调函数bsal_srv_fn_cb
+- 在nimble的WRITE 回调中,掉对应的service的回调函数bsal_srv_fn_cb通知service
+
+完成可以read write notify等接口即可。(确保数据可以根据handle来传输即可)
+
+**功能验证**
+
+用手机nrf connect  验证TX RX
+
+【图片】
+
+#### 2.2.5 步骤四 转换profile table
+
+**功能实现**
+
+将BSAL定义的BAS TABLE数组接口:
+
+```c
+    struct bsal_gatt_app_srv_def ble_svc_bas_defs[] =
+    {
+        {
+            /*** Battery Service. */
+            .type = BSAL_GATT_UUID_PRIMARY_SERVICE,
+            .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),//(bsal_uuid_any_t *)&battery_srv,//BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),
+            .characteristics = (bsal_gatt_chr_def_t[])
+            {
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL),//(bsal_uuid_any_t *)&bas_char_bas_level,//BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL),
+                    .properties = BSAL_ATT_P_READ
+                    | BSAL_ATT_P_NOTIFY
+                    ,
+                    .permission = GATT_PERM_READ,
+                    .value_length = 1,
+                },
+                {
+                    0, /* No more characteristics in this service. */
+                }
+            },
+        },
+
+        {
+            0, /* No more services. */
+        },
+    };
+```
+
+想办法转换成nimble可以识别的接口。
+
+在函数le_srv_reg_fun中实现对应的service功能。
+
+这一步纯粹是本地代码的转换工作,确保BSAL注册的service 转换成nimble对应的service 注册进去,能够将ATT的属性等信息完全相同即可。
+
+**功能验证**
+
+先用bas service 验证,
+
+后面用blufi service 功能验证
+
+#### 2.2.5 步骤五 完善广播等其他接口
+
+这一步也是纯粹代码的转换工作,主要是将广播数据(小于32byte)设置到协议栈中去,至于如何转换,根据协议栈的接口来调用相应的接口即可。
+

BIN=BIN
doc/figures/BSAL_INTERAL.jpg


BIN=BIN
doc/figures/adv.png


BIN=BIN
doc/figures/bal_framework.jpg


BIN=BIN
doc/figures/ble_soc.jpg


BIN=BIN
doc/figures/image-20200618155732239.png


BIN=BIN
doc/figures/mcu_ble_soc.jpg


BIN=BIN
doc/figures/menuconfig.png


BIN=BIN
doc/figures/sal_framework.jpg


BIN=BIN
doc/figures/srv_table.png


+ 122 - 0
inc/bsal.h

@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#ifndef __BSAL_H__
+#define __BSAL_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define BSAL_SW_VERSION "0.1.0"
+#define BSAL_SW_VERSION_NUM 0x01000
+
+#include "bsal_sig.h"
+
+#include "bsal_common.h"
+#include "bsal_app_api.h"
+
+//CALLBACK_EVENT
+typedef enum
+{
+    BSAL_CB_LAYER_GAP = 0xF1,
+    BSAL_CB_LAYER_GATT_PROFILE,
+    BSAL_CB_LAYER_SM,
+    BSAL_CB_LAYER_COMMON,
+    BSAL_CB_LAYER_UNKNOWN
+} T_BSAL_APP_CB_LAYER_TYPE;
+
+typedef enum
+{
+    BSAL_CB_STACK_READY = 0xD1,
+    BSAL_CB_CONNECT_STATUS,
+    BSAL_CB_STACK_ERROR = 0xFF,
+} T_BSAL_GAP_SUBEVENT_TYPE;
+
+typedef enum
+{
+    BSAL_GAP_CONN_STATE_DISCONNECTED, //!< Disconnected.
+    BSAL_GAP_CONN_STATE_CONNECTING,   //!< Connecting.
+    BSAL_GAP_CONN_STATE_CONNECTED,    //!< Connected.
+    BSAL_GAP_CONN_STATE_DISCONNECTING //!< Disconnecting.
+} T_BSAL_GAP_CONN_STATE;
+
+struct bsal_gap_conn_status
+{
+    uint8_t conn_id;
+    uint8_t new_state;
+    uint16_t disc_cause;
+};
+typedef struct bsal_gap_conn_status bsal_gap_conn_status_t;
+
+typedef union
+{
+    bsal_gap_conn_status_t    gap_conn_state_change;
+} T_BSAL_GAP_MSG_DATA;
+
+
+//bit 0...3 is read permision   bit 4..7 write permission bit 8...12 notify indicate permision
+
+#define BSAL_GATT_PERM_NONE                   0x00
+#define BSAL_GATT_PERM_ALL                    0x01
+#define BSAL_GATT_PERM_AUTHEN_REQ             0x02
+#define BSAL_GATT_PERM_AUTHEN_MITM_REQ        0x03
+#define BSAL_GATT_PERM_AUTHOR_REQ             0x04  /**< bits 2 (rd), 6 (wr), 10 (notif/ind) */
+#define BSAL_GATT_PERM_ENCRYPTED_REQ          0x08  /**< bits 3 (rd), 7 (wr), 11 (notif/ind) */
+#define BSAL_GATT_PERM_AUTHEN_SC_REQ          0x09
+
+#define BSAL_GATT_PERM_READ_NONE              BSAL_GATT_PERM_NONE
+#define BSAL_GATT_PERM_READ                   BSAL_GATT_PERM_ALL
+#define BSAL_GATT_PERM_READ_AUTHEN_REQ        BSAL_GATT_PERM_AUTHEN_REQ
+#define BSAL_GATT_PERM_READ_AUTHEN_MITM_REQ   BSAL_GATT_PERM_AUTHEN_MITM_REQ
+#define BSAL_GATT_PERM_READ_AUTHOR_REQ        BSAL_GATT_PERM_AUTHOR_REQ
+#define BSAL_GATT_PERM_READ_ENCRYPTED_REQ     BSAL_GATT_PERM_ENCRYPTED_REQ
+#define BSAL_GATT_PERM_READ_AUTHEN_SC_REQ     BSAL_GATT_PERM_AUTHEN_SC_REQ
+
+#define BSAL_GATT_PERM_GET_READ(x)              (x & 0x0f)
+
+#define BSAL_GATT_PERM_WRITE_NONE              (BSAL_GATT_PERM_NONE << 4)
+#define BSAL_GATT_PERM_WRITE                   (BSAL_GATT_PERM_ALL << 4)
+#define BSAL_GATT_PERM_WRITE_AUTHEN_REQ        (BSAL_GATT_PERM_AUTHEN_REQ << 4)
+#define BSAL_GATT_PERM_WRITE_AUTHEN_MITM_REQ   (BSAL_GATT_PERM_AUTHEN_MITM_REQ << 4)
+#define BSAL_GATT_PERM_WRITE_AUTHOR_REQ        (BSAL_GATT_PERM_AUTHOR_REQ << 4)
+#define BSAL_GATT_PERM_WRITE_ENCRYPTED_REQ     (BSAL_GATT_PERM_ENCRYPTED_REQ << 4)
+#define BSAL_GATT_PERM_WRITE_AUTHEN_SC_REQ     (BSAL_GATT_PERM_AUTHEN_SC_REQ<<4)
+
+#define BSAL_GATT_PERM_GET_WRITE(x)             ((x>>4) & 0x0f)
+
+#define BSAL_GATT_PERM_NOTIFY_IND_NONE              (BSAL_GATT_PERM_NONE << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND                   (BSAL_GATT_PERM_ALL << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_REQ        (BSAL_GATT_PERM_AUTHEN_REQ << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_MITM_REQ   (BSAL_GATT_PERM_AUTHEN_MITM_REQ << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND_AUTHOR_REQ        (BSAL_GATT_PERM_AUTHOR_REQ << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND_ENCRYPTED_REQ     (BSAL_GATT_PERM_ENCRYPTED_REQ << 8)
+#define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_SC_REQ     (BSAL_GATT_PERM_AUTHEN_SC_REQ<<8)
+
+#define BSAL_GATT_PERM_GET_NOTIFY_IND(x)        ((x>>8)& 0xf)
+
+
+#define BSAL_GATT_GET_ENC_TYPE(x)                     (x & BSAL_GATT_PERM_ALL)
+#define BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(x)          (x & BSAL_GATT_PERM_AUTHEN_REQ)
+#define BSAL_GATT_GET_ENC_TYPE_AUTHEN_MITM_REQ(x)     (x & BSAL_GATT_PERM_AUTHEN_MITM_REQ)
+#define BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(x)          (x & BSAL_GATT_PERM_AUTHOR_REQ)
+#define BSAL_GATT_GET_ENC_TYPE_ENCRYPTED_REQ(x)       (x & BSAL_GATT_PERM_READ_ENCRYPTED_REQ)
+#define BSAL_GATT_GET_ENC_AUTHEN_SC_REQ(x)            (x & BSAL_GATT_PERM_READ_AUTHEN_SC_REQ)
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

+ 492 - 0
inc/bsal_app_api.h

@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#ifndef __BSAL_APP_API_H__
+#define __BSAL_APP_API_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "bsal_common.h"
+
+//0. CALLED BY STACK
+/**
+* BSAL connect status callback
+*
+* @param stack_ptr the point of the stack object
+* @param conn_handle the connect handle of link
+* @param conn_status the connection status
+* @Note  callback the connect status called by stack
+*/
+int bsal_gap_connect_status(void *stack_ptr, uint16_t conn_handle, uint8_t connect_status, uint16_t disconnect_status);
+
+//====================================ENTER MAIN==============================
+
+//=================================APP API CALLED BY APP=======================
+
+/**
+* BSAL find the stack ptr
+*
+* @param stack_ptr the point of the stack object
+* @param stack_name the name of the stack
+* @Note  find the object ptr of the stack by the name
+*        called by APP
+*/
+void *bsal_find_stack_ptr(char *stack_name);
+
+/**
+* BSAL init the stack
+*
+* @param stack_ptr the point of the stack object
+* @param callback the function to deal with the event
+* @Note  find the object ptr of the stack by the name
+*        called by APP
+*/
+int bsal_stack_init(void *stack_ptr, void *callback);
+
+
+/**
+* BSAL start register the profile table
+*
+* @param stack_ptr the point of the stack object
+* @param num the all number of the profile table
+* @param p_fun_cb the function of the profile to callback
+* @Note start to register the profile with the num
+*/
+
+void bsal_stack_le_srv_begin(void *stack_ptr, uint8_t num, void *p_fun_cb);
+
+/**
+* BSAL end register the profile table
+*
+* @param stack_ptr the point of the stack object
+* @Note the end to register the profile with the num
+*/
+void bsal_stack_le_srv_end(void *stack_ptr);
+
+/**
+* BSAL start the stack
+*
+* @param stack_ptr the point of the stack object
+* @Note to start the stack
+*/
+void bsal_stack_startup(void *stack_ptr);
+
+//2. SERVICE CALLBACK API APP NEED KNOWN
+
+typedef enum
+{
+    BSAL_CALLBACK_TYPE_READ_CHAR_VALUE = 1,              /**< client read event */
+    BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE = 2,             /**< client write event */
+    BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION = 3,    /**< CCCD update event */
+    BSAL_CALLBACK_TYPE_HANDLE_TABLE = 4,                 /**< handle event */
+} T_BSAL_SRV_CB_TYPE;
+
+struct bsal_callbak_data
+{
+    void                    *stack_ptr;
+    uint8_t                 conn_id;
+    T_BSAL_SRV_CB_TYPE      msg_type;
+    uint16_t                start_handle;
+    uint32_t                off_handle;
+    uint16_t                length;
+    uint8_t                 *data;
+    uint32_t                value;                   /**< CCCD save the temp value */
+    bsal_uuid_any_t         srv_uuid;
+};
+typedef struct bsal_callbak_data bsal_callbak_data_t;
+
+
+//3.ADV OPERATE
+struct le_adv_ltv
+{
+    uint8_t length;
+    uint8_t type;
+    uint8_t *value;
+};
+typedef struct le_adv_ltv  le_adv_ltv_t;
+/**
+* BSAL ADD FLAG LTV TO adv_data.
+*
+* @param adv_data the array of adv_data
+* @param flag the flag value of adv_type
+* @Note the function is used for add flag
+*/
+
+void bsal_le_adv_data_add_flag(uint8_t *adv_data , uint8_t flag);
+/**
+* BSAL ADD name
+*
+* @param adv_data the array of adv_data
+* @param name_length the length of name
+* @note the function is used for add fla g
+*/
+void bsal_adv_data_add_name(uint8_t *adv_data, uint8_t name_length, char *name);
+
+/**
+* BSAL ADD ONE UUID
+*
+* @param adv_data the array of adv_data
+* @param uuid the uuid valule of service
+* @note the function is used for add UUID
+*/
+void bsal_adv_data_add_uuid16(uint8_t *adv_data, uint16_t uuid);
+/**
+* BSAL add LTV TO adv_data.
+*
+* @param adv_data the array of adv_data
+* @param ltv the struct of lengthTypeValue
+* @param timeout the maximum response time
+* @Note the function is used in combine the adv_data of ltv
+*/
+void bsal_le_adv_data_add_ltv(uint8_t *adv_data, le_adv_ltv_t *ltv);
+/**
+* BSAL Set the adv data to stack.
+*
+* @param stack_ptr the object of the stack
+* @param adv_data the array of adv_data
+* @Note the function is used for add the data to stack
+*/
+void bsal_set_le_adv_data_user(void *stack_ptr, uint8_t *adv_data);
+/**
+* BSAL Set the scan rsp data to stack.
+*
+* @param stack_ptr the object of the stack
+* @param scan_rsp_data the array of scan_rsp_data
+* @Note the function is used for add the scan response data to stack
+*/
+void bsal_set_le_scan_rsp_data_user(void *stack_ptr, uint8_t *scan_rsp_data);
+
+/** @defgroup BSAL_SET_LE_PARAM_TYPE
+  * @{
+  */
+#define BSAL_SET_LE_ADV_PARAM                BIT(0)
+#define BSAL_SET_LE_SCAN_RSP_DATA            BIT(1)
+#define BSAL_SET_LE_ADV_DATA                 BIT(2)
+/**
+  * @}
+  */
+struct bsal_adv_param
+{
+    uint8_t  set_param_flag;                         //!< set the param bit see #BSAL_SET_LE_PARAM_TYPE
+    uint16_t adv_int_min;                            //!< set adv interval min
+    uint16_t adv_int_max;                            //!< set adv interval max
+    uint8_t  adv_type;                                //!< set adv type
+    uint8_t  own_address_type;                        //!< own address type
+    uint8_t  direct_address_type;                     //!< set direct bt mac address type
+    uint8_t  direct_address[6];                       //!< set the direct mac address
+    uint8_t  channel_map;                             //!< set the channel map see  @ref BTCHANNEL_MAP
+    uint8_t  filter_policy;                           //!< the filter policy see @ref ADV_PARAM_FILTER_POLICY
+
+    uint8_t scan_rsp_data[BSAL_MAX_ADV_SCAN_DATA_LENGTH];                        //the scan rsp data
+
+    uint8_t adv_data[BSAL_MAX_ADV_SCAN_DATA_LENGTH];                             //the adv data
+};
+typedef struct bsal_adv_param bsal_adv_param_t;
+/**
+* BSAL set le advertising param.
+*
+* @param stack_ptr the object of the stack
+* @param adv_param the point of the adv_param
+* @Note the function is used for set the adv param
+*/
+void bsal_set_le_adv_parm(void *stack_ptr, bsal_adv_param_t *adv_param);
+/**
+* BSAL start adv
+*
+* @param stack_ptr the object of the stack
+* @Note the function is used for start tx the adv
+*/
+int bsal_stack_start_adv(void *stack_ptr);
+/**
+* BSAL stop adv
+*
+* @param stack_ptr the object of the stack
+* @Note the function is used for stop tx the adv
+*/
+int bsal_stack_stop_adv(void *stack_ptr);
+//BOND
+//self define
+typedef enum
+{
+    BSAL_NO_INPUT,
+    BSAL_INPUT_YES_NO,
+    BSAL_INPUT_KEYBOARD,
+} T_BSAL_GAP_INPUT_CAP;
+
+typedef enum
+{
+    BSAL_NO_OUTPUT,
+    BSAL_YES_OUTPUT,
+} T_BSAL_GAP_OUTPUT_CAP;
+//bond
+struct bsal_bond_param
+{
+    uint8_t  LE_BR_EDR_FLAG;                                       // LE is 1 BR/EDR is 0
+    bool     bonding_flag;                                         //is bond
+    uint8_t  oob_flag;                                             //not support;
+    uint8_t  auth_type;                                            //AuthReq flag of device
+    uint8_t  io_capability;                                        //io_capability
+
+    //useless
+    uint8_t  force_auth_type;
+    bool     fixed_key_flag;
+    uint32_t fixed_key;
+    bool     sm_req_enable;
+};
+typedef struct bsal_bond_param bsal_bond_param_t;
+
+/**
+* BSAL set the bond type
+*
+* @param stack_ptr the object of the stack see
+* @param is_bond the bool about is needed bond
+* @param input the ability of input  see #T_BSAL_GAP_INPUT_CAP
+* @param output the ability of output  see #T_BSAL_GAP_OUTPUT_CAP
+* @param bond_type the bond type of the #BSAL_GAP_AUTH_TYPE
+* @Note the function is used for stop tx the adv
+*/
+uint16_t bsal_set_device_le_bond_type(void *stack_ptr, bool is_bond, uint8_t input, uint8_t output, uint8_t bond_type, bool oob_enable);
+
+
+/**
+* BSAL set the bond param
+*
+* @param stack_ptr the object of the stack see
+* @param bond_param the param of the bond
+* @Note the function is used for le bond param directly
+*/
+uint16_t bsal_set_device_le_bond_param(void *stack_ptr, bsal_bond_param_t *bond_param);
+struct bsal_gaps_param
+{
+    uint8_t name[BSAL_MAX_NAME_LENGTH];                          //!<  The GAP's SHOW NAME MAX LENGTH IS 40
+    uint16_t apperance;                        //!<  The GAP's apperance
+};
+typedef struct bsal_gaps_param bsal_gaps_param_t;
+/**
+* BSAL set gap param set the param of gap
+*
+* @param stack_ptr the object of the stack
+* @param gaps_param the struct of the gaps_param see #bsal_gaps_param_t
+* @Note the function is set the gap param
+*/
+void bsal_set_gap_param(void *stack_ptr, bsal_gaps_param_t *gaps_param);
+/**
+* BSAL set set the device name
+*
+* @param stack_ptr the object of the stack
+* @param length the length of the name
+* @param name the buffer of the name
+* @Note the function is set the device name
+*/
+int bsal_set_device_name(void *stack_ptr, uint8_t length, uint8_t *name);
+/**
+* BSAL set get the device name
+*
+* @param stack_ptr the object of the stack
+* @Note the function is get the device name
+*/
+uint8_t *bsal_get_device_name(void *stack_ptr);
+
+//========================================PROFILE API==CALLED BY SERVICE===========================
+//2. SERVICE API
+typedef BSAL_STATUS(*P_SRV_GENERAL_CB)(void *p_para);
+
+/**
+* BSAL register the profile table
+*
+* @param stack_ptr the object of the stack
+* @param srv_def the table of the service
+* @param callback the callback function of the profile
+* @Note the function is used for register the servcie table
+*       called by the profile
+*/
+int  bsal_stack_le_srv_reg_func(void *stack_ptr, void *srv_def, P_SRV_GENERAL_CB *callback);
+
+//3. SERVICE SEND DATA
+
+/**
+* BSAL send the notify data
+*
+* @param stack_ptr the object of the stack
+* @param conn_id the connect id of the link(like conn_handle)
+* @param service_id the identify of the profile
+* @param offset_handle the offset handle of the att in the profile
+* @param value_length the data length of the data
+* @param value the buff of the data
+* @Note  called by the profile to send the notify
+*/
+
+int bsal_srv_send_notify_data(void *stack_ptr, uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+
+/**
+* BSAL send the indicate data
+*
+* @param stack_ptr the object of the stack
+* @param conn_id the connect id of the link(like conn_handle)
+* @param service_id the identify of the profile
+* @param offset_handle the offset handle of the att in the profile
+* @param value_length the data length of the data
+* @param value the buff of the data
+* @Note  called by the profile to send the indicate
+*/
+int bsal_srv_send_ind_data(void *stack_ptr, uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+
+/**
+* BSAL get the start handle
+*
+* @param stack_ptr the object of the stack
+* @param uuid the profile main service uuid
+* @Note  called by the profile to get the start handle
+*/
+uint16_t bsal_srv_get_start_handle(void *stack_ptr, bsal_uuid_any_t uuid);
+/**
+* BSAL get the start handle by value handle
+*
+* @param stack_ptr the object of the stack
+* @param handle the u_handle of the device
+* @Note  called by the profile to get the start handle
+*/
+uint16_t bsal_profile_get_start_handle(void *stack_ptr, uint16_t value_handle);
+
+
+
+
+/**
+* BSAL WRITE ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_write_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value);
+
+/**
+* BSAL READ ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_read_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t *value_length, uint8_t **value);
+
+/**
+* BSAL CREATE ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_create_att(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length);
+/**
+* BSAL WRITE ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_write_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length, uint8_t *value);
+
+/**
+* BSAL READ ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_read_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t *value_length, uint8_t **value);
+
+/**
+* BSAL CREATE ATT
+*
+* @param p_db   the database of data
+* @param u_handle the unique handle of mcu
+* @note the function is used for read attribute
+*/
+int bsal_srv_create_att_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length);
+
+//=========================================STACK API ==CALLED BY STACK===========
+/**
+* BSAL READ ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param start_handle the start handle of the profile
+* @param offset_handle the att value of the handle
+* @param length the length of the value
+* @param[out] the buffer address of the value
+* @note read the callback event, called by the stack
+*/
+void bsal_gatt_read_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t *length , uint8_t **value);
+/**
+* @brief BSAL write ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param start_handle the start handle of the profile
+* @param offset_handle the att value of the handle
+* @param length the length of the value
+* @param value the data buffer address
+* @note write the callback event, called by the stack
+*/
+void bsal_gatt_write_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t length , uint8_t *value);
+/**
+* @brief BSAL CCCD ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param start_handle the start handle of the profile
+* @param offset_handle the att offset handle
+* @param length the length of the value
+* @param value the cccd_bit of the device
+* @note cccd the callback event, called by the stack
+*/
+void bsal_gatt_cccd_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t value);
+/**
+* BSAL READ ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param u_handle the unique handle of the device
+* @param length the length of the value
+* @param[out] the buffer address of the value
+* @note read the callback event, called by the stack
+*/
+void bsal_gatt_read_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle, uint16_t *length , uint8_t **value);
+/**
+* @brief BSAL write ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param u_handle the unique handle of the device
+* @param length the length of the value
+* @param value the data buffer address
+* @note write the callback event, called by the stack
+*/
+void bsal_gatt_write_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle, uint16_t length , uint8_t *value);
+/**
+* @brief BSAL CCCD ATT EVENT
+*
+* @param stack_ptr   point of the stack
+* @param conn_handle conn id of the link
+* @param u_handle the unique handle of the device
+* @param value the CCCD value of the device
+* @note cccd the callback event, called by the stack
+*/
+void bsal_gatt_cccd_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle , uint16_t value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 146 - 0
inc/bsal_common.h

@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#ifndef __BSAL_COMMON_H__
+#define __BSAL_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdint.h>
+
+#define  BIT(x)                             (1<<x)
+
+typedef enum
+{
+    BSAL_RESULT_SUCCESS                   = 0,
+    BSAL_RESULT_FAIL                      = 0xff,
+    BSAL_SRV_READ_PENDING                 = 0xf1,
+} BSAL_STATUS;
+
+#define BSAL_UUID_TYPE_16BIT  16
+#define BSAL_UUID_TYPE_32BIT  32
+#define BSAL_UUID_TYPE_128BIT 128
+
+/** 16-bit UUID */
+struct bsal_uuid16
+{
+    uint8_t u_type;
+    uint16_t value;
+};
+
+typedef struct bsal_uuid16 bsal_uuid16_t;
+
+/** 32-bit UUID */
+struct bsal_uuid32
+{
+    uint8_t u_type;
+    uint32_t value;
+} ;
+typedef struct bsal_uuid32 bsal_uuid32_t;
+
+/** 128-bit UUID */
+struct bsal_uuid128
+{
+    uint8_t u_type;
+    uint8_t value[16];
+};
+typedef struct bsal_uuid128 bsal_uuid128_t;
+
+typedef union
+{
+    uint8_t u_type;
+    bsal_uuid16_t u16;
+    bsal_uuid32_t u32;
+    bsal_uuid128_t u128;
+} bsal_uuid_any_t;
+
+#define BSAL_UUID16_INIT(uuid16)         \
+    {                                   \
+        .u_type = BSAL_UUID_TYPE_16BIT,     \
+        .value = (uuid16),              \
+    }
+
+#define BSAL_UUID32_INIT(uuid32)         \
+    {                                   \
+        .u_type = BSAL_UUID_TYPE_32BIT,     \
+        .value = (uuid32),              \
+    }
+
+#define BSAL_UUID128_INIT(uuid128...)    \
+    {                                   \
+        .u_type = BSAL_UUID_TYPE_128BIT,    \
+        .value = { uuid128 },           \
+    }
+
+#define BSAL_UUID16_DECLARE(uuid16) \
+    ((bsal_uuid_any_t *) (&(bsal_uuid16_t) BSAL_UUID16_INIT(uuid16)))
+
+#define BSAL_UUID32_DECLARE(uuid32) \
+    ((bsal_uuid_any_t *) (&(bsal_uuid32_t) BSAL_UUID32_INIT(uuid32)))
+
+#define BSAL_UUID128_DECLARE(uuid128...) \
+    ((bsal_uuid_any_t *) (&(bsal_uuid128_t) BSAL_UUID128_INIT(uuid128)))
+
+struct bsal_gatt_chr_def
+{
+    bsal_uuid_any_t *uuid;
+    struct bsal_gatt_dsc_def *descriptors;
+    uint16_t properties;
+    uint16_t permission;
+    uint8_t value_length;
+    uint16_t *val_handle;
+    uint32_t bsal_flag;  //self define flag for future
+};
+typedef struct bsal_gatt_chr_def bsal_gatt_chr_def_t;
+
+//SERVICE DEF
+struct bsal_gatt_app_srv_def
+{
+    uint16_t type;
+    bsal_uuid_any_t *uuid;
+    struct bsal_gatt_app_srv_def **includes;
+    bsal_gatt_chr_def_t *characteristics;
+};
+typedef struct bsal_gatt_app_srv_def  bsal_gatt_app_srv_def_t;
+
+struct bsal_gatt_dsc_def
+{
+    bsal_uuid_any_t *uuid;
+    uint8_t att_flags;
+    uint8_t min_key_size;
+};
+typedef struct bsal_gatt_dsc_def bsal_gatt_dsc_def_t;
+
+struct bsal_gatt_res
+{
+    uint16_t svcs;
+    void     *srvc_addr;
+    uint16_t incs;
+    void     *incs_addr;
+    uint16_t chrs;
+    void     *chrs_addr;
+    uint16_t dscs;
+    void     *dscs_addr;
+    uint16_t cccds;
+    void     *cccds_addr;
+    uint16_t attrs;
+};
+
+typedef struct bsal_gatt_res bsal_gatt_res_t;
+#define BSAL_MAX_NAME_LENGTH 40
+#define BSAL_MAX_ADV_SCAN_DATA_LENGTH 30
+#define BSAL_SRV_UUID_GENERAL  0xEEEE
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

+ 189 - 0
inc/bsal_int.h

@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_INT_H__
+#define __BSAL_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "bsal.h"
+
+struct bsal_uuid
+{
+    uint8_t type;
+    uint8_t data[16];
+    uint16_t propertiy;
+    uint16_t permision;
+    uint32_t *handle;
+};
+typedef struct bsal_uuid bsal_uuid_t;
+
+struct bsal_gatt_value_entry
+{
+    uint32_t u_handle;
+    uint8_t *value;
+    uint16_t value_length;
+    uint32_t alloc_size;
+    bool append;///for future
+    struct bsal_gatt_value_entry *next_entry;
+};
+typedef struct bsal_gatt_value_entry bsal_gatt_value_entry_t;
+
+struct bsal_stack_ops
+{
+    BSAL_STATUS(*le_set_stack_param)(uint32_t value_length, uint8_t *value);         //set param  param_type firstbit   1:br/edr param 0: ble
+    BSAL_STATUS(*le_get_stack_param)(uint32_t value_length, uint8_t *value);        //get param  param_type firstbit   1:br/edr param 0: ble
+    void (*get_mac_address)(uint8_t addr_type, uint8_t *bd_addr);                                      //get mac addr
+    void (*init)(uint8_t stack_type);                                                                  //stack init     //set the default param stack_type: bit 0 :BR/EDR. bit 1: BLE, bit2:mesh
+    void (*startup)(void);                                                                             //stack init
+    //GAP OPERATE
+    //bond
+    void (*set_bond_param)(bsal_bond_param_t *value);              //set adv param
+    void (*get_bond_param)(bsal_bond_param_t *value);
+    //ADV PARAM
+    void (*le_set_adv_param)(bsal_adv_param_t *adv_param);              //set adv param
+    void (*le_get_adv_param)(bsal_adv_param_t *adv_param);
+    BSAL_STATUS(*le_adv_enable)(bool enable);                                   // set adv param
+    void (*set_gaps_param)(bsal_gaps_param_t *gaps_param);                                               //set device name
+
+    //service profile
+    uint32_t (*cov_handle_to_u_handle)(uint16_t service_id, uint16_t offset_handle);               // bsal_hanlde_to_stack_handle
+    BSAL_STATUS(*le_srv_reg_begin)(bool is_continue, uint8_t service_num, void *p_func);
+    BSAL_STATUS(*le_srv_reg_fun)(struct bsal_gatt_app_srv_def *p_srv, void *p_func);    //tobe define
+    BSAL_STATUS(*le_srv_reg_end)(void);
+    BSAL_STATUS(*le_srv_send_data)(uint16_t conn_handle, uint16_t service_id, uint16_t offse_handle, uint16_t value_len, const uint8_t *value, uint8_t send_type);
+    BSAL_STATUS(*send_notify_complete)(uint32_t credits);   /*TODO*/
+    //client profile
+    // TO BE CALLED BY BSAL_RTK.C
+};
+typedef struct bsal_stack_ops  bsal_stack_ops_t;
+
+//load the static info
+struct bsal_stack_info
+{
+    uint8_t public_bd_addr[6];
+    uint8_t device_name[BSAL_MAX_NAME_LENGTH];
+    uint16_t le_mtu_size;
+    uint16_t le_srv_tx_credits;
+    bsal_adv_param_t adv_param;
+    bsal_bond_param_t bond_param;
+};
+typedef struct bsal_stack_info bsal_stack_info_t;
+
+typedef BSAL_STATUS(*P_BSAL_PROFILE_CB)(void *p_para);
+struct bsal_srv_callback
+{
+    P_BSAL_PROFILE_CB  bsal_srv_fn_cb;
+    uint16_t           start_handle;
+    bsal_uuid_any_t    srv_uuid;
+};
+typedef struct bsal_srv_callback bsal_srv_callback_t;
+
+struct bsal_stack_obj
+{
+    bool                       stack_ready_flag;
+    bsal_stack_ops_t           bsal_ops;
+    //att
+    bsal_gatt_value_entry_t   *db;
+    //service
+    bsal_srv_callback_t       *bsal_srv_objs;
+    //static info:
+    bsal_stack_info_t          bsal_info;
+
+    uint16_t                   g_att_index;
+    uint8_t                    srv_num;
+    //register
+    void (*app_all_callbak)(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value);
+};
+typedef struct bsal_stack_obj  bsal_stack_obj_t;
+
+/**
+* BSAL create the att first init
+*
+* @param stack_ptr the point of the stack object
+* @param u_handle the unique handle of the att
+* @param value_length the length of the value
+* @param value the buffer of the value
+* @Note create the attribute with the unique handle
+*/
+
+int bsal_att_create_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length);
+
+/**
+* BSAL read the attribute with u_handle
+*
+* @param stack_ptr the point of the stack object
+* @param u_handle the unique handle of the att
+* @param value_length the length of the value
+* @param save the value the buffer of the value
+* @Note create the attribute with the unique handle
+*/
+int bsal_att_read_entry(void *stack_ptr, uint32_t u_handle, uint16_t *value_length, uint8_t **value);
+
+/**
+* BSAL write the attribute with u_handle
+*
+* @param stack_ptr the point of the stack object
+* @param u_handle the unique handle of the att
+* @param value_length the length of the value
+* @param value the buffer of the value
+* @Note create the attribute with the unique handle
+*/
+int bsal_att_write_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, uint8_t *value);
+
+/**
+* BSAL change the attribute size with u_handle
+*
+* @param stack_ptr the point of the stack object
+* @param u_handle the unique handle of the att
+* @param value_length the length of the value
+* @param append the flag of append the value
+* @Note change the size of value the attribute with the unique handle
+*/
+int bsal_att_resize_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, bool append);
+
+//send data
+typedef enum
+{
+    BSAL_SEND_DATA_TYPE_ANY           = 0x00, /**<  Any PDU type. */
+    BSAL_SEND_DATA_TYPE_NOTIFICATION  = 0x01, /**<  Notification PDU type. */
+    BSAL_SEND_DATA_TYPE_INDICATION    = 0x02  /**<  Indication PDU type. */
+} T_BSAL_SEND_DATA_TYPE;
+
+/**
+* BSAL find the start handle by the uuid
+*
+* @param stack_ptr the point of the stack object
+* @param uuid the 16 bit of the uuid
+* @Note get the profile start handle by the uuid
+*/
+uint16_t bsal_profile_get_start_handle_by_16_uuid(void *stack_ptr, uint16_t uuid);
+
+/**
+* BSAL get the profile entry by the start handle
+*
+* @param stack_ptr the point of the stack object
+* @param the start handle
+* @Note get the profile entry by the start_handle
+*/
+bsal_srv_callback_t *bsal_profile_get(void *stack_ptr, uint16_t start_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+

+ 71 - 0
inc/bsal_osif.h

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_OSIF_H__
+#define __BSAL_OSIF_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <rtthread.h>
+/**
+* BSAL OSIF malloc the buffer
+*
+* @param len the buffer size of the buffer
+* @Note  malloc the buffer
+*/
+void *bsal_osif_malloc(uint32_t len);
+
+/**
+* BSAL OSIF free the buffer
+*
+* @param p the point of the buffer
+* @Note  free the buffer
+*/
+void bsal_osif_free(void *p);
+
+/**
+* BSAL OSIF delay
+*
+* @param ms the ms of delay time
+* @Note  delay the time
+*/
+void bsal_osif_delay(uint32_t ms);
+
+
+
+#if 0
+int bsal_osif_printf_dbg(const char *fmt, ...);
+int bsal_osif_printf_err(const char *fmt, ...);
+int bsal_osif_printf_info(const char *fmt, ...);
+int bsal_osif_printf_warn(const char *fmt, ...);
+#else
+#define bsal_osif_printf_dbg rt_kprintf
+#define bsal_osif_printf_err rt_kprintf
+#define bsal_osif_printf_info rt_kprintf
+#define bsal_osif_printf_warn rt_kprintf
+
+#endif
+
+#ifdef BSAL_ASSERT_DEBUG
+
+#define BSAL_ASSERT_PTR(x)        if(x==NULL) \
+    {bsal_osif_printf_err("%s line:%d: the point is NULL:%p",__FUNCTION__, __LINE__,x); while(1);}
+#else
+#define BSAL_ASSERT_PTR(x)
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 524 - 0
inc/bsal_sig.h

@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+
+
+#ifndef __BSAL_SIG_H__
+#define __BSAL_SIG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdint.h>
+#include <stdbool.h>
+
+//=====================uuid===================
+
+//=====================uuid=PROFILE==================
+/**
+ * Assigned numbers from www.bluetooth.com/specifications/gatt/declarations
+ */
+#define BSAL_GATT_UUID_PRIMARY_SERVICE                                     0x2800 // Primary Service
+#define BSAL_GATT_UUID_SECONDARY_SERVICE                                   0x2801 // Secondary Service
+#define BSAL_GATT_UUID_INCLUDE                                             0x2802 // Include        
+#define BSAL_GATT_UUID_CHARACTERISTIC                                      0x2803 // Characteristic Declaration
+
+/**
+ * Assigned numbers from www.bluetooth.com/specifications/gatt/services
+ */
+#define BSAL_GATT_SERVICE_ALERT_NOTIFICATION                                         0x1811 // Alert Notification Service
+#define BSAL_GATT_SERVICE_AUTOMATION_IO                                              0x1815 // Automation IO
+#define BSAL_GATT_SERVICE_BATTERY_SERVICE                                            0x180F // Battery Service
+#define BSAL_GATT_SERVICE_BLOOD_PRESSURE                                             0x1810 // Blood Pressure
+#define BSAL_GATT_SERVICE_BODY_COMPOSITION                                           0x181B // Body Composition
+#define BSAL_GATT_SERVICE_BOND_MANAGEMENT                                            0x181E // Bond Management Service
+#define BSAL_GATT_SERVICE_CONTINUOUS_GLUCOSE_MONITORING                              0x181F // Continuous Glucose Monitoring
+#define BSAL_GATT_SERVICE_CURRENT_TIME                                               0x1805 // Current Time Service
+#define BSAL_GATT_SERVICE_CYCLING_POWER                                              0x1818 // Cycling Power
+#define BSAL_GATT_SERVICE_CYCLING_SPEED_AND_CADENCE                                  0x1816 // Cycling Speed and Cadence
+#define BSAL_GATT_SERVICE_DEVICE_INFORMATION                                         0x180A // Device Information
+#define BSAL_GATT_SERVICE_ENVIRONMENTAL_SENSING                                      0x181A // Environmental Sensing
+#define BSAL_GATT_SERVICE_FITNESS_MACHINE                                            0x1826 // Fitness Machine
+#define BSAL_GATT_SERVICE_GENERIC_ACCESS                                             0x1800 //  Generic Access
+#define BSAL_GATT_SERVICE_GENERIC_ATTRIBUTE                                          0x1801 // Generic Attribute
+#define BSAL_GATT_SERVICE_GLUCOSE                                                    0x1808 // Glucose
+#define BSAL_GATT_SERVICE_HEALTH_THERMOMETER                                         0x1809 // Health Thermometer
+#define BSAL_GATT_SERVICE_HEART_RATE                                                 0x180D // Heart Rate
+#define BSAL_GATT_SERVICE_HTTP_PROXY                                                 0x1823 // HTTP Proxy
+#define BSAL_GATT_SERVICE_HUMAN_INTERFACE_DEVICE                                     0x1812 // Human Interface Device
+#define BSAL_GATT_SERVICE_IMMEDIATE_ALERT                                            0x1802 // Immediate Alert
+#define BSAL_GATT_SERVICE_INDOOR_POSITIONING                                         0x1821 // Indoor Positioning
+#define BSAL_GATT_SERVICE_INSULIN_DELIVERY                                           0x183A // Insulin Delivery
+#define BSAL_GATT_SERVICE_INTERNET_PROTOCOL_SUPPORT                                  0x1820 // Internet Protocol Support Service
+#define BSAL_GATT_SERVICE_LINK_LOSS                                                  0x1803 // Link Loss
+#define BSAL_GATT_SERVICE_LOCATION_AND_NAVIGATION                                    0x1819 // Location and Navigation
+#define BSAL_GATT_SERVICE_MESH_PROVISIONING                                          0x1827 // Mesh Provisioning Service
+#define BSAL_GATT_SERVICE_MESH_PROXY                                                 0x1828 // Mesh Proxy Service
+#define BSAL_GATT_SERVICE_NEXT_DST_CHANGE                                            0x1807 // Next DST Change Service
+#define BSAL_GATT_SERVICE_OBJECT_TRANSFER                                            0x1825 // Object Transfer Service
+#define BSAL_GATT_SERVICE_PHONE_ALERT_STATUS                                         0x180E // Phone Alert Status Service
+#define BSAL_GATT_SERVICE_PULSE_OXIMETER                                             0x1822 // Pulse Oximeter Service
+#define BSAL_GATT_SERVICE_RECONNECTION_CONFIGURATION                                 0x1829 // Reconnection Configuration
+#define BSAL_GATT_SERVICE_REFERENCE_TIME_UPDATE                                      0x1806 // Reference Time Update Service
+#define BSAL_GATT_SERVICE_RUNNING_SPEED_AND_CADENCE                                  0x1814 // Running Speed and Cadence
+#define BSAL_GATT_SERVICE_SCAN_PARAMETERS                                            0x1813 // Scan Parameters
+#define BSAL_GATT_SERVICE_TRANSPORT_DISCOVERY                                        0x1824 // Transport Discovery
+#define BSAL_GATT_SERVICE_TX_POWER                                                   0x1804 // Tx Power
+#define BSAL_GATT_SERVICE_USER_DATA                                                  0x181C // User Data
+#define BSAL_GATT_SERVICE_WEIGHT_SCALE                                               0x181D // Weight Scale
+/**
+ * Assigned numbers from www.bluetooth.com/specifications/gatt/characteristics
+ */
+#define BSAL_UUID_CHAR_AEROBIC_HEART_RATE_LOWER_LIMIT                      0x2A7E // Aerobic Heart Rate Lower Limit
+#define BSAL_UUID_CHAR_AEROBIC_HEART_RATE_UPPER_LIMIT                      0x2A84 // Aerobic Heart Rate Upper Limit
+#define BSAL_UUID_CHAR_AEROBIC_THRESHOLD                                   0x2A7F // Aerobic Threshold
+#define BSAL_UUID_CHAR_AGE                                                 0x2A80 // Age
+#define BSAL_UUID_CHAR_AGGREGATE                                           0x2A5A // Aggregate
+#define BSAL_UUID_CHAR_ALERT_CATEGORY_ID                                   0x2A43 // Alert Category ID
+#define BSAL_UUID_CHAR_ALERT_CATEGORY_ID_BIT_MASK                          0x2A42 // Alert Category ID Bit Mask
+#define BSAL_UUID_CHAR_ALERT_LEVEL                                         0x2A06 // Alert Level
+#define BSAL_UUID_CHAR_ALERT_NOTIFICATION_CONTROL_POINT                    0x2A44 // Alert Notification Control Point
+#define BSAL_UUID_CHAR_ALERT_STATUS                                        0x2A3F // Alert Status
+#define BSAL_UUID_CHAR_ALTITUDE                                            0x2AB3 // Altitude
+#define BSAL_UUID_CHAR_ANAEROBIC_HEART_RATE_LOWER_LIMIT                    0x2A81 // Anaerobic Heart Rate Lower Limit
+#define BSAL_UUID_CHAR_ANAEROBIC_HEART_RATE_UPPER_LIMIT                    0x2A82 // Anaerobic Heart Rate Upper Limit
+#define BSAL_UUID_CHAR_ANAEROBIC_THRESHOLD                                 0x2A83 // Anaerobic Threshold
+#define BSAL_UUID_CHAR_ANALOG                                              0x2A58 // Analog
+#define BSAL_UUID_CHAR_ANALOG_OUTPUT                                       0x2A59 // Analog Output
+#define BSAL_UUID_CHAR_APPARENT_WIND_DIRECTION                             0x2A73 // Apparent Wind Direction
+#define BSAL_UUID_CHAR_APPARENT_WIND_SPEED                                 0x2A72 // Apparent Wind Speed
+#define BSAL_UUID_CHAR_BAROMETRIC_PRESSURE_TREND                           0x2AA3 // Barometric Pressure Trend
+#define BSAL_UUID_CHAR_BATTERY_LEVEL                                       0x2A19 // Battery Level
+#define BSAL_UUID_CHAR_BATTERY_LEVEL_STATE                                 0x2A1B // Battery Level State
+#define BSAL_UUID_CHAR_BATTERY_POWER_STATE                                 0x2A1A // Battery Power State
+#define BSAL_UUID_CHAR_BLOOD_PRESSURE_FEATURE                              0x2A49 // Blood Pressure Feature
+#define BSAL_UUID_CHAR_BLOOD_PRESSURE_MEASUREMENT                          0x2A35 // Blood Pressure Measurement
+#define BSAL_UUID_CHAR_BODY_COMPOSITION_FEATURE                            0x2A9B // Body Composition Feature
+#define BSAL_UUID_CHAR_BODY_COMPOSITION_MEASUREMENT                        0x2A9C // Body Composition Measurement
+#define BSAL_UUID_CHAR_BODY_SENSOR_LOCATION                                0x2A38 // Body Sensor Location
+#define BSAL_UUID_CHAR_BOND_MANAGEMENT_CONTROL_POINT                       0x2AA4 // Bond Management Control Point
+#define BSAL_UUID_CHAR_BOND_MANAGEMENT_FEATURE                             0x2AA5 // Bond Management Features
+#define BSAL_UUID_CHAR_BOOT_KEYBOARD_INPUT_REPORT                          0x2A22 // Boot Keyboard Input Report
+#define BSAL_UUID_CHAR_BOOT_KEYBOARD_OUTPUT_REPORT                         0x2A32 // Boot Keyboard Output Report
+#define BSAL_UUID_CHAR_BOOT_MOUSE_INPUT_REPORT                             0x2A33 // Boot Mouse Input Report
+#define BSAL_UUID_CHAR_CGM_FEATURE                                         0x2AA8 // CGM Feature
+#define BSAL_UUID_CHAR_CGM_MEASUREMENT                                     0x2AA7 // CGM Measurement
+#define BSAL_UUID_CHAR_CGM_SESSION_RUN_TIME                                0x2AAB // CGM Session Run Time
+#define BSAL_UUID_CHAR_CGM_SESSION_START_TIME                              0x2AAA // CGM Session Start Time
+#define BSAL_UUID_CHAR_CGM_SPECIFIC_OPS_CONTROL_POINT                      0x2AAC // CGM Specific Ops Control Point
+#define BSAL_UUID_CHAR_CGM_STATUS                                          0x2AA9 // CGM Status
+#define BSAL_UUID_CHAR_CROSS_TRAINER_DATA                                  0x2ACE // Cross Trainer Data
+#define BSAL_UUID_CHAR_CSC_FEATURE                                         0x2A5C // CSC Feature
+#define BSAL_UUID_CHAR_CSC_MEASUREMENT                                     0x2A5B // CSC Measurement
+#define BSAL_UUID_CHAR_CURRENT_TIME                                        0x2A2B // Current Time
+#define BSAL_UUID_CHAR_CYCLING_POWER_CONTROL_POINT                         0x2A66 // Cycling Power Control Point
+#define BSAL_UUID_CHAR_CYCLING_POWER_FEATURE                               0x2A65 // Cycling Power Feature
+#define BSAL_UUID_CHAR_CYCLING_POWER_MEASUREMENT                           0x2A63 // Cycling Power Measurement
+#define BSAL_UUID_CHAR_CYCLING_POWER_VECTOR                                0x2A64 // Cycling Power Vector
+#define BSAL_UUID_CHAR_DATABASE_CHANGE_INCREMENT                           0x2A99 // Database Change Increment
+#define BSAL_UUID_CHAR_DATE_OF_BIRTH                                       0x2A85 // Date of Birth
+#define BSAL_UUID_CHAR_DATE_OF_THRESHOLD_ASSESSMENT                        0x2A86 // Date of Threshold Assessment
+#define BSAL_UUID_CHAR_DATE_TIME                                           0x2A08 // Date Time
+#define BSAL_UUID_CHAR_DATE_UTC                                            0x2AED // Date UTC
+#define BSAL_UUID_CHAR_DAY_DATE_TIME                                       0x2A0A // Day Date Time
+#define BSAL_UUID_CHAR_DAY_OF_WEEK                                         0x2A09 // Day of Week
+#define BSAL_UUID_CHAR_DESCRIPTOR_VALUE_CHANGED                            0x2A7D // Descriptor Value Changed
+#define BSAL_UUID_CHAR_DEW_POINT                                           0x2A7B // Dew Point
+#define BSAL_UUID_CHAR_DIGITAL                                             0x2A56 // Digital
+#define BSAL_UUID_CHAR_DIGITAL_OUTPUT                                      0x2A57 // Digital Output
+#define BSAL_UUID_CHAR_DST_OFFSET                                          0x2A0D // DST Offset
+#define BSAL_UUID_CHAR_ELEVATION                                           0x2A6C // Elevation
+#define BSAL_UUID_CHAR_EMAIL_ADDRESS                                       0x2A87 // Email Address
+#define BSAL_UUID_CHAR_EXACT_TIME_100                                      0x2A0B // Exact Time 100
+#define BSAL_UUID_CHAR_EXACT_TIME_256                                      0x2A0C // Exact Time 256
+#define BSAL_UUID_CHAR_FAT_BURN_HEART_RATE_LOWER_LIMIT                     0x2A88 // Fat Burn Heart Rate Lower Limit
+#define BSAL_UUID_CHAR_FAT_BURN_HEART_RATE_UPPER_LIMIT                     0x2A89 // Fat Burn Heart Rate Upper Limit
+#define BSAL_UUID_CHAR_FIRMWARE_REVISION_STRING                            0x2A26 // Firmware Revision String
+#define BSAL_UUID_CHAR_FIRST_NAME                                          0x2A8A // First Name
+#define BSAL_UUID_CHAR_FITNESS_MACHINE_CONTROL_POINT                       0x2AD9 // Fitness Machine Control Point
+#define BSAL_UUID_CHAR_FITNESS_MACHINE_FEATURE                             0x2ACC // Fitness Machine Feature
+#define BSAL_UUID_CHAR_FITNESS_MACHINE_STATUS                              0x2ADA // Fitness Machine Status
+#define BSAL_UUID_CHAR_FIVE_ZONE_HEART_RATE_LIMITS                         0x2A8B // Five Zone Heart Rate Limits
+#define BSAL_UUID_CHAR_FLOOR_NUMBER                                        0x2AB2 // Floor Number
+#define BSAL_UUID_CHAR_GAP_APPEARANCE                                      0x2A01 // Appearance
+#define BSAL_UUID_CHAR_GAP_CENTRAL_ADDRESS_RESOLUTION                      0x2AA6 // Central Address Resolution
+#define BSAL_UUID_CHAR_GAP_DEVICE_NAME                                     0x2A00 // Device Name
+#define BSAL_UUID_CHAR_GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS      0x2A04 // Peripheral Preferred Connection Parameters
+#define BSAL_UUID_CHAR_GAP_PERIPHERAL_PRIVACY_FLAG                         0x2A02 // Peripheral Privacy Flag
+#define BSAL_UUID_CHAR_GAP_RECONNECTION_ADDRESS                            0x2A03 // Reconnection Address
+#define BSAL_UUID_CHAR_GATT_SERVICE_CHANGED                                0x2A05 // Service Changed
+#define BSAL_UUID_CHAR_GENDER                                              0x2A8C // Gender
+#define BSAL_UUID_CHAR_GLUCOSE_FEATURE                                     0x2A51 // Glucose Feature
+#define BSAL_UUID_CHAR_GLUCOSE_MEASUREMENT                                 0x2A18 // Glucose Measurement
+#define BSAL_UUID_CHAR_GLUCOSE_MEASUREMENT_CONTEXT                         0x2A34 // Glucose Measurement Context
+#define BSAL_UUID_CHAR_GUST_FACTOR                                         0x2A74 // Gust Factor
+#define BSAL_UUID_CHAR_HARDWARE_REVISION_STRING                            0x2A27 // Hardware Revision String
+#define BSAL_UUID_CHAR_HEART_RATE_CONTROL_POINT                            0x2A39 // Heart Rate Control Point
+#define BSAL_UUID_CHAR_HEART_RATE_MAX                                      0x2A8D // Heart Rate Max
+#define BSAL_UUID_CHAR_HEART_RATE_MEASUREMENT                              0x2A37 // Heart Rate Measurement
+#define BSAL_UUID_CHAR_HEAT_INDEX                                          0x2A7A // Heat Index
+#define BSAL_UUID_CHAR_HEIGHT                                              0x2A8E // Height
+#define BSAL_UUID_CHAR_HID_CONTROL_POINT                                   0x2A4C // HID Control Point
+#define BSAL_UUID_CHAR_HID_INFORMATION                                     0x2A4A // HID Information
+#define BSAL_UUID_CHAR_HIP_CIRCUMFERENCE                                   0x2A8F // Hip Circumference
+#define BSAL_UUID_CHAR_HTTP_CONTROL_POINT                                  0x2ABA // HTTP Control Point
+#define BSAL_UUID_CHAR_HTTP_ENTITY_BODY                                    0x2AB9 // HTTP Entity Body
+#define BSAL_UUID_CHAR_HTTP_HEADERS                                        0x2AB7 // HTTP Headers
+#define BSAL_UUID_CHAR_HTTP_STATUS_CODE                                    0x2AB8 // HTTP Status Code
+#define BSAL_UUID_CHAR_HTTPS_SECURITY                                      0x2ABB // HTTPS Security
+#define BSAL_UUID_CHAR_HUMIDITY                                            0x2A6F // Humidity
+#define BSAL_UUID_CHAR_IDD_ANNUNCIATION_STATUS                             0x2B22 // IDD Annunciation Status
+#define BSAL_UUID_CHAR_IDD_COMMAND_CONTROL_POINT                           0x2B25 // IDD Command Control Point
+#define BSAL_UUID_CHAR_IDD_COMMAND_DATA                                    0x2B26 // IDD Command Data
+#define BSAL_UUID_CHAR_IDD_FEATURES                                        0x2B23 // IDD Features
+#define BSAL_UUID_CHAR_IDD_HISTORY_DATA                                    0x2B28 // IDD History Data
+#define BSAL_UUID_CHAR_IDD_RECORD_ACCESS_CONTROL_POINT                     0x2B27 // IDD Record Access Control Point
+#define BSAL_UUID_CHAR_IDD_STATUS                                          0x2B21 // IDD Status
+#define BSAL_UUID_CHAR_IDD_STATUS_CHANGED                                  0x2B20 // IDD Status Changed
+#define BSAL_UUID_CHAR_IDD_STATUS_READER_CONTROL_POINT                     0x2B24 // IDD Status Reader Control Point
+#define BSAL_UUID_CHAR_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST 0x2A2A // IEEE 11073-20601 Regulatory Certification Data List
+#define BSAL_UUID_CHAR_INDOOR_BIKE_DATA                                    0x2AD2 // Indoor Bike Data
+#define BSAL_UUID_CHAR_INDOOR_POSITIONING_CONFIGURATION                    0x2AAD // Indoor Positioning Configuration
+#define BSAL_UUID_CHAR_INTERMEDIATE_CUFF_PRESSURE                          0x2A36 // Intermediate Cuff Pressure
+#define BSAL_UUID_CHAR_INTERMEDIATE_TEMPERATURE                            0x2A1E // Intermediate Temperature
+#define BSAL_UUID_CHAR_IRRADIANCE                                          0x2A77 // Irradiance
+#define BSAL_UUID_CHAR_LANGUAGE                                            0x2AA2 // Language
+#define BSAL_UUID_CHAR_LAST_NAME                                           0x2A90 // Last Name
+#define BSAL_UUID_CHAR_LATITUDE                                            0x2AAE // Latitude
+#define BSAL_UUID_CHAR_LN_CONTROL_POINT                                    0x2A6B // LN Control Point
+#define BSAL_UUID_CHAR_LN_FEATURE                                          0x2A6A // LN Feature
+#define BSAL_UUID_CHAR_LOCAL_EAST_COORDINATE                               0x2AB1 // Local East Coordinate
+#define BSAL_UUID_CHAR_LOCAL_NORTH_COORDINATE                              0x2AB0 // Local North Coordinate
+#define BSAL_UUID_CHAR_LOCAL_TIME_INFORMATION                              0x2A0F // Local Time Information
+#define BSAL_UUID_CHAR_LOCATION_AND_SPEED                                  0x2A67 // Location and Speed Characteristic
+#define BSAL_UUID_CHAR_LOCATION_NAME                                       0x2AB5 // Location Name
+#define BSAL_UUID_CHAR_LONGITUDE                                           0x2AAF // Longitude
+#define BSAL_UUID_CHAR_MAGNETIC_DECLINATION                                0x2A2C // Magnetic Declination
+#define BSAL_UUID_CHAR_MAGNETIC_FLUX_DENSITY_2D                            0x2AA0 // Magnetic Flux Density - 2D
+#define BSAL_UUID_CHAR_MAGNETIC_FLUX_DENSITY_3D                            0x2AA1 // Magnetic Flux Density - 3D
+#define BSAL_UUID_CHAR_MANUFACTURER_NAME_STRING                            0x2A29 // Manufacturer Name String
+#define BSAL_UUID_CHAR_MAXIMUM_RECOMMENDED_HEART_RATE                      0x2A91 // Maximum Recommended Heart Rate
+#define BSAL_UUID_CHAR_MEASUREMENT_INTERVAL                                0x2A21 // Measurement Interval
+#define BSAL_UUID_CHAR_MODEL_NUMBER_STRING                                 0x2A24 // Model Number String
+#define BSAL_UUID_CHAR_NAVIGATION                                          0x2A68 // Navigation
+#define BSAL_UUID_CHAR_NETWORK_AVAILABILITY                                0x2A3E // Network Availability
+#define BSAL_UUID_CHAR_NEW_ALERT                                           0x2A46 // New Alert
+#define BSAL_UUID_CHAR_OBJECT_ACTION_CONTROL_POINT                         0x2AC5 // Object Action Control Point
+#define BSAL_UUID_CHAR_OBJECT_CHANGED                                      0x2AC8 // Object Changed
+#define BSAL_UUID_CHAR_OBJECT_FIRST_CREATED                                0x2AC1 // Object First-Created
+#define BSAL_UUID_CHAR_OBJECT_ID                                           0x2AC3 // Object ID
+#define BSAL_UUID_CHAR_OBJECT_LAST_MODIFIED                                0x2AC2 // Object Last-Modified
+#define BSAL_UUID_CHAR_OBJECT_LIST_CONTROL_POINT                           0x2AC6 // Object List Control Point
+#define BSAL_UUID_CHAR_OBJECT_LIST_FILTER                                  0x2AC7 // Object List Filter
+#define BSAL_UUID_CHAR_OBJECT_NAME                                         0x2ABE // Object Name
+#define BSAL_UUID_CHAR_OBJECT_PROPERTIES                                   0x2AC4 // Object Properties
+#define BSAL_UUID_CHAR_OBJECT_SIZE                                         0x2AC0 // Object Size
+#define BSAL_UUID_CHAR_OBJECT_TYPE                                         0x2ABF // Object Type
+#define BSAL_UUID_CHAR_OTS_FEATURE                                         0x2ABD // OTS Feature
+#define BSAL_UUID_CHAR_PLX_CONTINUOUS_MEASUREMENT                          0x2A5F // PLX Continuous Measurement Characteristic
+#define BSAL_UUID_CHAR_PLX_FEATURES                                        0x2A60 // PLX Features
+#define BSAL_UUID_CHAR_PLX_SPOT_CHECK_MEASUREMENT                          0x2A5E // PLX Spot-Check Measurement
+#define BSAL_UUID_CHAR_PNP_ID                                              0x2A50 // PnP ID
+#define BSAL_UUID_CHAR_POLLEN_CONCENTRATION                                0x2A75 // Pollen Concentration
+#define BSAL_UUID_CHAR_POSITION_2D                                         0x2A2F // Position 2D
+#define BSAL_UUID_CHAR_POSITION_3D                                         0x2A30 // Position 3D
+#define BSAL_UUID_CHAR_POSITION_QUALITY                                    0x2A69 // Position Quality
+#define BSAL_UUID_CHAR_PRESSURE                                            0x2A6D // Pressure
+#define BSAL_UUID_CHAR_PROTOCOL_MODE                                       0x2A4E // Protocol Mode
+#define BSAL_UUID_CHAR_PULSE_OXIMETRY_CONTROL_POINT                        0x2A62 // Pulse Oximetry Control Point
+#define BSAL_UUID_CHAR_RAINFALL                                            0x2A78 // Rainfall
+#define BSAL_UUID_CHAR_RC_FEATURE                                          0x2B1D // RC Feature
+#define BSAL_UUID_CHAR_RC_SETTINGS                                         0x2B1E // RC Settings
+#define BSAL_UUID_CHAR_RECONNECTION_CONFIGURATION_CONTROL_POINT            0x2B1F // Reconnection Configuration Control Point
+#define BSAL_UUID_CHAR_RECORD_ACCESS_CONTROL_POINT                         0x2A52 // Record Access Control Point
+#define BSAL_UUID_CHAR_REFERENCE_TIME_INFORMATION                          0x2A14 // Reference Time Information
+#define BSAL_UUID_CHAR_REMOVABLE                                           0x2A3A // Removable
+#define BSAL_UUID_CHAR_REPORT                                              0x2A4D // Report
+#define BSAL_UUID_CHAR_REPORT_MAP                                          0x2A4B // Report Map
+#define BSAL_UUID_CHAR_RESOLVABLE_PRIVATE_ADDRESS_ONLY                     0x2AC9 // Resolvable Private Address Only
+#define BSAL_UUID_CHAR_RESTING_HEART_RATE                                  0x2A92 // Resting Heart Rate
+#define BSAL_UUID_CHAR_RINGER_CONTROL_POINT                                0x2A40 // Ringer Control point
+#define BSAL_UUID_CHAR_RINGER_SETTING                                      0x2A41 // Ringer Setting
+#define BSAL_UUID_CHAR_ROWER_DATA                                          0x2AD1 // Rower Data
+#define BSAL_UUID_CHAR_RSC_FEATURE                                         0x2A54 // RSC Feature
+#define BSAL_UUID_CHAR_RSC_MEASUREMENT                                     0x2A53 // RSC Measurement
+#define BSAL_UUID_CHAR_SC_CONTROL_POINT                                    0x2A55 // SC Control Point
+#define BSAL_UUID_CHAR_SCAN_INTERVAL_WINDOW                                0x2A4F // Scan Interval Window
+#define BSAL_UUID_CHAR_SCAN_REFRESH                                        0x2A31 // Scan Refresh
+#define BSAL_UUID_CHAR_SCIENTIFIC_TEMPERATURE_CELSIUS                      0x2A3C // Scientific Temperature Celsius
+#define BSAL_UUID_CHAR_SECONDARY_TIME_ZONE                                 0x2A10 // Secondary Time Zone
+#define BSAL_UUID_CHAR_SENSOR_LOCATION                                     0x2A5D // Sensor Location
+#define BSAL_UUID_CHAR_SERIAL_NUMBER_STRING                                0x2A25 // Serial Number String
+#define BSAL_UUID_CHAR_SERVICE_REQUIRED                                    0x2A3B // Service Required
+#define BSAL_UUID_CHAR_SOFTWARE_REVISION_STRING                            0x2A28 // Software Revision String
+#define BSAL_UUID_CHAR_SPORT_TYPE_FOR_AEROBIC_AND_ANAEROBIC_THRESHOLDS     0x2A93 // Sport Type for Aerobic and Anaerobic Thresholds
+#define BSAL_UUID_CHAR_STAIR_CLIMBER_DATA                                  0x2AD0 // Stair Climber Data
+#define BSAL_UUID_CHAR_STEP_CLIMBER_DATA                                   0x2ACF // Step Climber Data
+#define BSAL_UUID_CHAR_STRING                                              0x2A3D // String
+#define BSAL_UUID_CHAR_SUPPORTED_HEART_RATE_RANGE                          0x2AD7 // Supported Heart Rate Range
+#define BSAL_UUID_CHAR_SUPPORTED_INCLINATION_RANGE                         0x2AD5 // Supported Inclination Range
+#define BSAL_UUID_CHAR_SUPPORTED_NEW_ALERT_CATEGORY                        0x2A47 // Supported New Alert Category
+#define BSAL_UUID_CHAR_SUPPORTED_POWER_RANGE                               0x2AD8 // Supported Power Range
+#define BSAL_UUID_CHAR_SUPPORTED_RESISTANCE_LEVEL_RANGE                    0x2AD6 // Supported Resistance Level Range
+#define BSAL_UUID_CHAR_SUPPORTED_SPEED_RANGE                               0x2AD4 // Supported Speed Range
+#define BSAL_UUID_CHAR_SUPPORTED_UNREAD_ALERT_CATEGORY                     0x2A48 // Supported Unread Alert Category
+#define BSAL_UUID_CHAR_SYSTEM_ID                                           0x2A23 // System ID
+#define BSAL_UUID_CHAR_TDS_CONTROL_POINT                                   0x2ABC // TDS Control Point
+#define BSAL_UUID_CHAR_TEMPERATURE                                         0x2A6E // Temperature
+#define BSAL_UUID_CHAR_TEMPERATURE_CELSIUS                                 0x2A1F // Temperature Celsius
+#define BSAL_UUID_CHAR_TEMPERATURE_FAHRENHEIT                              0x2A20 // Temperature Fahrenheit
+#define BSAL_UUID_CHAR_TEMPERATURE_MEASUREMENT                             0x2A1C // Temperature Measurement
+#define BSAL_UUID_CHAR_TEMPERATURE_TYPE                                    0x2A1D // Temperature Type
+#define BSAL_UUID_CHAR_THREE_ZONE_HEART_RATE_LIMITS                        0x2A94 // Three Zone Heart Rate Limits
+#define BSAL_UUID_CHAR_TIME_ACCURACY                                       0x2A12 // Time Accuracy
+#define BSAL_UUID_CHAR_TIME_BROADCAST                                      0x2A15 // Time Broadcast
+#define BSAL_UUID_CHAR_TIME_SOURCE                                         0x2A13 // Time Source
+#define BSAL_UUID_CHAR_TIME_UPDATE_CONTROL_POINT                           0x2A16 // Time Update Control Point
+#define BSAL_UUID_CHAR_TIME_UPDATE_STATE                                   0x2A17 // Time Update State
+#define BSAL_UUID_CHAR_TIME_WITH_DST                                       0x2A11 // Time with DST
+#define BSAL_UUID_CHAR_TIME_ZONE                                           0x2A0E // Time Zone
+#define BSAL_UUID_CHAR_TRAINING_STATUS                                     0x2AD3 // Training Status
+#define BSAL_UUID_CHAR_TREADMILL_DATA                                      0x2ACD // Treadmill Data
+#define BSAL_UUID_CHAR_TRUE_WIND_DIRECTION                                 0x2A71 // True Wind Direction
+#define BSAL_UUID_CHAR_TRUE_WIND_SPEED                                     0x2A70 // True Wind Speed
+#define BSAL_UUID_CHAR_TWO_ZONE_HEART_RATE_LIMIT                           0x2A95 // Two Zone Heart Rate Limit
+#define BSAL_UUID_CHAR_TX_POWER_LEVEL                                      0x2A07 // Tx Power Level
+#define BSAL_UUID_CHAR_UNCERTAINTY                                         0x2AB4 // Uncertainty
+#define BSAL_UUID_CHAR_UNREAD_ALERT_STATUS                                 0x2A45 // Unread Alert Status
+#define BSAL_UUID_CHAR_URI                                                 0x2AB6 // URI
+#define BSAL_UUID_CHAR_USER_CONTROL_POINT                                  0x2A9F // User Control Point
+#define BSAL_UUID_CHAR_USER_INDEX                                          0x2A9A // User Index
+#define BSAL_UUID_CHAR_UV_INDEX                                            0x2A76 // UV Index
+#define BSAL_UUID_CHAR_VO2_MAX                                             0x2A96 // VO2 Max
+#define BSAL_UUID_CHAR_WAIST_CIRCUMFERENCE                                 0x2A97 // Waist Circumference
+#define BSAL_UUID_CHAR_WEIGHT                                              0x2A98 // Weight
+#define BSAL_UUID_CHAR_WEIGHT_MEASUREMENT                                  0x2A9D // Weight Measurement
+#define BSAL_UUID_CHAR_WEIGHT_SCALE_FEATURE                                0x2A9E // Weight Scale Feature
+#define BSAL_UUID_CHAR_WIND_CHILL                                          0x2A79 // Wind Chill
+
+/**
+ * Assigned numbers from www.bluetooth.com/specifications/gatt/descriptors
+ */
+#define BSAL_UUID_DESCRIPTOR_ES_CONFIGURATION                                        0x290B // Environmental Sensing Configuration
+#define BSAL_UUID_DESCRIPTOR_ES_MEASUREMENT                                          0x290C // Environmental Sensing Measurement
+#define BSAL_UUID_DESCRIPTOR_ES_TRIGGER_SETTING                                      0x290D // Environmental Sensing Trigger Setting
+#define BSAL_UUID_DESCRIPTOR_EXTERNAL_REPORT_REFERENCE                               0x2907 // External Report Reference
+#define BSAL_UUID_DESCRIPTOR_GATT_CHARACTERISTIC_AGGREGATE_FORMAT                    0x2905 // Characteristic Aggregate Format
+#define BSAL_UUID_DESCRIPTOR_GATT_CHARACTERISTIC_EXTENDED_PROPERTIES                 0x2900 // Characteristic Extended Properties
+#define BSAL_UUID_DESCRIPTOR_GATT_CHARACTERISTIC_PRESENTATION_FORMAT                 0x2904 // Characteristic Presentation Format
+#define BSAL_UUID_DESCRIPTOR_GATT_CHARACTERISTIC_USER_DESCRIPTION                    0x2901 // Characteristic User Description
+#define BSAL_UUID_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION                0x2902 // Client Characteristic Configuration
+#define BSAL_UUID_DESCRIPTOR_GATT_SERVER_CHARACTERISTIC_CONFIGURATION                0x2903 // Server Characteristic Configuration
+#define BSAL_UUID_DESCRIPTOR_NUMBER_OF_DIGITALS                                      0x2909 // Number of Digitals
+#define BSAL_UUID_DESCRIPTOR_REPORT_REFERENCE                                        0x2908 // Report Reference
+#define BSAL_UUID_DESCRIPTOR_TIME_TRIGGER_SETTING                                    0x290E // Time Trigger Setting
+#define BSAL_UUID_DESCRIPTOR_VALID_RANGE                                             0x2906 // Valid Range
+#define BSAL_UUID_DESCRIPTOR_VALUE_TRIGGER_SETTING                                   0x290A // Value Trigger Setting
+
+//=============================UUID   END============================================
+
+//=================================ATT===============================================
+
+// Attribute Property Flags
+#define BSAL_ATT_P_BROADCAST                  0x01
+#define BSAL_ATT_P_READ                       0x02
+#define BSAL_ATT_P_WRITE_WITHOUT_RESPONSE     0x04
+#define BSAL_ATT_P_WRITE                      0x08
+#define BSAL_ATT_P_NOTIFY                     0x10
+#define BSAL_ATT_P_INDICATE                   0x20
+#define BSAL_ATT_P_AUTHENTICATED_SIGNED_WRITE 0x40
+#define BSAL_ATT_P_EXTENDED_PROPERTIES        0x80
+
+
+// Attribute NOTIFY FLAG
+#define BSAL_GATT_CCC_NONE                              0x0000 /**< The Characteristic Value shall be neither indicated nor notified. */
+#define BSAL_GATT_CCC_NOTIFY                            0x0001 /**< The Characteristic Value shall be notified. */
+#define BSAL_GATT_CCC_INDICATE                          0x0002 /**< The Characteristic Value shall be indicated. */
+#define BSAL_GATT_CCC_NOTIFY_INDICATE                   0x0003 /**< The Characteristic Value shall be both indicated and notified. */
+
+//==========================ADV==============================
+
+/** @defgroup ADV_PARAM_FILTER_POLICY  adv filter policy
+  * @{
+  */
+typedef enum
+{
+    BSAL_GAP_ADV_FILTER_ANY = 0,
+    BSAL_GAP_ADV_FILTER_WHITE_LIST_SCAN,
+    BSAL_GAP_ADV_FILTER_WHITE_LIST_CONN,
+    BSAL_GAP_ADV_FILTER_WHITE_LIST_ALL,
+} T_BSAL_GAP_ADV_FILTER_POLICY;
+/**
+  * @}
+  */
+
+/** @defgroup BTCHANNEL_MAP  BT ADVERTISING CHANNEL MAP
+  * @{
+  */
+#define BSAL_GAP_ADVCHAN_37                          0x01  //!< Advertisement Channel 37
+#define BSAL_GAP_ADVCHAN_38                          0x02  //!< Advertisement Channel 38
+#define BSAL_GAP_ADVCHAN_39                          0x04  //!< Advertisement Channel 39
+#define BSAL_GAP_ADVCHAN_ALL (BSAL_GAP_ADVCHAN_37 | BSAL_GAP_ADVCHAN_38 | BSAL_GAP_ADVCHAN_39) //!< All Advertisement Channels Enabled
+/**
+  * @}
+  */
+
+//BSAL_GAP_TYPE_FLAGS BIT CSS
+#define BSAL_GAP_ADTYPE_FLAGS_LIMITED                            0x01 //!< Discovery Mode: LE Limited Discoverable Mode
+#define BSAL_GAP_ADTYPE_FLAGS_GENERAL                            0x02 //!< Discovery Mode: LE General Discoverable Mode
+#define BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED                0x04 //!< Discovery Mode: BR/EDR Not Supported
+#define BSAL_GAP_ADTYPE_FLAGS_SIMULTANEOUS_LE_BREDR_CONTROLLER   0x08 //!< Discovery Mode: Simultaneous LE and BR/EDR Controller Supported
+#define BSAL_GAP_ADTYPE_FLAGS_SIMULTANEOUS_LE_BREDR_HOST         0x10 //!< Discovery Mode: Simultaneous LE and BR/EDR Host Supported
+
+
+// https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
+//AD TYPE
+#define BSAL_GAP_TYPE_FLAGS                                              0x01 // Flags
+#define BSAL_GAP_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS      0x02 // Incomplete List of 16-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS        0x03 // Complete List of 16-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS      0x04 // Incomplete List of 32-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS        0x05 // Complete List of 32-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS     0x06 // Incomplete List of 128-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS       0x07 // Complete List of 128-bit Service Class UUIDs
+#define BSAL_GAP_TYPE_SHORTENED_LOCAL_NAME                               0x08 // Shortened Local Name
+#define BSAL_GAP_TYPE_COMPLETE_LOCAL_NAME                                0x09 // Complete Local Name
+#define BSAL_GAP_TYPE_TX_POWER_LEVEL                                     0x0A // Tx Power Level
+#define BSAL_GAP_TYPE_CLASS_OF_DEVICE                                    0x0D // Class of Device
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_HASH_C                              0x0E // Simple Pairing Hash C
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_HASH_C_192                          0x0E // Simple Pairing Hash C-192
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_RANDOMIZER_R                        0x0F // Simple Pairing Randomizer R
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_192                    0x0F // Simple Pairing Randomizer R-192
+#define BSAL_GAP_TYPE_DEVICE_ID                                          0x10 // Device ID
+#define BSAL_GAP_TYPE_SECURITY_MANAGER_TK_VALUE                          0x10 // Security Manager TK Value
+#define BSAL_GAP_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS                 0x11 // Security Manager Out of Band Flags
+#define BSAL_GAP_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE                    0x12 // Slave Connection Interval Range
+#define BSAL_GAP_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS          0x14 // List of 16-bit Service Solicitation UUIDs
+#define BSAL_GAP_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS         0x15 // List of 128-bit Service Solicitation UUIDs
+#define BSAL_GAP_TYPE_SERVICE_DATA                                       0x16 // Service Data
+#define BSAL_GAP_TYPE_SERVICE_DATA_16_BIT_UUID                           0x16 // Service Data - 16-bit UUID
+#define BSAL_GAP_TYPE_PUBLIC_TARGET_ADDRESS                              0x17 // Public Target Address
+#define BSAL_GAP_TYPE_RANDOM_TARGET_ADDRESS                              0x18 // Random Target Address
+#define BSAL_GAP_TYPE_APPEARANCE                                         0x19 // Appearance
+#define BSAL_GAP_TYPE_ADVERTISING_INTERVAL                               0x1A // Advertising Interval
+#define BSAL_GAP_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS                        0x1B // LE Bluetooth Device Address
+#define BSAL_GAP_TYPE_LE_ROLE                                            0x1C // LE Role
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_HASH_C_256                          0x1D // Simple Pairing Hash C-256
+#define BSAL_GAP_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256                    0x1E // Simple Pairing Randomizer R-256
+#define BSAL_GAP_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS          0x1F // List of 32-bit Service Solicitation UUIDs
+#define BSAL_GAP_TYPE_SERVICE_DATA_32_BIT_UUID                           0x20 // Service Data - 32-bit UUID
+#define BSAL_GAP_TYPE_SERVICE_DATA_128_BIT_UUID                          0x21 // Service Data - 128-bit UUID
+#define BSAL_GAP_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE           0x22 // LE Secure Connections Confirmation Value
+#define BSAL_GAP_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE                 0x23 // LE Secure Connections Random Value
+#define BSAL_GAP_TYPE_URI                                                0x24 // URI
+#define BSAL_GAP_TYPE_INDOOR_POSITIONING                                 0x25 // Indoor Positioning
+#define BSAL_GAP_TYPE_TRANSPORT_DISCOVERY_DATA                           0x26 // Transport Discovery Data
+#define BSAL_GAP_TYPE_LE_SUPPORTED_FEATURES                              0x27 // LE Supported Features
+#define BSAL_GAP_TYPE_CHANNEL_MAP_UPDATE_INDICATION                      0x28 // Channel Map Update Indication
+#define BSAL_GAP_TYPE_PB_ADV                                             0x29 // PB-ADV
+#define BSAL_GAP_TYPE_MESH_MESSAGE                                       0x2A // Mesh Message
+#define BSAL_GAP_TYPE_MESH_BEACON                                        0x2B // Mesh Beacon
+#define BSAL_GAP_TYPE_3D_INFORMATION_DATA                                0x3D // 3D Information Data
+#define BSAL_GAP_TYPE_MANUFACTURER_SPECIFIC_DATA                         0xFF // Manufacturer Specific Data
+
+//https://www.bluetooth.com/xml-viewer/?src=https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.gap.appearance.xml
+/* LE GAP APPERANCE VALUE*/
+#define BSAL_GAP_APPEARANCE_UNKNOWN                                0
+#define BSAL_GAP_APPEARANCE_GENERIC_PHONE                          64
+#define BSAL_GAP_APPEARANCE_GENERIC_COMPUTER                       128
+#define BSAL_GAP_APPEARANCE_GENERIC_WATCH                          192
+#define BSAL_GAP_APPEARANCE_WATCH_SPORTS_WATCH                     193
+#define BSAL_GAP_APPEARANCE_GENERIC_CLOCK                          256
+#define BSAL_GAP_APPEARANCE_GENERIC_DISPLAY                        320
+#define BSAL_GAP_APPEARANCE_GENERIC_REMOTE_CONTROL                 384
+#define BSAL_GAP_APPEARANCE_GENERIC_EYE_GLASSES                    448
+#define BSAL_GAP_APPEARANCE_GENERIC_TAG                            512
+#define BSAL_GAP_APPEARANCE_GENERIC_KEYRING                        576
+#define BSAL_GAP_APPEARANCE_GENERIC_MEDIA_PLAYER                   640
+#define BSAL_GAP_APPEARANCE_GENERIC_BARCODE_SCANNER                704
+#define BSAL_GAP_APPEARANCE_GENERIC_THERMOMETER                    768
+#define BSAL_GAP_APPEARANCE_THERMOMETER_EAR                        769
+#define BSAL_GAP_APPEARANCE_GENERIC_HEART_RATE_SENSOR              832
+#define BSAL_GAP_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT      833
+#define BSAL_GAP_APPEARANCE_GENERIC_BLOOD_PRESSURE                 896
+#define BSAL_GAP_APPEARANCE_BLOOD_PRESSURE_ARM                     897
+#define BSAL_GAP_APPEARANCE_BLOOD_PRESSURE_WRIST                   898
+#define BSAL_GAP_APPEARANCE_HUMAN_INTERFACE_DEVICE                 960
+#define BSAL_GAP_APPEARANCE_KEYBOARD                               961
+#define BSAL_GAP_APPEARANCE_MOUSE                                  962
+#define BSAL_GAP_APPEARANCE_JOYSTICK                               963
+#define BSAL_GAP_APPEARANCE_GAMEPAD                                964
+#define BSAL_GAP_APPEARANCE_DIGITIZER_TABLET                       965
+#define BSAL_GAP_APPEARANCE_CARD_READER                            966
+#define BSAL_GAP_APPEARANCE_DIGITAL_PEN                            967
+#define BSAL_GAP_APPEARANCE_BARCODE_SCANNER                        968
+#define BSAL_GAP_APPEARANCE_GENERIC_GLUCOSE_METER                  1024
+#define BSAL_GAP_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR         1088
+#define BSAL_GAP_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE         1089
+#define BSAL_GAP_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE         1090
+#define BSAL_GAP_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP          1091
+#define BSAL_GAP_APPEARANCE_GENERIC_CYCLING                        1152
+#define BSAL_GAP_APPEARANCE_CYCLING_CYCLING_COMPUTER               1153
+#define BSAL_GAP_APPEARANCE_CYCLING_SPEED_SENSOR                   1154
+#define BSAL_GAP_APPEARANCE_CYCLING_CADENCE_SENSOR                 1155
+#define BSAL_GAP_APPEARANCE_CYCLING_POWER_SENSOR                   1156
+#define BSAL_GAP_APPEARANCE_CYCLING_SPEED_AND_CADENCE_SENSOR       1157
+#define BSAL_GAP_APPEARANCE_GENERIC_PULSE_OXIMETER                 3136
+#define BSAL_GAP_APPEARANCE_FINGERTIP                              3137
+#define BSAL_GAP_APPEARANCE_WRIST_WORN                             3138
+#define BSAL_GAP_APPEARANCE_GENERIC_WEIGHT_SCALE                   3200
+#define BSAL_GAP_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACTIVITY        5184
+#define BSAL_GAP_APPEARANCE_LOCATION_DISPLAY_DEVICE                5185
+#define BSAL_GAP_APPEARANCE_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE 5186
+#define BSAL_GAP_APPEARANCE_LOCATION_POD                           5187
+#define BSAL_GAP_APPEARANCE_LOCATION_AND_NAVIGATION_POD            5188
+
+//AD_TYPE
+#define BSAL_GAP_ADTYPE_ADV_IND                                               0x00      //!< Connectable undirected advertisement
+#define BSAL_GAP_ADTYPE_ADV_DIRECT_IND                                        0x01      //!< Connectable high duty cycle directed advertisement #define BSAL_GAP_ADTYPE_ADV_SCAN_IND                                          0x02      //!< Scannable undirected advertisement
+#define BSAL_GAP_ADTYPE_ADV_NONCONN_IND                                       0x03      //!< Non-Connectable undirected advertisement
+#define BSAL_GAP_ADTYPE_SCAN_RSP                                              0x04      //!< Connectable low duty cycle directed advertisement
+
+
+//BD_ADDR_TYPE
+typedef enum
+{
+    BSAL_GAP_REMOTE_ADDR_LE_PUBLIC          = 0x00, /**< LE Public device address type. */
+    BSAL_GAP_REMOTE_ADDR_LE_RANDOM          = 0x01, /**< LE Random device address type. */
+    BSAL_GAP_REMOTE_ADDR_LE_PUBLIC_IDENTITY = 0x02, /**< LE Public identity address type. */
+    BSAL_GAP_REMOTE_ADDR_LE_RANDOM_IDENTITY = 0x03, /**< LE Random identity address type. */
+} BSAL_BD_ADDR_TYPE;
+
+
+//bond===
+/** @defgroup BSAL_GAP_AUTH_TYPE GAP Common Macros
+  * @{
+  */
+#define BSAL_GAP_AUTHEN_BIT_NO_BONDING            0      //!<  No authentication required.
+#define BSAL_GAP_AUTHEN_BIT_BONDING_FLAG          0x0001 //!<  Bonding is required   
+#define BSAL_GAP_AUTHEN_BIT_MITM_FLAG             0x0004 //!<  Mitm is preferred
+#define BSAL_GAP_AUTHEN_BIT_SC_FLAG               0x0008 //!<  Secure connection is preferred
+#define BSAL_GAP_AUTHEN_BIT_KEYPRESS_FLAG         0x0010 //!<  keypress
+
+/** @brief I/O Capabilities */
+typedef enum
+{
+    BSAL_GAP_IO_CAP_DISPLAY_ONLY,        //!<  Only a Display present, no Keyboard or Yes/No Keys.
+    BSAL_GAP_IO_CAP_DISPLAY_YES_NO,      //!<  Display and Yes/No Keys present.
+    BSAL_GAP_IO_CAP_KEYBOARD_ONLY,       //!<  Only a Keyboard present, no Display.
+    BSAL_GAP_IO_CAP_NO_INPUT_NO_OUTPUT,  //!<  No input/output capabilities.
+    BSAL_GAP_IO_CAP_KEYBOARD_DISPLAY,    //!<  Keyboard and Display present.
+} BSAL_GAP_IO_CAP;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

+ 70 - 0
inc/bsal_stack_api.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_STACK_API_H__
+#define __BSAL_STACK_API_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bsal_common.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+/**
+* BSAL compute the sum of the srv handle number.
+*
+* @param[in] p_srv the service table of the p_srv
+* @param[out] att_res the result of the att resource
+* @Note  compute the number of the service
+*/
+uint8_t bsal_util_sum_handle_num(struct bsal_gatt_app_srv_def *p_srv, bsal_gatt_res_t *att_res);
+
+/**
+* BSAL save the profile
+*
+* @param[in] stack_ptr the point of the stack ptr
+* @param[in] handle the start_handle of the device
+* @param[in] callback the callback function of the service
+* @param[in] uuid the uuid of the service
+* @Note
+*/
+BSAL_STATUS bsal_profile_insert(void *stack_ptr, uint16_t handle, void *callback, bsal_uuid_any_t uuid);
+
+/**
+* BSAL Stack ready callback
+*
+* @param[in] stack_ptr the point of the stack ptr
+* @param[in] status true is the stack ready, false is stack fail
+* @Note
+*/
+int bsal_stack_ready(void *stack_ptr, bool status);
+
+/**
+* BSAL Stack ready callback
+*
+* @param[in] stack_ptr the point of the stack ptr
+* @param[in] conn_handle the conn_handle of the link
+* @param[in] conn_status the connect status of the link
+* @param[in] disconnect_status the disconnect reason of the link
+* @Note  callback the link status of the devcie
+*/
+int bsal_gap_connect_status(void *stack_ptr, uint16_t conn_handle, uint8_t connect_status, uint16_t disconnect_status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+

+ 527 - 0
port/NIMBLE/bsal_nimble.c

@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_int.h"
+#include "bsal_stack_api.h"
+#ifdef PKG_BSAL_NIMBLE_STACK
+#include "bsal_nimble.h"
+bsal_stack_obj_t nimble_obj;
+#endif
+
+static void *bsal_get_local_stack_obj()
+{
+    return &nimble_obj;
+}
+#ifdef PKG_BSAL_NIMBLE_STACK
+static int
+bsal_nimble_gap_event(struct ble_gap_event *event, void *arg)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+    uint16_t cccbits = 0;
+    switch (event->type)
+    {
+    case BLE_GAP_EVENT_CONNECT:
+        if (event->connect.status == 0)
+        {
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            //save the connect_handle;
+            //BSAL CALLBACK
+            bsal_gap_connect_status(arg, event->connect.conn_handle, BSAL_GAP_CONN_STATE_CONNECTED, 0);
+        }
+        break;
+    case BLE_GAP_EVENT_DISCONNECT:
+        //BSAL CALLBACK
+        bsal_gap_connect_status(arg, event->connect.conn_handle, BSAL_GAP_CONN_STATE_DISCONNECTED, 0);
+        break;
+    case BLE_GAP_EVENT_SUBSCRIBE:
+        /* TODO NOTIFY ENABLE DISABLE*/
+        MODLOG_DFLT(INFO, "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);
+
+        if (event->subscribe.cur_notify == 1)
+        {
+            cccbits |= BSAL_GATT_CCC_NOTIFY;
+        }
+
+        if (event->subscribe.cur_indicate == 1)
+        {
+            cccbits |= BSAL_GATT_CCC_INDICATE;
+        }
+        //BSAL CALLBACK
+        bsal_gatt_cccd_callback_event_by_handle(bsal_get_local_stack_obj(), event->subscribe.conn_handle, event->subscribe.attr_handle + 1,  cccbits);
+        break;
+    default:
+        break;
+    }
+    return 0;
+}
+//===============================================STACK ABOUT CODE=================================
+
+
+static void
+basl_nimble_on_reset(int reason)
+{
+    MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
+    //BSAL CALLBACK
+    bsal_stack_ready(bsal_get_local_stack_obj(), false);
+    while (1);
+}
+
+static void
+bsal_nimble_on_sync(void)
+{
+    int rc;
+    //BSAL CALLBACK
+    bsal_stack_ready(bsal_get_local_stack_obj(), true);
+}
+
+static void
+bsal_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:
+        MODLOG_DFLT(INFO, "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:
+        MODLOG_DFLT(INFO, "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);
+        //load the last srv handle
+        bsal_srv_create_att_by_handle(bsal_get_local_stack_obj(), ctxt->chr.val_handle, ctxt->chr.chr_def->min_key_size);
+        break;
+    case BLE_GATT_REGISTER_OP_DSC:
+
+        /* TODO no need templete*/
+        MODLOG_DFLT(INFO, "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;
+    }
+}
+
+
+
+int
+bsal_ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle,
+                        struct ble_gatt_access_ctxt *ctxt,
+                        void *arg)
+{
+    int rc;
+
+    uint16_t p_length;
+    uint8_t *pp_value;
+
+//     *     o  BLE_GATT_ACCESS_OP_READ_CHR
+//     *     o  BLE_GATT_ACCESS_OP_WRITE_CHR
+//     *     o  BLE_GATT_ACCESS_OP_READ_DSC
+//     *     o  BLE_GATT_ACCESS_OP_WRITE_DSC
+
+    switch (ctxt->op)
+    {
+    case BLE_GATT_ACCESS_OP_READ_CHR:
+    case BLE_GATT_ACCESS_OP_READ_DSC:
+        bsal_gatt_read_callback_event_by_handle(bsal_get_local_stack_obj(), conn_handle, *ctxt->chr->val_handle, &p_length,  &pp_value);
+        rc = os_mbuf_append(ctxt->om, (const void *) pp_value, p_length);
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+        break;
+    case BLE_GATT_ACCESS_OP_WRITE_CHR:
+    case BLE_GATT_ACCESS_OP_WRITE_DSC:
+        bsal_gatt_write_callback_event_by_handle(bsal_get_local_stack_obj(), conn_handle, *ctxt->chr->val_handle, ctxt->om->om_len,  ctxt->om->om_data);
+        break;
+    default:
+        break;
+    }
+}
+#endif
+//=================================================END============================================
+
+//================================BSAL.C==========================
+static void bsal_stack_int_init(uint8_t stack_type)
+{
+#ifdef PKG_BSAL_NIMBLE_STACK
+    ble_hs_cfg.reset_cb = basl_nimble_on_reset; //fail callback
+    ble_hs_cfg.sync_cb = bsal_nimble_on_sync;
+    ble_hs_cfg.gatts_register_cb = bsal_gatt_svr_register_cb;
+    ble_hs_cfg.gatts_register_arg = bsal_get_local_stack_obj();
+    ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+#endif
+}
+
+static void bsal_stack_int_startup(void)
+{
+#ifdef PKG_BSAL_NIMBLE_STACK
+    ble_hs_thread_startup();
+#endif
+}
+
+
+static BSAL_STATUS bsal_stack_int_le_adv_enable(bool enable)
+{
+    bsal_stack_obj_t *p_bsal_stack =  bsal_get_local_stack_obj();
+
+    if (enable == true)
+    {
+        /* ENABLE ADV */
+#ifdef PKG_BSAL_NIMBLE_STACK
+        struct ble_gap_adv_params adv_param;
+        memset(&adv_param, 0, sizeof(struct ble_gap_adv_params));
+
+        if (p_bsal_stack->bsal_info.adv_param.adv_type == BSAL_GAP_ADTYPE_ADV_IND)
+        {
+            adv_param.conn_mode = BLE_GAP_CONN_MODE_UND;
+            adv_param.disc_mode = BLE_GAP_DISC_MODE_GEN;
+        }
+
+        adv_param.channel_map = p_bsal_stack->bsal_info.adv_param.channel_map;
+        adv_param.filter_policy = p_bsal_stack->bsal_info.adv_param.filter_policy;
+        adv_param.itvl_max = p_bsal_stack->bsal_info.adv_param.adv_int_max;
+        adv_param.itvl_min = p_bsal_stack->bsal_info.adv_param.adv_int_min;
+        ble_addr_t direct_address;
+        direct_address.type = p_bsal_stack->bsal_info.adv_param.direct_address_type;
+        memcpy(direct_address.val, p_bsal_stack->bsal_info.adv_param.direct_address, 6);
+        ble_gap_adv_start(p_bsal_stack->bsal_info.adv_param.own_address_type, &direct_address , BLE_HS_FOREVER,
+                          &adv_param, bsal_nimble_gap_event, p_bsal_stack);
+#endif
+    }
+    else
+    {
+        /* DISABLE ADV */
+#ifdef PKG_BSAL_NIMBLE_STACK
+        ble_gap_adv_stop();
+#endif
+    }
+    return BSAL_RESULT_SUCCESS;
+}
+
+//for app
+static BSAL_STATUS bsal_int_srv_profile_srv_begin(bool is_continue, uint8_t service_num, void *p_fnc_callback)
+{
+    return BSAL_RESULT_SUCCESS;
+}
+
+//common utils
+static BSAL_STATUS bsal_int_srv_profile_reg_service(
+    struct bsal_gatt_app_srv_def *p_srv,
+    void *p_func  //callback
+)
+{
+#ifdef PKG_BSAL_NIMBLE_STACK
+    uint16_t att_num = 0;
+    uint8_t att_index = 0;
+    uint16_t sum_of_descript = 0;
+    uint8_t write_index = 0;
+    uint8_t i = 0;
+    uint8_t j = 0;
+    uint8_t x = 0;
+    uint8_t y = 0;
+    bsal_gatt_res_t res;
+    bsal_util_sum_handle_num(p_srv, &res);
+    att_num  = res.attrs;
+    bsal_stack_obj_t *p_bsal_stack =  bsal_get_local_stack_obj();
+    //malloc memory:
+    struct ble_gatt_svc_def *nimble_srvs = bsal_osif_malloc(sizeof(struct ble_gatt_svc_def) * (res.svcs + 1));
+    struct bsal_gatt_app_srv_def *tmp_srv;
+    bsal_gatt_chr_def_t      *tmp_chr;
+    uint8_t srv_idx = 0;
+    uint8_t chr_idx = 0;
+    uint8_t dsc_idx = 0;
+
+    //combine the srv
+    for (i = 0; p_srv[i].type != 0; i++)
+    {
+        tmp_srv = p_srv + i;
+
+        //add service============================================
+        if ((tmp_srv->type != BSAL_GATT_UUID_PRIMARY_SERVICE) &&
+                (tmp_srv->type != BSAL_GATT_UUID_SECONDARY_SERVICE))
+        {
+            return BSAL_RESULT_FAIL;
+        }
+        nimble_srvs[srv_idx].type = BLE_GATT_SVC_TYPE_PRIMARY;
+        write_index++;
+        if (tmp_srv->uuid->u_type  == BSAL_UUID_TYPE_16BIT)
+        {
+            ble_uuid16_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid16_t));
+            tmp_uuid->u.type = BLE_UUID_TYPE_16;
+            tmp_uuid->value = tmp_srv->uuid->u16.value;
+            nimble_srvs->uuid = &tmp_uuid->u;
+        }
+        else if (tmp_srv->characteristics[x].uuid->u_type == BSAL_UUID_TYPE_128BIT)
+        {
+
+        }
+        write_index++;
+        //add include=============================================================
+        if (tmp_srv->includes != NULL)
+        {
+            for (j = 0; tmp_srv->includes[j] != NULL; j++)
+            {
+//               att_res->attrs++;
+//               att_res->incs++;
+                //add include /*TODO*/
+                write_index++;
+            }
+        }
+        //add char=========================================================
+        if (tmp_srv->characteristics != NULL)
+        {
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                //figure the chr_num
+            }
+            write_index++;
+            //write_index++;
+            struct ble_gatt_chr_def *nimble_chrs = bsal_osif_malloc(sizeof(struct ble_gatt_chr_def) * (x + 1));
+            nimble_srvs[srv_idx].characteristics = nimble_chrs;
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                tmp_chr = tmp_srv->characteristics + x;
+
+                if (tmp_chr->uuid->u_type == BSAL_UUID_TYPE_16BIT)
+                {
+                    ble_uuid16_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid16_t));
+                    tmp_uuid->u.type = BLE_UUID_TYPE_16;
+                    tmp_uuid->value = tmp_srv->characteristics[x].uuid->u16.value;
+
+                    nimble_chrs[x].uuid = &tmp_uuid->u;
+                }
+                else if (tmp_srv->characteristics[x].uuid->u_type == BSAL_UUID_TYPE_128BIT)
+                {
+
+                }
+                nimble_chrs[x].access_cb = bsal_ble_svc_bas_access;
+                nimble_chrs[x].arg = bsal_get_local_stack_obj();
+                nimble_chrs[x].flags = tmp_srv->characteristics[x].properties;
+                nimble_chrs[x].min_key_size = tmp_srv->characteristics[x].value_length;
+                nimble_chrs[x].val_handle = bsal_osif_malloc(tmp_srv->characteristics[x].value_length);
+                //read
+
+                if (BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission) !=  0) ///ENCRYTYED
+                {
+                    /* TODO*/
+                    if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission)))
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ_AUTHEN;
+                    }
+                    else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission)))
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ_AUTHOR;
+                    }
+                    else
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ;
+                    }
+                }
+                //write
+                if (BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission) !=  0) ///ENCRYTYED
+                {
+                    /* TODO*/
+                    if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission)))
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE_AUTHEN;
+                    }
+                    else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission)))
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE_AUTHOR;
+                    }
+                    else
+                    {
+                        nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE;
+                    }
+                }
+                //no need add NOTIFY STACK WILL ADD
+                write_index++;
+            }
+        }
+    }
+
+    for (i = 0; p_srv[i].type != 0; i++)
+    {
+        bsal_uuid_any_t srv_uuid;
+        srv_uuid.u_type = BSAL_UUID_TYPE_16BIT; //16bit
+        srv_uuid.u16.value = p_srv[i].uuid->u16.value;
+        tmp_srv = p_srv + i;
+        p_bsal_stack->g_att_index++;
+        bsal_profile_insert(bsal_get_local_stack_obj(), p_bsal_stack->g_att_index, p_func, srv_uuid);
+        if (tmp_srv->characteristics != NULL)
+        {
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                //ONLY READ NEED ADD THIS ATT
+                tmp_chr = tmp_srv->characteristics + x;
+                p_bsal_stack->g_att_index++;
+                p_bsal_stack->g_att_index++;
+                bsal_att_create_entry(bsal_get_local_stack_obj(), p_bsal_stack->g_att_index, tmp_chr->value_length);
+
+                if ((tmp_srv->characteristics[x].properties & BSAL_ATT_P_NOTIFY) || (tmp_srv->characteristics[x].properties & BSAL_ATT_P_INDICATE))
+                {
+                    p_bsal_stack->g_att_index ++;
+                }
+            }
+        }
+    }
+
+    int rc;
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = ble_gatts_count_cfg(nimble_srvs);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = ble_gatts_add_svcs(nimble_srvs);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
+    return BSAL_RESULT_SUCCESS;
+}
+
+//FOR APP
+static BSAL_STATUS bsal_int_srv_profile_srv_end(void)
+{
+    //all register service is end
+    //NIMBLE NO NEED
+    return BSAL_RESULT_SUCCESS;
+}
+static uint32_t bsal_stack_get_unique_handle(uint16_t start_handle, uint16_t offset_handle)
+{
+    return (start_handle + offset_handle);
+}
+static BSAL_STATUS bsal_int_stack_srv_send_data(uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_len, const uint8_t *value, uint8_t send_type)
+{
+#ifdef PKG_BSAL_NIMBLE_STACK
+    int rc;
+    struct os_mbuf *om;
+    /*TODO*/
+    om = ble_hs_mbuf_from_flat(value, value_len);
+    if (send_type != BSAL_SEND_DATA_TYPE_INDICATION)
+    {
+        rc = ble_gattc_notify_custom(conn_id, bsal_stack_get_unique_handle(service_id, offset_handle), om);
+    }
+    else
+    {
+        rc = ble_gattc_indicate_custom(conn_id, bsal_stack_get_unique_handle(service_id, offset_handle), om);
+    }
+#endif
+
+    return BSAL_RESULT_SUCCESS;
+}
+
+static void bsal_stack_set_bond_param(bsal_bond_param_t *bond_param)
+{
+#ifdef PKG_BSAL_NIMBLE_STACK
+    /* TODO*/
+
+    if (bond_param->bonding_flag == false)
+    {
+        ble_hs_cfg.sm_bonding = 0;
+        return;
+    }
+    else
+    {
+        ble_hs_cfg.sm_bonding = 1;
+    }
+    //set iocapability
+    ble_hs_cfg.sm_io_cap = bond_param->io_capability;
+    //set mitm
+    if (bond_param->io_capability != BSAL_GAP_IO_CAP_NO_INPUT_NO_OUTPUT)
+    {
+        //maybe have mitm
+        if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_MITM_FLAG)
+        {
+            ble_hs_cfg.sm_mitm = 1;
+        }
+        if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_SC_FLAG)
+        {
+            ble_hs_cfg.sm_sc = 1;
+        }
+        if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_KEYPRESS_FLAG)
+        {
+            ble_hs_cfg.sm_keypress = 1;
+        }
+    }
+
+    if (bond_param->oob_flag == true)
+    {
+        ble_hs_cfg.sm_oob_data_flag = 1;
+    }
+#endif
+}
+
+static void bsal_stack_le_set_adv_param(bsal_adv_param_t *adv_param)
+{
+    if (adv_param->set_param_flag & BSAL_SET_LE_ADV_PARAM)
+    {
+        //save to  local adv_param
+        bsal_stack_obj_t *p_bsal_stack =  bsal_get_local_stack_obj();
+        //save the adv param
+        memcpy(&p_bsal_stack->bsal_info.adv_param, adv_param, sizeof(bsal_adv_param_t));
+    }
+    else if (adv_param->set_param_flag & BSAL_SET_LE_ADV_DATA)
+    {
+#ifdef PKG_BSAL_NIMBLE_STACK
+        ble_gap_adv_set_data((void *)((uint32_t)(adv_param->adv_data) + 1), adv_param->adv_data[0]);
+#endif
+    }
+    else if (adv_param->set_param_flag & BSAL_SET_LE_SCAN_RSP_DATA)
+    {
+#ifdef PKG_BSAL_NIMBLE_STACK
+        ble_gap_adv_rsp_set_data((void *)((uint32_t)(adv_param->scan_rsp_data) + 1), adv_param->scan_rsp_data[0]);
+#endif
+    }
+}
+static void bsal_stack_set_gas_param(bsal_gaps_param_t *adv_param)
+{
+    /* TODO*/
+    uint8_t  slave_init_mtu_req = false;
+}
+
+bsal_stack_obj_t nimble_obj =
+{
+    .bsal_ops = {
+        .init                     = bsal_stack_int_init ,
+        .startup                  = bsal_stack_int_startup,
+        .le_adv_enable            = bsal_stack_int_le_adv_enable,
+        .le_srv_reg_begin         = bsal_int_srv_profile_srv_begin,
+        .le_srv_reg_fun           = bsal_int_srv_profile_reg_service,
+        .le_srv_reg_end           = bsal_int_srv_profile_srv_end,
+        .le_srv_send_data         = bsal_int_stack_srv_send_data,
+        .cov_handle_to_u_handle   = bsal_stack_get_unique_handle,
+        .set_bond_param           = bsal_stack_set_bond_param,
+        .le_set_adv_param         = bsal_stack_le_set_adv_param,
+        .set_gaps_param           = bsal_stack_set_gas_param,
+        //callback
+    },
+};
+
+
+

+ 37 - 0
port/NIMBLE/bsal_nimble.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_RTK_H__
+#define __BSAL_RTK_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "host/ble_hs.h"
+#include "sysinit/sysinit.h"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
+
+
+
+
+
+
+

+ 89 - 0
port/NIMBLE/bsal_osif.c

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "bsal_osif.h"
+
+void *bsal_osif_malloc(uint32_t len)
+{
+    void *p = NULL;
+    p = rt_malloc(len);
+    memset(p, 0, len);
+    return p;
+}
+
+void bsal_osif_free(void *p)
+{
+    rt_free(p);
+}
+
+#if 0
+int bsal_osif_printf_warn(const char *fmt, ...)
+{
+    rt_kprintf("\r\n [BSAL][WARN]:");
+    va_list args;
+    va_start(args, fmt);
+    rt_kprintf(fmt, args);
+    va_end(args);
+    return 0;
+}
+
+int bsal_osif_printf_info(const char *fmt, ...)
+{
+    rt_kprintf("\r\n [BSAL][INFO]:");
+    va_list args;
+    va_start(args, fmt);
+    rt_kprintf(fmt, args);
+    va_end(args);
+    return 0;
+}
+
+int bsal_osif_printf_dbg(const char *fmt, ...)
+{
+    rt_kprintf("\r\n [BSAL][DEBUG]:");
+    va_list args;
+    va_start(args, fmt);
+    rt_kprintf(fmt, args);
+    va_end(args);
+    rt_kprintf("\r\n");
+    return 0;
+}
+
+
+int bsal_osif_printf_err(const char *fmt, ...)
+{
+    rt_kprintf("\r\n [BSAL][ERROR]:");
+    va_list args;
+    va_start(args, fmt);
+    rt_kprintf(fmt, args);
+    va_end(args);
+    rt_kprintf("\r\n");
+    return 0;
+}
+#endif
+
+void bsal_osif_delay(uint32_t ms)
+{
+    rt_thread_mdelay(ms);
+}
+
+
+
+
+
+
+
+
+

+ 72 - 0
port/empty_stack/bsal_osal_empty.c

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "bsal_osif.h"
+
+
+void *bsal_osif_malloc(uint32_t len)
+{
+    void *p = NULL;
+
+/* TODO */
+    return p;
+}
+
+void bsal_osif_free(void *p)
+{
+	/* TODO */
+}
+
+#if 0
+int bsal_osif_printf_warn(const char *fmt, ...)
+{
+/* TODO */
+    return 0;
+}
+
+int bsal_osif_printf_info(const char *fmt, ...)
+{
+/* TODO */
+    return 0;
+}
+
+int bsal_osif_printf_dbg(const char *fmt, ...)
+{
+/* TODO */
+    return 0;
+}
+
+
+int bsal_osif_printf_err(const char *fmt, ...)
+{
+/* TODO */
+    return 0;
+}
+#endif
+
+void bsal_osif_delay(uint32_t ms)
+{
+/* TODO */
+	
+}
+
+
+
+
+
+
+
+
+

+ 136 - 0
port/empty_stack/bsal_stack_empty.c

@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_int.h"
+#include "bsal_stack_api.h"
+
+
+//#include "bsal_stack.h"
+
+bsal_stack_obj_t rtk_obj;
+
+static void *bsal_get_rtk_obj()
+{
+    return &rtk_obj;
+}
+//================================BSAL.C==========================
+static void bsal_rtk_stack_init(uint8_t stack_type)
+{
+	    /* TODO*/
+}
+
+static void bsal_rtk_stack_startup(void)
+{
+      /* TODO*/
+}
+
+static BSAL_STATUS bsal_rtk_le_adv_enable(bool enable)
+{
+    if (enable == true)
+    {
+      /* TODO*/
+    }
+    else
+    {
+			/* TODO*/
+    }
+    return BSAL_RESULT_SUCCESS;
+}
+//for app
+static BSAL_STATUS bsal_srv_profile_srv_begin(bool is_continue, uint8_t service_num, void *p_fnc_callback)
+{
+	  /* TODO */
+    return BSAL_RESULT_SUCCESS;
+}
+//common utils
+static BSAL_STATUS bsal_srv_profile_reg_service(
+    struct bsal_gatt_app_srv_def *p_srv,
+    void *p_func  //callback
+)
+{
+    uint16_t att_num = 0;
+    uint8_t att_index = 0;
+    uint16_t sum_of_descript = 0;
+    uint8_t write_index = 0;
+    uint8_t i = 0;
+    uint8_t j = 0;
+    uint8_t x = 0;
+    uint8_t y = 0;
+
+
+    bsal_gatt_res_t res;
+    bsal_util_sum_handle_num(p_srv, &res);
+    att_num  = res.attrs;
+    return BSAL_RESULT_SUCCESS;
+}
+
+
+//FOR APP
+static BSAL_STATUS bsal_srv_profile_srv_end(void)
+{
+    //all register service is end
+    return BSAL_RESULT_SUCCESS;
+}
+
+static BSAL_STATUS bsal_stack_srv_send_data(uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_len, const uint8_t *value, uint8_t send_type)
+{
+	  /* TODO */
+    return BSAL_RESULT_FAIL;
+}
+
+static uint32_t bsal_stack_rtk_get_unique_handle(uint16_t start_id, uint16_t offset_handle)
+{
+	  /* TODO */
+    return 0;
+}
+
+static void bsal_stack_rtk_set_bond_param(bsal_bond_param_t *bond_param)
+{
+    uint8_t  auth_pair_mode;
+    uint16_t auth_flags;
+     /* TODO */
+}
+
+static void bsal_rtk_le_set_adv_param(bsal_adv_param_t *adv_param)
+{
+/* TODO*/
+}
+static void bsal_rtk_set_gas_param(bsal_gaps_param_t *adv_param)
+{
+    uint8_t  slave_init_mtu_req = false;
+/* TODO*/
+}
+
+bsal_stack_obj_t rtk_obj =
+{
+    .bsal_ops = {
+        .init                                                = bsal_rtk_stack_init,
+        .startup                                             = bsal_rtk_stack_startup,
+        .le_adv_enable                                       = bsal_rtk_le_adv_enable,
+        .le_srv_reg_begin                                    = bsal_srv_profile_srv_begin,
+        .le_srv_reg_fun                                      = bsal_srv_profile_reg_service,
+        .le_srv_reg_end                                      = bsal_srv_profile_srv_end,
+        .le_srv_send_data                                    = bsal_stack_srv_send_data,
+        .cov_handle_to_u_handle                              = bsal_stack_rtk_get_unique_handle,
+        .set_bond_param                                      = bsal_stack_rtk_set_bond_param,
+        .le_set_adv_param                                    = bsal_rtk_le_set_adv_param,
+        .set_gaps_param                                      = bsal_rtk_set_gas_param,
+        //callback
+    },
+};
+
+
+

+ 31 - 0
port/empty_stack/bsal_stack_empty.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_STACK_H__
+#define __BSAL_STACK_H__
+
+/**
+ * @brief  Initialize App task
+ * @return void
+ */
+
+
+
+#endif
+
+
+
+
+
+
+
+
+

+ 39 - 0
port/realtek/bsal_osif.c

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "bsal_osif.h"
+#include "os_mem.h"
+#include "os_sched.h"
+
+
+void *bsal_osif_malloc(uint32_t len)
+{
+    void *p = NULL;
+    p = os_mem_alloc(RAM_TYPE_DATA_ON, len);
+    memset(p, 0, len);
+    return p;
+}
+
+void bsal_osif_free(void *p)
+{
+    os_mem_free(p);
+}
+
+void bsal_osif_delay(uint32_t ms)
+{
+    os_delay(ms);
+}
+
+

+ 990 - 0
port/realtek/bsal_rtk.c

@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_int.h"
+#include "bsal_stack_api.h"
+
+
+#include "bsal_rtk.h"
+
+bsal_stack_obj_t rtk_obj;
+
+static void *bsal_get_rtk_obj()
+{
+    return &rtk_obj;
+}
+//================================BSAL.C==========================
+static void bsal_rtk_stack_init(uint8_t stack_type)
+{
+#define APP_MAX_LINKS 1
+    le_gap_init(APP_MAX_LINKS);   //if changed must be removed from here
+    /* Device name and device appearance */
+//    uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN;
+#ifdef SOC_RTL_8762D
+	   gap_lib_init();
+#endif
+    le_register_app_cb(bsal_app_gap_callback);
+}
+
+static void bsal_rtk_stack_startup(void)
+{
+    app_task_init();
+}
+
+static BSAL_STATUS bsal_rtk_le_adv_enable(bool enable)
+{
+    if (enable == true)
+    {
+        le_adv_start();
+    }
+    else
+    {
+        le_adv_stop();
+    }
+    return BSAL_RESULT_SUCCESS;
+}
+//for app
+static BSAL_STATUS bsal_srv_profile_srv_begin(bool is_continue, uint8_t service_num, void *p_fnc_callback)
+{
+    server_init(service_num);
+    //get local obj,
+    //register obj
+    bsal_stack_obj_t *p_bsal_stack =  bsal_get_rtk_obj();
+    //add 0xffff
+    p_bsal_stack->bsal_srv_objs =  bsal_osif_malloc((service_num + 1) * sizeof(bsal_srv_callback_t));
+    p_bsal_stack->srv_num = service_num + 1;
+    //server_builtin_service_reg(true);
+    //save the profile num;
+    server_register_app_cb(bsal_app_profile_callback);
+
+    bsal_uuid_any_t srv_uuid;
+    srv_uuid.u_type = BSAL_UUID_TYPE_16BIT; //16bit
+    srv_uuid.u16.value = 0xffff;//p_srv[i].uuid->u16.value;
+    // add the generate uuid for except common profile
+    bsal_profile_insert(p_bsal_stack, 0xffff, p_fnc_callback, srv_uuid);
+
+    return BSAL_RESULT_SUCCESS;
+}
+//common utils
+static BSAL_STATUS bsal_srv_profile_reg_service(
+    struct bsal_gatt_app_srv_def *p_srv,
+    void *p_func  //callback
+)
+{
+    uint16_t att_num = 0;
+    uint8_t att_index = 0;
+    uint16_t sum_of_descript = 0;
+    uint8_t write_index = 0;
+    uint8_t i = 0;
+    uint8_t j = 0;
+    uint8_t x = 0;
+    uint8_t y = 0;
+    bsal_stack_obj_t *p_bsal_stack =  bsal_get_rtk_obj();
+
+    bsal_gatt_res_t res;
+    bsal_util_sum_handle_num(p_srv, &res);
+    att_num  = res.attrs;
+    T_ATTRIB_APPL *rtk_table = bsal_osif_malloc(sizeof(T_ATTRIB_APPL) * att_num);
+    //primary service
+    struct bsal_gatt_app_srv_def *tmp_srv;
+    bsal_gatt_chr_def_t      *tmp_chr;
+
+    for (i = 0; p_srv[i].type != 0; i++)
+    {
+        //service
+        tmp_srv = p_srv + i;
+        if ((tmp_srv->type != BSAL_GATT_UUID_PRIMARY_SERVICE) &&
+                (tmp_srv->type != BSAL_GATT_UUID_SECONDARY_SERVICE))
+        {
+            return BSAL_RESULT_FAIL;
+        }
+//          att_res->attrs++;
+//                  att_res->svcs++;
+        if (tmp_srv->uuid->u_type == BSAL_UUID_TYPE_16BIT)
+        {
+            rtk_table[write_index].type_value[0] = LO_WORD(tmp_srv->type);
+            rtk_table[write_index].type_value[1] = HI_WORD(tmp_srv->type);
+            rtk_table[write_index].type_value[2] = LO_WORD(tmp_srv->uuid->u16.value);
+            rtk_table[write_index].type_value[3] = HI_WORD(tmp_srv->uuid->u16.value);
+            rtk_table[write_index].value_len = UUID_16BIT_SIZE;
+            rtk_table[write_index].p_value_context = NULL;
+            rtk_table[write_index].permissions = GATT_PERM_READ;
+            rtk_table[write_index].flags = (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE);
+        }
+        else if (tmp_srv->uuid->u_type == BSAL_UUID_TYPE_128BIT)
+        {
+            rtk_table[write_index].type_value[0] = LO_WORD(BSAL_GATT_UUID_PRIMARY_SERVICE);
+            rtk_table[write_index].type_value[1] = HI_WORD(BSAL_GATT_UUID_PRIMARY_SERVICE);
+            rtk_table[write_index].p_value_context = tmp_srv->uuid->u128.value;
+            rtk_table[write_index].value_len = UUID_128BIT_SIZE;
+            rtk_table[write_index].permissions = GATT_PERM_READ;
+            rtk_table[write_index].flags = (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE);
+        }
+        write_index++;
+        if (tmp_srv->includes != NULL)
+        {
+            for (j = 0; tmp_srv->includes[j] != NULL; j++)
+            {
+//                                att_res->attrs++;
+//                                att_res->incs++;
+                //add include /*TODO*/
+            }
+        }
+
+        if (tmp_srv->characteristics != NULL)
+        {
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                tmp_chr = tmp_srv->characteristics + x;
+                if (tmp_chr->uuid->u_type == BSAL_UUID_TYPE_16BIT)
+                {
+                    /* <<Characteristic>> declear */
+                    rtk_table[write_index].flags = (ATTRIB_FLAG_VALUE_INCL);
+                    rtk_table[write_index].type_value[0] = LO_WORD(GATT_UUID_CHARACTERISTIC);
+                    rtk_table[write_index].type_value[1] = HI_WORD(GATT_UUID_CHARACTERISTIC);
+                    rtk_table[write_index].type_value[2] = LO_WORD(tmp_chr->properties & 0xff);
+                    rtk_table[write_index].type_value[3] = HI_WORD(tmp_chr->properties >> 8);
+                    rtk_table[write_index].permissions = GATT_PERM_READ;
+                    rtk_table[write_index].value_len = tmp_chr->value_length;
+
+                    write_index++;
+                    /* <<Characteristic>> value */
+                    rtk_table[write_index].flags = ATTRIB_FLAG_VALUE_APPL;
+                    rtk_table[write_index].type_value[0] = LO_WORD(tmp_chr->uuid->u16.value);
+                    rtk_table[write_index].type_value[1] = HI_WORD(tmp_chr->uuid->u16.value);
+                    if (BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission) !=  0) ///ENCRYTYED
+                    {
+                        /* TODO*/
+                        if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission)))
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_READ_AUTHEN_REQ; //tmp_chr->permission;
+                        }
+                        else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission)))
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_READ_AUTHOR_REQ;
+                        }
+                        else
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_READ;
+                        }
+                    }
+                    else
+                    {
+
+                    }
+                    //write
+                    if (BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission) !=  0) ///ENCRYTYED
+                    {
+                        /* TODO*/
+                        if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission)))
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_WRITE_AUTHEN_REQ; //tmp_chr->permission;
+                        }
+                        else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission)))
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_WRITE_AUTHOR_REQ;
+                        }
+                        else
+                        {
+                            rtk_table[write_index].permissions |= GATT_PERM_WRITE;
+                        }
+                    }
+                    //rtk_table[write_index].permissions = tmp_chr->permission;
+                    rtk_table[write_index].value_len = 0;
+                    write_index++;
+//                            att_res->chrs++;
+//                            att_res->attrs +=2;
+                    if ((tmp_chr->properties & BSAL_ATT_P_NOTIFY) ||
+                            (tmp_chr->properties & BSAL_ATT_P_INDICATE))
+                    {
+//                                    att_res->dscs++;
+//                                    att_res->cccds++;
+//                                    att_res->attrs++;
+                        //ADD CCCD:
+                        rtk_table[write_index].flags = ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL;
+                        rtk_table[write_index].type_value[0] = LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG);
+                        rtk_table[write_index].type_value[1] = HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG);
+                        rtk_table[write_index].type_value[2] = LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT);
+                        rtk_table[write_index].type_value[3] = HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT);
+#if SIMP_SRV_AUTHEN_EN
+                        rtk_table[write_index].permissions  = (GATT_PERM_READ_AUTHEN_REQ | GATT_PERM_WRITE_AUTHEN_REQ);   /* permissions */
+#else
+                        rtk_table[write_index].permissions = (GATT_PERM_READ | GATT_PERM_WRITE);          /* permissions */
+#endif
+                        rtk_table[write_index].value_len = 2;
+                    }
+
+                    if (tmp_chr->descriptors != NULL)
+                    {
+                        for (y = 0; tmp_chr->descriptors[y].uuid != NULL; y++)
+                        {
+//                                         att_res->dscs++;
+//                                         att_res->attrs++;
+                            /*TODO*/
+                        }
+                    }
+                }
+            }
+        }
+    }
+    T_SERVER_ID service_id;
+
+    if (false == server_add_service(&service_id,
+                                    (uint8_t *)rtk_table,
+                                    sizeof(T_ATTRIB_APPL) * att_num,
+                                    bsal_cbs))
+    {
+        APP_PRINT_ERROR1("bas_add_service: service_id %d", service_id);
+        service_id = 0xff;
+    }
+    APP_PRINT_ERROR1(" bas_add_service: service_id %d", service_id);
+//    bsal_srv_objs[service_id].bsal_srv_fn_cb = (P_BSAL_PROFILE_CB)p_func;
+//    bsal_srv_objs[service_id].start_handle = 0;// RTK NO NEED
+
+    //insert the profile service_id to start_handle
+
+    uint16_t start_handle = 0;
+    for (i = 0; p_srv[i].type != 0; i++)
+    {
+        bsal_uuid_any_t srv_uuid;
+        srv_uuid.u_type = BSAL_UUID_TYPE_16BIT; //16bit
+        srv_uuid.u16.value = p_srv[i].uuid->u16.value;
+        tmp_srv = p_srv + i;
+        p_bsal_stack->g_att_index ++;
+        //save the service id with the start_handle;
+        //rtk_save_service_id_with_start_handle(service_id, p_bsal_stack->g_att_index);
+        start_handle = p_bsal_stack->g_att_index;
+        bsal_profile_insert(bsal_get_rtk_obj(), service_id, p_func, srv_uuid);
+        if (tmp_srv->characteristics != NULL)
+        {
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                tmp_chr = tmp_srv->characteristics + x;
+                p_bsal_stack->g_att_index ++;//declear
+                p_bsal_stack->g_att_index ++;//value
+                bsal_srv_create_att(bsal_get_rtk_obj(), service_id, (p_bsal_stack->g_att_index - start_handle) , tmp_chr->value_length);
+
+            }
+        }
+    }
+    return BSAL_RESULT_SUCCESS;
+}
+
+
+//FOR APP
+static BSAL_STATUS bsal_srv_profile_srv_end(void)
+{
+    //all register service is end
+    return BSAL_RESULT_SUCCESS;
+}
+
+static BSAL_STATUS bsal_stack_srv_send_data(uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_len, const uint8_t *value, uint8_t send_type)
+{
+
+    if (server_send_data(conn_id, service_id, offset_handle, (uint8_t *)value, value_len,  send_type))
+    {
+        return BSAL_RESULT_SUCCESS;
+    }
+    return BSAL_RESULT_FAIL;
+}
+
+static uint32_t bsal_stack_rtk_get_unique_handle(uint16_t start_id, uint16_t offset_handle)
+{
+    return (start_id << 16) | offset_handle;
+}
+
+static void bsal_stack_rtk_set_bond_param(bsal_bond_param_t *bond_param)
+{
+    uint8_t  auth_pair_mode;
+    uint16_t auth_flags;
+    if (bond_param->bonding_flag == false)
+    {
+        //do nothing
+        auth_pair_mode = GAP_PAIRING_MODE_NO_PAIRING;
+        //no need check the other param
+        gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode);
+        return;
+    }
+    else
+    {
+        auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE;
+        gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode);
+    }
+
+    if (bond_param->force_auth_type != 0)
+    {
+        //force the
+        auth_flags = bond_param->force_auth_type;
+    }
+    else
+    {
+        auth_flags = bond_param->auth_type;
+    }
+    gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags);
+    le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(bond_param->sm_req_enable), &bond_param->sm_req_enable);
+    if (bond_param->sm_req_enable == true)
+    {
+        le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_flags),
+                          &auth_flags);
+    }
+
+    gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(bond_param->io_capability), &bond_param->io_capability);
+    if (bond_param->fixed_key_flag == true)
+    {
+        le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(bond_param->fixed_key), &bond_param->fixed_key);
+        le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(bond_param->fixed_key_flag),
+                          &bond_param->fixed_key_flag);
+    }
+
+    if (bond_param->oob_flag == true)
+    {
+#if F_BT_LE_SMP_OOB_SUPPORT
+        gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(bond_param->oob_flag), &bond_param->oob_flag);
+#endif
+    }
+
+
+
+}
+
+static void bsal_rtk_le_set_adv_param(bsal_adv_param_t *adv_param)
+{
+    if (adv_param->set_param_flag & BSAL_SET_LE_ADV_DATA)
+    {
+        APP_PRINT_INFO2("bsal_rtk_le_set_adv_param :%d, %x", adv_param->adv_data[0], *((uint8_t *)((uint32_t)(adv_param->adv_data) + 1)));
+        le_adv_set_param(GAP_PARAM_ADV_DATA, adv_param->adv_data[0], (void *)((uint32_t)(adv_param->adv_data) + 1));
+    }
+    else if (adv_param->set_param_flag & BSAL_SET_LE_SCAN_RSP_DATA)
+    {
+        le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, adv_param->scan_rsp_data[0], (void *)((uint32_t)(adv_param->scan_rsp_data) + 1));
+    }
+    else if (adv_param->set_param_flag & BSAL_SET_LE_ADV_PARAM)
+    {
+        le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_param->adv_type), &adv_param->adv_type);
+        le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_param->direct_address_type), &adv_param->direct_address_type);
+        le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_param->direct_address), adv_param->direct_address);
+        le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_param->channel_map), &adv_param->channel_map);
+        le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_param->filter_policy), &adv_param->filter_policy);
+        le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_param->adv_int_min), &adv_param->adv_int_min);
+        le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_param->adv_int_max), &adv_param->adv_int_max);
+    }
+}
+static void bsal_rtk_set_gas_param(bsal_gaps_param_t *adv_param)
+{
+    uint8_t  slave_init_mtu_req = false;
+
+    /* Advertising parameters */
+    /* Set device name and device appearance */
+    le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, adv_param->name);
+    le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(adv_param->apperance), &adv_param->apperance);
+    le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req),
+                     &slave_init_mtu_req);
+
+}
+
+bsal_stack_obj_t rtk_obj =
+{
+    .bsal_ops = {
+        .init                                                = bsal_rtk_stack_init,
+        .startup                                             = bsal_rtk_stack_startup,
+        .le_adv_enable                                       = bsal_rtk_le_adv_enable,
+        .le_srv_reg_begin                                    = bsal_srv_profile_srv_begin,
+        .le_srv_reg_fun                                      = bsal_srv_profile_reg_service,
+        .le_srv_reg_end                                      = bsal_srv_profile_srv_end,
+        .le_srv_send_data                                    = bsal_stack_srv_send_data,
+        .cov_handle_to_u_handle                              = bsal_stack_rtk_get_unique_handle,
+        .set_bond_param                                      = bsal_stack_rtk_set_bond_param,
+        .le_set_adv_param                                    = bsal_rtk_le_set_adv_param,
+        .set_gaps_param                                      = bsal_rtk_set_gas_param,
+        //callback
+    },
+};
+
+
+/*TODO*/
+//register rtk object
+
+//=================================realtek source orignal codeAPP TASK========
+
+//REALTEK ENTER
+#ifndef SOC_RTL_8762D
+int bt_app_main(void)
+{
+    bt_trace_set_switch(true);  //need called befor bt_trace_init() //default close
+    bt_trace_init();
+    bte_init();
+    bsal_bt_app_main();
+    return 0;
+}
+#endif
+
+
+
+/** @defgroup  PERIPH_APP Peripheral Application
+    * @brief This file handles BLE peripheral application routines.
+    * @{
+    */
+/*============================================================================*
+ *                              Variables
+ *============================================================================*/
+/** @} */ /* End of group PERIPH_SEVER_CALLBACK */
+/** @defgroup  PERIPH_GAP_MSG GAP Message Handler
+    * @brief Handle GAP Message
+    * @{
+    */
+static T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0};                 /**< GAP device state */
+static T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */
+
+/*============================================================================*
+ *                              Functions
+ *============================================================================*/
+void app_handle_gap_msg(T_IO_MSG  *p_gap_msg);
+
+
+/**
+ * @brief    Handle msg GAP_MSG_LE_DEV_STATE_CHANGE
+ * @note     All the gap device state events are pre-handled in this function.
+ *           Then the event handling function shall be called according to the new_state
+ * @param[in] new_state  New gap device state
+ * @param[in] cause GAP device state change cause
+ * @return   void
+ */
+void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
+{
+    APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x",
+                    new_state.gap_init_state, new_state.gap_adv_state, cause);
+    if (gap_dev_state.gap_init_state != new_state.gap_init_state)
+    {
+        if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY)
+        {
+            APP_PRINT_INFO0("GAP stack ready");
+            /*stack ready*/
+#ifdef BSAL_DEBUG
+            le_adv_start();
+#else
+            bsal_stack_ready(bsal_get_rtk_obj(), true);
+#endif
+        }
+    }
+
+    if (gap_dev_state.gap_adv_state != new_state.gap_adv_state)
+    {
+        if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE)
+        {
+            if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN)
+            {
+                APP_PRINT_INFO0("GAP adv stoped: because connection created");
+            }
+            else
+            {
+                APP_PRINT_INFO0("GAP adv stoped");
+            }
+        }
+        else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING)
+        {
+            APP_PRINT_INFO0("GAP adv start");
+        }
+    }
+
+    gap_dev_state = new_state;
+}
+
+/**
+ * @brief    Handle msg GAP_MSG_LE_CONN_STATE_CHANGE
+ * @note     All the gap conn state events are pre-handled in this function.
+ *           Then the event handling function shall be called according to the new_state
+ * @param[in] conn_id Connection ID
+ * @param[in] new_state  New gap connection state
+ * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED
+ * @return   void
+ */
+void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause)
+{
+    APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x",
+                    conn_id, gap_conn_state, new_state, disc_cause);
+    switch (new_state)
+    {
+    case GAP_CONN_STATE_DISCONNECTED:
+    {
+        if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE))
+                && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)))
+        {
+            APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause);
+        }
+#ifdef BSAL_DEBUG
+        le_adv_start();
+#else
+
+#endif
+
+    }
+    break;
+
+    case GAP_CONN_STATE_CONNECTED:
+    {
+        uint16_t conn_interval;
+        uint16_t conn_latency;
+        uint16_t conn_supervision_timeout;
+        uint8_t  remote_bd[6];
+        T_GAP_REMOTE_ADDR_TYPE remote_bd_type;
+
+        le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id);
+        le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id);
+        le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id);
+        le_get_conn_addr(conn_id, remote_bd, (void *)&remote_bd_type);
+        APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x",
+                        TRACE_BDADDR(remote_bd), remote_bd_type,
+                        conn_interval, conn_latency, conn_supervision_timeout);
+    }
+    break;
+    default:
+        break;
+    }
+//TODO need to changed
+    bsal_gap_connect_status(bsal_get_rtk_obj(), conn_id, new_state, disc_cause);
+    gap_conn_state = new_state;
+}
+
+/**
+ * @brief    Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE
+ * @note     All the gap authentication state events are pre-handled in this function.
+ *           Then the event handling function shall be called according to the new_state
+ * @param[in] conn_id Connection ID
+ * @param[in] new_state  New authentication state
+ * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE
+ * @return   void
+ */
+void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause)
+{
+    APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause);
+
+    switch (new_state)
+    {
+    case GAP_AUTHEN_STATE_STARTED:
+    {
+        APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED");
+    }
+    break;
+
+    case GAP_AUTHEN_STATE_COMPLETE:
+    {
+        if (cause == GAP_SUCCESS)
+        {
+            APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success");
+
+        }
+        else
+        {
+            APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed");
+        }
+    }
+    break;
+
+    default:
+    {
+        APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state);
+    }
+    break;
+    }
+}
+
+/**
+ * @brief    Handle msg GAP_MSG_LE_CONN_MTU_INFO
+ * @note     This msg is used to inform APP that exchange mtu procedure is completed.
+ * @param[in] conn_id Connection ID
+ * @param[in] mtu_size  New mtu size
+ * @return   void
+ */
+void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size)
+{
+    APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size);
+}
+
+/**
+ * @brief    Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE
+ * @note     All the connection parameter update change  events are pre-handled in this function.
+ * @param[in] conn_id Connection ID
+ * @param[in] status  New update state
+ * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL
+ * @return   void
+ */
+void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause)
+{
+    switch (status)
+    {
+    case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS:
+    {
+        uint16_t conn_interval;
+        uint16_t conn_slave_latency;
+        uint16_t conn_supervision_timeout;
+
+        le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id);
+        le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id);
+        le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id);
+        APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x",
+                        conn_interval, conn_slave_latency, conn_supervision_timeout);
+    }
+    break;
+
+    case GAP_CONN_PARAM_UPDATE_STATUS_FAIL:
+    {
+        APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause);
+    }
+    break;
+
+    case GAP_CONN_PARAM_UPDATE_STATUS_PENDING:
+    {
+        APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending.");
+    }
+    break;
+
+    default:
+        break;
+    }
+}
+/**
+ * @brief    All the BT GAP MSG are pre-handled in this function.
+ * @note     Then the event handling function shall be called according to the
+ *           subtype of T_IO_MSG
+ * @param[in] p_gap_msg Pointer to GAP msg
+ * @return   void
+ */
+void app_handle_gap_msg(T_IO_MSG *p_gap_msg)
+{
+    T_LE_GAP_MSG gap_msg;
+    uint8_t conn_id;
+    memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param));
+
+    APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype);
+    switch (p_gap_msg->subtype)
+    {
+    case GAP_MSG_LE_DEV_STATE_CHANGE:
+    {
+        app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
+                                 gap_msg.msg_data.gap_dev_state_change.cause);
+    }
+    break;
+
+    case GAP_MSG_LE_CONN_STATE_CHANGE:
+    {
+        app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id,
+                                  (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state,
+                                  gap_msg.msg_data.gap_conn_state_change.disc_cause);
+    }
+    break;
+
+    case GAP_MSG_LE_CONN_MTU_INFO:
+    {
+        app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id,
+                                     gap_msg.msg_data.gap_conn_mtu_info.mtu_size);
+    }
+    break;
+
+    case GAP_MSG_LE_CONN_PARAM_UPDATE:
+    {
+        app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id,
+                                         gap_msg.msg_data.gap_conn_param_update.status,
+                                         gap_msg.msg_data.gap_conn_param_update.cause);
+    }
+    break;
+
+    case GAP_MSG_LE_AUTHEN_STATE_CHANGE:
+    {
+        app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id,
+                                    gap_msg.msg_data.gap_authen_state.new_state,
+                                    gap_msg.msg_data.gap_authen_state.status);
+    }
+    break;
+
+    case GAP_MSG_LE_BOND_JUST_WORK:
+    {
+        conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id;
+        le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+        APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK");
+    }
+    break;
+
+    case GAP_MSG_LE_BOND_PASSKEY_DISPLAY:
+    {
+        uint32_t display_value = 0;
+        conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id;
+        //le_bond_get_display_key(conn_id, &display_value);
+        APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value);
+        le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+    }
+    break;
+
+    case GAP_MSG_LE_BOND_USER_CONFIRMATION:
+    {
+        uint32_t display_value = 0;
+        conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id;
+        le_bond_get_display_key(conn_id, &display_value);
+        APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value);
+        le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+    }
+    break;
+
+    case GAP_MSG_LE_BOND_PASSKEY_INPUT:
+    {
+        uint32_t passkey = 888888;
+        conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id;
+        APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id);
+        le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT);
+    }
+    break;
+#if F_BT_LE_SMP_OOB_SUPPORT
+    case GAP_MSG_LE_BOND_OOB_INPUT:
+    {
+        uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id;
+        APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT");
+        le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data);
+        le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+    }
+    break;
+#endif
+    default:
+        APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype);
+        break;
+    }
+}
+/**
+ * @brief    All the application messages are pre-handled in this function
+ * @note     All the IO MSGs are sent to this function, then the event handling
+ *           function shall be called according to the MSG type.
+ * @param[in] io_msg  IO message data
+ * @return   void
+ */
+static void app_handle_io_msg(T_IO_MSG io_msg)
+{
+    uint16_t msg_type = io_msg.type;
+
+    switch (msg_type)
+    {
+    case IO_MSG_TYPE_BT_STATUS:
+    {
+        app_handle_gap_msg(&io_msg);
+    }
+    break;
+    default:
+        break;
+    }
+}
+/** @defgroup  PERIPH_APP_TASK Peripheral App Task
+    * @brief This file handles the implementation of application task related functions.
+    *
+    * Create App task and handle events & messages
+    * @{
+    */
+/*============================================================================*
+ *                              Macros
+ *============================================================================*/
+#define APP_TASK_PRIORITY             12         //!< Task priorities
+#define APP_TASK_STACK_SIZE           256 * 4   //!<  Task stack size
+#define MAX_NUMBER_OF_GAP_MESSAGE     0x20      //!<  GAP message queue size
+#define MAX_NUMBER_OF_IO_MESSAGE      0x20      //!<  IO message queue size
+#define MAX_NUMBER_OF_EVENT_MESSAGE   (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE)    //!< Event message queue size
+
+/*============================================================================*
+ *                              Variables
+ *============================================================================*/
+static void *app_task_handle;   //!< APP Task handle
+static void *evt_queue_handle;  //!< Event queue handle
+static void *io_queue_handle;   //!< IO queue handle
+
+/*============================================================================*
+ *                              Functions
+ *============================================================================*/
+void app_main_task(void *p_param);
+void bsal_ble_loop(void *p_param);
+
+/**
+ * @brief  Initialize App task
+ * @return void
+ */
+void app_task_init()
+{
+    os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE,
+                   APP_TASK_PRIORITY);
+//    os_task_create(&app_task_handle, "bsal_loop", bsal_ble_loop, 0, APP_TASK_STACK_SIZE,
+//                   3);
+}
+
+/**
+ * @brief        App task to handle events & messages
+ * @param[in]    p_param    Parameters sending to the task
+ * @return       void
+ */
+static void app_main_task(void *p_param)
+{
+    uint8_t event;
+    os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG));
+    os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t));
+
+    gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE);
+
+    while (true)
+    {
+        if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true)
+        {
+            if (event == EVENT_IO_TO_APP)
+            {
+                T_IO_MSG io_msg;
+                if (os_msg_recv(io_queue_handle, &io_msg, 0) == true)
+                {
+                    app_handle_io_msg(io_msg);
+                }
+            }
+            else
+            {
+                gap_handle_msg(event);
+            }
+        }
+    }
+}
+
+
+T_APP_RESULT  bsal_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id,
+                                uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value)
+{
+    T_APP_RESULT cause = APP_RESULT_SUCCESS;
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = bsal_get_rtk_obj();
+    p_param.start_handle = service_id;
+
+    p_param.conn_id = conn_id;
+    p_param.off_handle = attrib_index;
+    p_param.msg_type = BSAL_CALLBACK_TYPE_READ_CHAR_VALUE;
+
+    //load the new data
+    //frome service_id find the service index;
+
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, service_id);
+    memcpy(&p_param.srv_uuid, &p_bsal_srv->srv_uuid, sizeof(bsal_uuid_any_t));
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+    //load the new data
+    //database get data
+    //read from db
+    //
+
+    bsal_srv_read_data(bsal_get_rtk_obj(), service_id, attrib_index, p_length,  pp_value);
+    return (cause);
+}
+
+
+
+T_APP_RESULT bsal_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id,
+                                uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value,
+                                P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc)
+{
+    T_APP_RESULT  cause = APP_RESULT_SUCCESS;
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = bsal_get_rtk_obj();
+    p_param.conn_id = conn_id;
+    p_param.start_handle = service_id;
+    p_param.off_handle = attrib_index;
+    p_param.msg_type = BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE;
+    p_param.length = length;
+    p_param.data = (uint8_t *)p_value;// send the cccd;
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, service_id);
+    memcpy(&p_param.srv_uuid, &p_bsal_srv->srv_uuid, sizeof(bsal_uuid_any_t));
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+    return (cause);
+}
+
+void bsal_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index,
+                         uint16_t cccbits)
+{
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = bsal_get_rtk_obj();
+    p_param.conn_id = conn_id;
+    p_param.off_handle = index;
+    p_param.start_handle = service_id;
+    p_param.msg_type = BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION;
+    p_param.length = 2;
+    p_param.value = cccbits;// send the cccd;
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, service_id);
+    memcpy(&p_param.srv_uuid, &p_bsal_srv->srv_uuid, sizeof(bsal_uuid_any_t));
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+}
+
+static const T_FUN_GATT_SERVICE_CBS bsal_cbs =
+{
+    bsal_attr_read_cb,  // Read callback function pointer
+    bsal_attr_write_cb, // Write callback function pointer
+    bsal_cccd_update_cb  // CCCD update callback function pointer
+};
+
+
+static T_APP_RESULT bsal_app_gap_callback(uint8_t cb_type, void *p_cb_data)
+{
+    T_APP_RESULT result = APP_RESULT_SUCCESS;
+    T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data;
+
+    switch (cb_type)
+    {
+    case GAP_MSG_LE_MODIFY_WHITE_LIST:
+        APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x",
+                        p_data->p_le_modify_white_list_rsp->operation,
+                        p_data->p_le_modify_white_list_rsp->cause);
+        break;
+
+    default:
+        APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type);
+        break;
+    }
+    return result;
+}
+
+
+static T_APP_RESULT bsal_app_profile_callback(T_SERVER_ID service_id, void *p_data)
+{
+    T_APP_RESULT app_result = APP_RESULT_SUCCESS;
+    if (service_id == SERVICE_PROFILE_GENERAL_ID)
+    {
+        T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data;
+        switch (p_param->eventId)
+        {
+        case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event.
+            APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d",
+                            p_param->event_data.service_reg_result);
+            break;
+        case PROFILE_EVT_SEND_DATA_COMPLETE:
+            APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d",
+                            p_param->event_data.send_data_result.conn_id,
+                            p_param->event_data.send_data_result.cause,
+                            p_param->event_data.send_data_result.service_id,
+                            p_param->event_data.send_data_result.attrib_idx,
+                            p_param->event_data.send_data_result.credits);
+            if (p_param->event_data.send_data_result.cause == GAP_SUCCESS)
+            {
+                APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success");
+            }
+            else
+            {
+                APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed");
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+    return app_result;
+}
+
+
+

+ 55 - 0
port/realtek/bsal_rtk.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#ifndef __BSAL_RTK_H__
+#define __BSAL_RTK_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "os_mem.h"
+#include "os_msg.h"
+#include "os_task.h"
+#include "gap.h"
+#include "gap_le.h"
+#include "profile_server.h"
+#include "gap.h"
+#include "gap_adv.h"
+#include "gap_bond_le.h"
+#include "app_msg.h"
+#include "trace.h"
+#include "gap_bond_le.h"
+#include "gap_msg.h"
+#include "gap_conn_le.h"
+/**
+ * @brief  Initialize App task
+ * @return void
+ */
+void app_task_init(void);
+static const T_FUN_GATT_SERVICE_CBS bsal_cbs;
+static T_APP_RESULT bsal_app_gap_callback(uint8_t cb_type, void *p_cb_data);
+static T_APP_RESULT bsal_app_profile_callback(T_SERVER_ID service_id, void *p_data);
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
+
+
+
+
+
+
+
+
+

+ 126 - 0
profiles/service/basl_bas/bsal_srv_bas.c

@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_srv_bas.h"
+
+
+static uint8_t bsal_bas_battery_level = 50;
+
+static P_SRV_GENERAL_CB pfn_bas_cb = NULL;
+static void profile_callback(void *p)
+{
+    bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p;
+    bool is_app_cb = false;
+    if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE)
+    {
+        if (GATT_SVC_BAS_BATTERY_LEVEL_INDEX == p_param->off_handle)
+        {
+            is_app_cb = true;
+            //write db the battery_level
+            bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(uint8_t), &bsal_bas_battery_level);
+        }
+
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+    {
+        //do nothing
+        is_app_cb = true;
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION)
+    {
+        if (GATT_SVC_BAS_CHAR_CCCD_INDEX == p_param->off_handle)
+        {
+            if (p_param->length == 2)
+            {
+                //uint16_t ccdbit = (uint16_t)p_param->data;
+                is_app_cb = true;
+            }
+        }
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_HANDLE_TABLE)
+    {
+        //save the could notify u_handle
+        // bsal_start_handle = p_param->start_handle;
+    }
+
+    if (is_app_cb && (pfn_bas_cb != NULL))
+    {
+        pfn_bas_cb(p_param);
+    }
+
+    //read write the datebase
+
+}
+
+void bsal_le_bas_svr_init(void *stack_ptr, void *app_callback)
+{
+    struct bsal_gatt_app_srv_def ble_svc_bas_defs[] =
+    {
+        {
+            /*** Battery Service. */
+            .type = BSAL_GATT_UUID_PRIMARY_SERVICE,
+            .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),//(bsal_uuid_any_t *)&battery_srv,//BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),
+            .characteristics = (bsal_gatt_chr_def_t[])
+            {
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL),//(bsal_uuid_any_t *)&bas_char_bas_level,//BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL),
+                    .properties = BSAL_ATT_P_READ
+                    | BSAL_ATT_P_NOTIFY
+                    ,
+                    .permission = BSAL_GATT_PERM_READ_NONE,
+                    .value_length = 1,
+                },
+                {
+                    0, /* No more characteristics in this service. */
+                }
+            },
+        },
+
+        {
+            0, /* No more services. */
+        },
+    };
+    bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_bas_defs, (P_SRV_GENERAL_CB *)profile_callback);
+    pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback;
+}
+void bsal_le_bas_svr_deinit(void *stack_ptr)
+{
+    //delete the service
+}
+
+
+//no notify
+void bsal_set_battery_level_static(uint8_t battery_level)
+{
+    bsal_bas_battery_level = battery_level;
+}
+
+void bsal_bas_send_notify_level(void *stack_ptr, uint16_t conn_id,  uint8_t battery_level)
+{
+    /*TODO*/
+    if (battery_level > 100)
+    {
+        bsal_osif_printf_err("The battery is invalid:%d", battery_level);
+        return;
+    }
+    bsal_uuid_any_t uuid_srv;
+    uuid_srv.u_type = 16;
+    uuid_srv.u16.value = GATT_UUID_BATTERY;
+    uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv);
+    bsal_bas_battery_level = battery_level;
+    bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, GATT_SVC_BAS_BATTERY_LEVEL_INDEX, sizeof(uint8_t), &battery_level);
+}
+
+

+ 55 - 0
profiles/service/basl_bas/bsal_srv_bas.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+#ifndef __BSAL_SRV_BAS_H__
+#define __BSAL_SRV_BAS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdint.h>
+#include <stdbool.h>
+#include "bsal.h"
+#define GATT_UUID_BATTERY                       BSAL_GATT_SERVICE_BATTERY_SERVICE
+#define GATT_UUID_CHAR_BAS_LEVEL                BSAL_UUID_CHAR_BATTERY_LEVEL
+
+#define GATT_SVC_BAS_BATTERY_LEVEL_INDEX        2 /**< @brief Index for battery level chars's value */
+#define GATT_SVC_BAS_CHAR_CCCD_INDEX            (GATT_SVC_BAS_BATTERY_LEVEL_INDEX+1) /**< @brief CCCD Index for battery level chars's value */
+/**
+* BSAL battery service init
+*
+* @param stack_ptr the point of the stack object
+* @param app_callback the callback of the service
+* @Note init the service
+*/
+void bsal_le_bas_svr_init(void *stack_ptr, void *app_callback);
+
+/**
+* BSAL set the battery level local
+*
+* @param stack_ptr the point of the stack object
+* @param app_callback the callback of the service
+* @Note init the service
+*/
+void bsal_set_battery_level_static(uint8_t battery_level);
+
+/**
+* BSAL set the battery level and send notify
+*
+* @param stack_ptr the point of the stack object
+* @param conn_id the conn_handle of the link
+* @param battery_level the battery level of the battery service
+* @Note set the notify level
+*/
+void bsal_bas_send_notify_level(void *stack_ptr, uint16_t conn_id,  uint8_t battery_level);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 156 - 0
profiles/service/bsal_blufi/bsal_srv_blufi.c

@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_srv_blufi.h"
+
+#define BLUFI_RECV_BUFF_SIZE  200
+
+struct basl_blufi_recv_data
+{
+    uint8_t buf[BLUFI_RECV_BUFF_SIZE];
+    uint16_t alloc_len;
+    uint8_t recv_offset;
+};
+
+
+static struct basl_blufi_recv_data blufi_data;
+static P_SRV_GENERAL_CB pfn_bas_cb = NULL;
+uint8_t bsal_blufi_push_data(struct basl_blufi_recv_data *blufi_data, uint8_t length, uint8_t *data)
+{
+    if (blufi_data->recv_offset + length > blufi_data->alloc_len)
+    {
+        //error
+        return 1;
+    }
+    if (data[0] == '{')
+    {
+        //first entry
+        blufi_data->recv_offset = 0;
+        memset(blufi_data->buf, 0, blufi_data->alloc_len);
+    }
+    memcpy(&blufi_data->buf[blufi_data->recv_offset], data, length);
+    blufi_data->recv_offset += length;
+    //check the data
+    if (data[length - 1] == '}')
+    {
+        return 0xff;
+    }
+    return 0;
+}
+
+
+static void profile_callback(void *p)
+{
+    bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p;
+    bool is_app_cb = false;
+    //BSAL_STATUS bsal_result = BSAL_RESULT_SUCCESS;
+    if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE)
+    {
+        //NO DEAL
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+    {
+        //do nothing
+        if (BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX == p_param->off_handle)
+        {
+            uint8_t ret =  bsal_blufi_push_data(&blufi_data, p_param->length, p_param->data);
+            if (ret == 0xff)
+            {
+                //the data is ready
+                is_app_cb = true;
+                p_param->data = blufi_data.buf;
+                p_param->length = blufi_data.recv_offset;
+                //bsal_osif_printf("\r\n BLUFI: THE RECEIVE DATA IS :%s \r\n", p_param->data);
+            }
+        }
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION)
+    {
+        if (BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX == p_param->off_handle)
+        {
+            if (p_param->length == 2)
+            {
+                // uint16_t ccdbit = (uint32_t)p_param->data;
+                is_app_cb = true;
+            }
+        }
+    }
+    if (is_app_cb && (pfn_bas_cb != NULL))
+    {
+        pfn_bas_cb(p_param);
+    }
+}
+
+void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback)
+{
+    struct bsal_gatt_app_srv_def ble_svc_blufi_defs[] =
+    {
+        {
+            /*** Battery Service. */
+            .type = BSAL_GATT_UUID_PRIMARY_SERVICE,
+            .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BLUFI_PROFILE),
+            .characteristics = (bsal_gatt_chr_def_t[])
+            {
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V2_WRITE),
+                    .properties = BSAL_ATT_P_WRITE
+                    ,
+                    .permission = BSAL_GATT_PERM_WRITE_NONE,
+                    .value_length = 1,
+                },
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V4_INDICATE),
+                    .properties = BSAL_ATT_P_INDICATE
+                    ,
+                    .permission = BSAL_GATT_PERM_WRITE_NONE | BSAL_GATT_PERM_READ_NONE,
+                    .value_length = 1,
+                },
+                {
+                    0, /* No more characteristics in this service. */
+                }
+            },
+        },
+
+        {
+            0, /* No more services. */
+        },
+    };
+    bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_blufi_defs, (P_SRV_GENERAL_CB *)profile_callback);
+
+    pfn_bas_cb = app_callback;
+    blufi_data.alloc_len = BLUFI_RECV_BUFF_SIZE;
+    blufi_data.recv_offset = 0;
+}
+
+void bsal_blufi_ble_send_v4_indicate(void *stack_ptr, uint16_t conn_id,  void *p_value, uint16_t length)
+{
+    bsal_uuid_any_t uuid_srv;
+    uuid_srv.u_type = BSAL_UUID_TYPE_16BIT;
+    uuid_srv.u16.value = GATT_UUID_BLUFI_PROFILE;
+    uint16_t  start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv);
+    bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX, length, p_value);
+}
+
+
+void bsal_le_blufi_svr_deinit(void *stack_ptr)
+{
+    //deinit
+}
+
+

+ 37 - 0
profiles/service/bsal_blufi/bsal_srv_blufi.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+
+
+#ifndef __BSAL_SRV_BLUFI_H__
+#define __BSAL_SRV_BLUFI_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define GATT_UUID_BLUFI_PROFILE                   0xFFFF
+#define GATT_UUID_CHAR_BLUFI_V2_WRITE             0xFF01
+#define GATT_UUID_CHAR_BLUFI_V4_INDICATE          0xFF02
+
+#define BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX          0x02
+#define BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX         0x04
+#define BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX     (BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX + 1)
+
+void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 166 - 0
profiles/service/bsal_dis/bsal_srv_dis.c

@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_srv_blufi.h"
+
+
+#define GATT_UUID_BLUFI_PROFILE                   0xFFFF
+#define GATT_UUID_CHAR_BLUFI_V2_WRITE             0xFF01
+#define GATT_UUID_CHAR_BLUFI_V4_INDICATE          0xFF02
+
+
+#define BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX          0x02
+#define BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX         0x04
+#define BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX     (BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX + 1)
+
+#define BLUFI_RECV_BUFF_SIZE  200
+
+struct basl_blufi_recv_data
+{
+    uint8_t buf[BLUFI_RECV_BUFF_SIZE];
+    uint16_t alloc_len;
+    uint8_t recv_offset;
+};
+
+
+static struct basl_blufi_recv_data blufi_data;
+static P_SRV_GENERAL_CB pfn_bas_cb = NULL;
+uint8_t bsal_blufi_push_data(struct basl_blufi_recv_data *blufi_data, uint8_t length, uint8_t *data)
+{
+    if (blufi_data->recv_offset + length > blufi_data->alloc_len)
+    {
+        //error
+        return 1;
+    }
+    if (data[0] == '{')
+    {
+        //first entry
+        blufi_data->recv_offset = 0;
+        memset(blufi_data->buf, 0, blufi_data->alloc_len);
+    }
+    memcpy(&blufi_data->buf[blufi_data->recv_offset], data, length);
+    blufi_data->recv_offset += length;
+    //check the data
+    if (data[length - 1] == '}')
+    {
+        return 0xff;
+    }
+    return 0;
+}
+
+
+static void profile_callback(void *p)
+{
+    bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p;
+    bool is_app_cb = false;
+    //BSAL_STATUS bsal_result = BSAL_RESULT_SUCCESS;
+    if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE)
+    {
+        //NO DEAL
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+    {
+        //do nothing
+        if (BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX == p_param->off_handle)
+        {
+            uint8_t ret =  bsal_blufi_push_data(&blufi_data, p_param->length, p_param->data);
+            if (ret == 0xff)
+            {
+                //the data is ready
+                is_app_cb = true;
+                p_param->data = blufi_data.buf;
+                p_param->length = blufi_data.recv_offset;
+                //bsal_osif_printf("\r\n BLUFI: THE RECEIVE DATA IS :%s \r\n", p_param->data);
+            }
+        }
+    }
+    else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION)
+    {
+        if (BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX == p_param->off_handle)
+        {
+            if (p_param->length == 2)
+            {
+                // uint16_t ccdbit = (uint32_t)p_param->data;
+                is_app_cb = true;
+            }
+        }
+    }
+    if (is_app_cb && (pfn_bas_cb != NULL))
+    {
+        pfn_bas_cb(p_param);
+    }
+}
+
+void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback)
+{
+    struct bsal_gatt_app_srv_def ble_svc_blufi_defs[] =
+    {
+        {
+            /*** Battery Service. */
+            .type = BSAL_GATT_UUID_PRIMARY_SERVICE,
+            .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BLUFI_PROFILE),
+            .characteristics = (bsal_gatt_chr_def_t[])
+            {
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V2_WRITE),
+                    .properties = BSAL_ATT_P_WRITE
+                    ,
+                    .permission = GATT_PERM_WRITE,
+                    .value_length = 1,
+                },
+                {
+                    /*** Battery level characteristic */
+                    .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V4_INDICATE),
+                    .properties = BSAL_ATT_P_INDICATE
+                    ,
+                    .permission = GATT_PERM_READ | GATT_PERM_WRITE,
+                    .value_length = 1,
+                },
+                {
+                    0, /* No more characteristics in this service. */
+                }
+            },
+        },
+
+        {
+            0, /* No more services. */
+        },
+    };
+    bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_blufi_defs, (P_SRV_GENERAL_CB *)profile_callback);
+
+    pfn_bas_cb = app_callback;
+    blufi_data.alloc_len = BLUFI_RECV_BUFF_SIZE;
+    blufi_data.recv_offset = 0;
+}
+
+void bsal_blufi_ble_send_v4_indicate(void *stack_ptr, uint16_t conn_id,  void *p_value, uint16_t length)
+{
+    bsal_uuid_any_t uuid_srv;
+    uuid_srv.u_type = BSAL_UUID_TYPE_16BIT;
+    uuid_srv.u16.value = GATT_UUID_BLUFI_PROFILE;
+    uint16_t  start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv);
+    bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX, length, p_value);
+}
+
+
+void bsal_le_blufi_svr_deinit(void *stack_ptr)
+{
+    //deinit
+}
+
+

+ 29 - 0
profiles/service/bsal_dis/bsal_srv_dis.h

@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+
+
+#ifndef __BSAL_SRV_BLUFI_H__
+#define __BSAL_SRV_BLUFI_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stdint.h"
+#include "stdbool.h"
+
+void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 214 - 0
samples/ble_bas_blufi_app.c

@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include "bsal.h"
+#include <stdio.h>
+#include <string.h>
+#include "bsal_osif.h"
+#include "bsal_srv_blufi.h"
+#include "bsal_srv_bas.h"
+
+#define BSAL_STACK_NAME PKG_BSAL_STACK_NAME
+
+static void *bsal_stack_ptr = NULL;
+uint16_t bsal_app_conn_handle;
+static uint8_t battery_flag = 0;
+static uint8_t  gap_conn_state = BSAL_GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */
+
+void bsa_app_set_adv_data(void *stack_ptr)
+{
+    uint8_t tmp_data[32] = {0} ; //must be zero
+    bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED);
+
+    char *adv_name = (char *)bsal_get_device_name(stack_ptr);
+    bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name);
+    //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE);
+    bsal_set_le_adv_data_user(stack_ptr, tmp_data);
+}
+
+void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value)
+{
+    T_BSAL_GAP_MSG_DATA  *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value;
+    uint8_t bd_addr[6];
+    switch (cb_layer)
+    {
+    case BSAL_CB_LAYER_GAP:
+        switch (cb_sub_event)
+        {
+        case BSAL_CB_STACK_READY:
+            //get mac address
+
+            bsal_osif_printf_info("============stack ready===========\r\n");
+            bsa_app_set_adv_data(stack_ptr);
+            bsal_stack_start_adv(stack_ptr);
+            break;
+        case BSAL_CB_CONNECT_STATUS:
+            bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id);
+            if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED)
+            {
+                bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id;
+            }
+            else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED)
+            {
+                bsal_stack_start_adv(stack_ptr);
+                battery_flag = 0;
+            }
+            bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x",
+                                  bsal_gap_msg_data->gap_conn_state_change.conn_id , gap_conn_state, bsal_gap_msg_data->gap_conn_state_change.new_state, bsal_gap_msg_data->gap_conn_state_change.disc_cause);
+
+            break;
+        default:
+            break;
+        }
+
+        if (cb_sub_event == BSAL_CB_STACK_READY)
+        {
+            //stack ready
+            //   APP_PRINT_INFO0("GAP stack ready");
+
+        }
+
+        break;
+    case BSAL_CB_LAYER_GATT_PROFILE:
+        switch (cb_sub_event)
+        {
+            //save the service start_handle
+            //case uuid profile save start_handle
+            //case SRV_CALLBACK66
+            //save the identity
+        }
+        break;
+    case BSAL_CB_LAYER_SM:
+        break;
+    case BSAL_CB_LAYER_COMMON:
+        //connected save the connect id
+
+        break;
+    case BSAL_CB_LAYER_UNKNOWN:
+        break;
+    default:
+        break;
+    }
+
+}
+
+void bsal_app_profile_callback(void *p)
+{
+    bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p;
+
+    if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE)
+    {
+        bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value);
+    }
+    else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION)
+    {
+        uint16_t  cccbits = bsal_param->value;
+        bsal_osif_printf_info("======callback notify from %x===data cccd %x====%x=====\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+        if (bsal_param->srv_uuid.u16.value == BSAL_GATT_SERVICE_BATTERY_SERVICE)
+        {
+            if (cccbits & BSAL_GATT_CCC_NOTIFY)
+            {
+                bsal_osif_printf_info("=========NOTIFY ENABLE from %x===data cccd %x====%x=====\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+                battery_flag = 1;
+            }
+            else
+            {
+                bsal_osif_printf_info("========NOTIFY DISABLE from %x===data cccd %x====%x=====\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+                battery_flag = 0;
+            }
+        }
+        else if (bsal_param->srv_uuid.u16.value == GATT_UUID_BLUFI_PROFILE)
+        {
+            if (cccbits & BSAL_GATT_CCC_NOTIFY)
+            {
+                bsal_osif_printf_info("=========NOTIFY ENABLE from %x===data cccd %x====%x=====\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+            }
+            else
+            {
+                bsal_osif_printf_info("========NOTIFY DISABLE from %x===data cccd %x====%x=====\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+            }
+        }
+    }
+    else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+    {
+        bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data);
+    }
+}
+
+//add the db for
+
+
+void bsal_ble_loop(void *p_param)
+{
+
+    uint8_t count = 0;
+    battery_flag = 1;
+    while (1)
+    {
+        bsal_osif_delay(20000);
+        bsal_osif_printf_info("====hello world===%d=\r\n", battery_flag);
+        if (battery_flag == 1)
+        {
+            uint8_t battery_level = 90 - count * 10;
+            count++;
+            bsal_bas_send_notify_level(bsal_stack_ptr, bsal_app_conn_handle, battery_level);
+        }
+        bsal_osif_delay(2000);
+    }
+}
+
+
+int bsal_bas_blufi_app(void)
+{
+    void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME);
+    if (stack_ptr == NULL)
+    {
+        //print error;
+        return 1;
+    }
+    //set iocapability
+
+
+    bsal_stack_ptr  = stack_ptr;
+    //1. init stack
+    bsal_stack_init(stack_ptr, bsal_app_all_callback);  // init param not start stack
+    // set device name
+    char *device_name = "ble_rtt";
+    bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name);
+    //2. bond type
+    bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false);
+    //set the bond flag:
+
+    //3. service begin
+    bsal_stack_le_srv_begin(stack_ptr, 2, bsal_app_profile_callback);  //will add 1 service
+    //4. bas_init
+    bsal_le_bas_svr_init(stack_ptr, bsal_app_profile_callback); //add battery servcie
+
+    //5. blufi_init
+    bsal_le_blufi_svr_init(stack_ptr, bsal_app_profile_callback);
+
+    //6. srv_end
+    bsal_stack_le_srv_end(stack_ptr);    //end srv add
+
+    //start stack
+    bsal_stack_startup(stack_ptr);    //start she
+
+    return 0;
+}
+MSH_CMD_EXPORT_ALIAS(bsal_bas_blufi_app, bsal_bas_blufi_app, "bluetoooth blufi and bas sample");
+
+
+
+
+
+//CMD
+
+

+ 209 - 0
samples/ble_bas_only_app.c

@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include "bsal.h"
+#include <stdio.h>
+#include <string.h>
+#include "bsal_osif.h"
+#include "bsal_srv_bas.h"
+#include <rtdbg.h>
+#define DBG_TAG     "BSAL"
+#define DBG_LVL     DBG_LOG
+
+#define BSAL_STACK_NAME PKG_BSAL_STACK_NAME
+
+static void *bsal_stack_ptr = NULL;
+uint16_t bsal_app_conn_handle;
+static uint8_t battery_flag = 0;
+static uint8_t  gap_conn_state = BSAL_GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */
+
+uint16_t battery_start_handle = 0;
+void bsa_app_set_adv_data(void *stack_ptr)
+{
+    uint8_t tmp_data[32] = {0} ; //must be zero
+    bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED);
+
+    char *adv_name = (char *)bsal_get_device_name(stack_ptr);
+    bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name);
+    //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE);
+    bsal_set_le_adv_data_user(stack_ptr, tmp_data);
+}
+
+void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value)
+{
+    T_BSAL_GAP_MSG_DATA  *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value;
+    switch (cb_layer)
+    {
+    case BSAL_CB_LAYER_GAP:
+        switch (cb_sub_event)
+        {
+        case BSAL_CB_STACK_READY:
+            LOG_I("BSAL STACK READY");
+
+            bsa_app_set_adv_data(stack_ptr);
+
+            bsal_stack_start_adv(stack_ptr);
+            break;
+        case BSAL_CB_CONNECT_STATUS:
+            if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED)
+            {
+                LOG_I("REMOTE DEVICE CONNECT ID %d STATUS CONNECTED READY\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id);
+                bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id;
+            }
+            else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED)
+            {
+                LOG_I("REMOTE DEVICE CONNECT ID %d STATUS DISCONNECT READY\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id);
+
+                bsal_stack_start_adv(stack_ptr);
+                battery_flag = 0;
+            }
+            bsal_osif_printf_info("conn_id %d old_state %d new_state %d, disc_cause 0x%x",
+                                  bsal_gap_msg_data->gap_conn_state_change.conn_id , gap_conn_state, bsal_gap_msg_data->gap_conn_state_change.new_state, bsal_gap_msg_data->gap_conn_state_change.disc_cause);
+
+            break;
+        default:
+            break;
+        }
+
+        break;
+    case BSAL_CB_LAYER_GATT_PROFILE:
+        switch (cb_sub_event)
+        {
+            //save the service start_handle
+            //case uuid profile save start_handle
+            //case SRV_CALLBACK66
+            //save the identity
+        }
+        break;
+    case BSAL_CB_LAYER_SM:
+        break;
+    case BSAL_CB_LAYER_COMMON:
+        //connected save the connect id
+
+        break;
+    case BSAL_CB_LAYER_UNKNOWN:
+        break;
+    default:
+        break;
+    }
+
+}
+
+
+
+
+void bsal_app_profile_callback(void *p)
+{
+    bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p;
+
+    if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE)
+    {
+         LOG_I("GATT:READ CHAR VALUE OFF_HANDLE %x  UUID:%x\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value);
+    }
+    else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION)
+    {
+        uint16_t  cccbits = (uint16_t)bsal_param->value;
+        LOG_I("GATT: NOTIFY HANDLE %x cccd %x UUID:%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+
+        if (bsal_param->srv_uuid.u16.value == BSAL_GATT_SERVICE_BATTERY_SERVICE)
+        {
+            if (cccbits & BSAL_GATT_CCC_NOTIFY)
+            {
+							 LOG_I("NOTIFY ENABLE from %x data cccd %x  UUID:%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+                battery_flag = 1;
+            }
+            else
+            {
+                LOG_I("NOTIFY DISABLE from %x data cccd %x UUID%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value);
+                battery_flag = 0;
+            }
+        }
+    }
+    else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+    {
+        LOG_I("\r\n Recv THE DATA IS :%s\r\n", bsal_param->data);
+    }
+}
+
+//add the db for
+
+
+void bsal_ble_loop(void *p_param)
+{
+
+    uint8_t count = 0;
+    while (1)
+    {
+        bsal_osif_delay(2000);
+        if (battery_flag == 1)
+        {
+            uint8_t battery_level = 90 - count * 10;
+            count++;
+            if (battery_level <= 0)
+            {
+                count = 0;
+            }
+            bsal_bas_send_notify_level(bsal_stack_ptr, bsal_app_conn_handle, battery_level);
+        }
+    }
+}
+
+
+int bsal_bas_app(void)
+{
+    void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME);
+    void *bsal_test_app_task;
+    if (stack_ptr == NULL)
+    {
+        //print error;
+        return 1;
+    }
+    //set iocapability
+
+
+    bsal_stack_ptr  = stack_ptr;
+
+    //1. stack init
+    bsal_stack_init(stack_ptr, bsal_app_all_callback);  // init param not start stack
+    char *device_name = "ble_rtt";
+    bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name);
+    //2. set bond type
+    bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false);
+    //set the bond flag:
+    //3. start add profile service
+    bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service
+
+    //4. add profile service
+    bsal_le_bas_svr_init(stack_ptr, bsal_app_profile_callback); //add battery servcie
+
+    //5. end add profile service
+    bsal_stack_le_srv_end(stack_ptr);    //end srv add
+
+    //6. start ble stack
+    bsal_stack_startup(stack_ptr);    //start she
+
+    //bsal_ble_loop(NULL);
+
+    bsal_test_app_task =  rt_thread_create("bsal_app", bsal_ble_loop, NULL, 2 * 256, 5, 10);
+    if (bsal_test_app_task != RT_NULL)
+    {
+
+        rt_thread_startup(bsal_test_app_task);
+    }
+    return 0;
+}
+MSH_CMD_EXPORT_ALIAS(bsal_bas_app, bsal_bas_app, "bluetoooth battery service sample");
+
+
+
+
+//CMD
+

+ 860 - 0
src/bsal.c

@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2020-05-28     Supperthomas the first version
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include "bsal.h"
+#include "bsal_osif.h"
+#include "bsal_int.h"
+
+//======================================BSAL UTILS======DEPEND NOTHING======================================================
+
+void bsal_gatt_read_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t *length , uint8_t **value)
+{
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = stack_ptr;
+    p_param.conn_id = conn_handle;
+    p_param.start_handle = start_handle;
+    p_param.off_handle   = offset_handle;
+    p_param.msg_type     = BSAL_CALLBACK_TYPE_READ_CHAR_VALUE;
+
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, p_param.start_handle);
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+    bsal_srv_read_data(p_param.stack_ptr, p_param.start_handle, p_param.off_handle, length, value);
+}
+
+void bsal_gatt_write_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t length , uint8_t *value)
+{
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = stack_ptr;
+    p_param.conn_id = conn_handle;
+    p_param.start_handle = start_handle;
+    p_param.off_handle   = offset_handle;
+    p_param.msg_type     = BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE;
+    p_param.data = value;
+    p_param.length = length;
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, p_param.start_handle);
+    memcpy(&p_param.srv_uuid, &p_bsal_srv->srv_uuid, sizeof(bsal_uuid_any_t));
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+
+}
+
+void bsal_gatt_cccd_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t value)
+{
+    bsal_callbak_data_t p_param;
+    p_param.stack_ptr = stack_ptr;
+    p_param.conn_id = conn_handle;
+    p_param.start_handle = start_handle;
+    p_param.off_handle   = offset_handle;
+    p_param.msg_type     = BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION;
+    p_param.length = 2;
+    p_param.value = value;
+    bsal_srv_callback_t *p_bsal_srv = bsal_profile_get(p_param.stack_ptr, p_param.start_handle);
+    memcpy(&p_param.srv_uuid, &p_bsal_srv->srv_uuid, sizeof(bsal_uuid_any_t));
+    p_bsal_srv->bsal_srv_fn_cb((void *)&p_param);
+
+}
+
+
+void bsal_gatt_read_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle, uint16_t *length , uint8_t **value)
+{
+    uint16_t start_handle = bsal_profile_get_start_handle(stack_ptr, u_handle);
+    uint16_t offset_handle = u_handle - start_handle;
+    bsal_gatt_read_callback_event(stack_ptr, conn_handle, start_handle, offset_handle, length, value);
+}
+
+void bsal_gatt_write_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle, uint16_t length , uint8_t *value)
+{
+    uint16_t start_handle = bsal_profile_get_start_handle(stack_ptr, u_handle);
+    uint16_t offset_handle = u_handle - start_handle;
+    bsal_gatt_write_callback_event(stack_ptr, conn_handle, start_handle, offset_handle, length, value);
+}
+
+void bsal_gatt_cccd_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle , uint16_t value)
+{
+    uint16_t start_handle = bsal_profile_get_start_handle(stack_ptr, u_handle);
+    uint16_t offset_handle = u_handle - start_handle;
+    bsal_gatt_cccd_callback_event(stack_ptr, conn_handle, start_handle, offset_handle, value);
+}
+
+
+
+void bsal_le_adv_data_add_ltv(uint8_t *adv_data, le_adv_ltv_t *ltv)
+{
+    BSAL_ASSERT_PTR(data);
+    BSAL_ASSERT_PTR(ltv);
+    uint8_t index = 0;
+    index = adv_data[0] + 1;
+    adv_data[index++] = ltv->length;
+    adv_data[index++] = ltv->type;
+    memcpy(&adv_data[index], ltv->value, ltv->length - 1);
+    index += ltv->length - 1;
+    adv_data[0] = index - 1;
+}
+
+void bsal_le_adv_data_add_flag(uint8_t *adv_data , uint8_t flag)
+{
+    BSAL_ASSERT_PTR(ptr);
+    le_adv_ltv_t ltv;
+    ltv.length = 2;
+    uint8_t value = flag;
+    ltv.value = (uint8_t *)&value;
+    ltv.type = BSAL_GAP_TYPE_FLAGS;
+    bsal_le_adv_data_add_ltv(adv_data, &ltv);
+}
+
+
+void bsal_adv_data_add_name(uint8_t *adv_data, uint8_t name_length, char *name)
+{
+    BSAL_ASSERT_PTR(adv_data);
+    le_adv_ltv_t ltv;
+    ltv.length = name_length + 1;
+    ltv.value = (uint8_t *)name;
+    ltv.type = BSAL_GAP_TYPE_COMPLETE_LOCAL_NAME;
+    bsal_le_adv_data_add_ltv(adv_data, &ltv);
+}
+
+
+void bsal_adv_data_add_uuid16(uint8_t *adv_data, uint16_t uuid)
+{
+    BSAL_ASSERT_PTR(adv_data);
+    le_adv_ltv_t ltv;
+    ltv.length = 3;
+    ltv.type = BSAL_GAP_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS;
+    uint16_t tmp_uuid = uuid;
+    ltv.value = (uint8_t *)&tmp_uuid;
+    bsal_le_adv_data_add_ltv(adv_data, &ltv);
+}
+
+static bsal_gatt_value_entry_t *bsal_read_att(bsal_gatt_value_entry_t *p_db, uint32_t u_handle)
+{
+    BSAL_ASSERT_PTR(p_db);
+    bsal_gatt_value_entry_t *tmp_db = p_db;
+    while (tmp_db != NULL)
+    {
+        if (tmp_db->u_handle == u_handle)
+        {
+            return tmp_db;
+        }
+        else
+        {
+            tmp_db = tmp_db->next_entry;
+        }
+    }
+    bsal_osif_printf_err("could not find the att:%d", u_handle);
+    return NULL;
+}
+
+static int bsal_insert_att(void *stack_ptr, uint32_t u_handle, uint16_t value_length)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    bsal_gatt_value_entry_t *p_db = p_ops->db;
+    if (p_db == NULL)
+    {
+        //first INIT
+        bsal_gatt_value_entry_t *temp_db = bsal_osif_malloc(sizeof(bsal_gatt_value_entry_t));
+        temp_db->next_entry = NULL;
+        temp_db->u_handle = u_handle;
+        temp_db->value = bsal_osif_malloc(value_length);
+        temp_db->alloc_size = value_length;
+        if (temp_db->value != NULL)
+        {
+            //first time
+            p_ops->db = temp_db;
+            return 0;
+        }
+        bsal_osif_printf_err("temp_db->value malloc failed1 value_length:%x", value_length);
+        return 1;
+    }
+    bsal_gatt_value_entry_t *last_db = p_db;
+    //find the end
+    while (p_db != NULL)
+    {
+        last_db = p_db;
+        p_db = p_db->next_entry;
+    }
+
+    if (p_db == NULL)
+    {
+        // the last one
+        bsal_gatt_value_entry_t *temp_db = bsal_osif_malloc(sizeof(bsal_gatt_value_entry_t));
+        last_db->next_entry = temp_db;
+        temp_db->next_entry = NULL;
+        temp_db->u_handle = u_handle;
+        temp_db->value = bsal_osif_malloc(value_length);
+        temp_db->alloc_size = value_length;
+        if (temp_db->value != NULL)
+        {
+            return 0;
+        }
+        bsal_osif_printf_err("temp_db->value %x malloc value_length:%x", u_handle, value_length);
+        return 0;
+    }
+    return 2;
+}
+
+int bsal_att_create_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length)
+{
+    //SAVE THE DATA
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(value_length);
+    BSAL_ASSERT_PTR(u_handle);
+    return bsal_insert_att(stack_ptr, u_handle, value_length);//just use the length malloc data
+}
+
+int bsal_att_read_entry(void *stack_ptr, uint32_t u_handle, uint16_t *value_length, uint8_t **value)
+{
+    //READ THE DATE
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(value_length);
+    BSAL_ASSERT_PTR(value);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    bsal_gatt_value_entry_t *p_db = p_ops->db;
+    bsal_gatt_value_entry_t *p_value = bsal_read_att(p_db, u_handle);//just use the length malloc data
+    *value = p_value->value;
+    *value_length = p_value->value_length;
+    return 0;
+}
+
+int bsal_att_write_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, uint8_t *value)
+{
+    //WRITE THE DATA
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(value_length);
+    BSAL_ASSERT_PTR(value);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    bsal_gatt_value_entry_t *p_db = p_ops->db;
+    bsal_gatt_value_entry_t *p_value = bsal_read_att(p_db, u_handle);//just use the length malloc data
+    if (value_length <= p_value->alloc_size)
+    {
+        memcpy(p_value->value, value, value_length);
+    }
+    else
+    {
+        //size out of reset value ,fail
+        //FAILED
+        bsal_osif_printf_err("bsal_att_write_entry: FAIL WRITE THE DATA THE LENGTH IS %dLESS THAN ALLOCATED %d", value_length, p_value->alloc_size);
+        return 1;
+    }
+    p_value->value_length = value_length;
+    return 0;
+}
+
+int bsal_att_resize_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, bool append)
+{
+    //RESIZE THE DATA
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(value_length);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    bsal_gatt_value_entry_t *p_db = p_ops->db;
+    bsal_gatt_value_entry_t *p_value = bsal_read_att(p_db, u_handle);//just use the length malloc data
+    bsal_osif_free(p_value->value);
+    p_value->value = bsal_osif_malloc(value_length);
+    p_value->append = append;
+    return 0;
+}
+
+void bsal_util_sum_handle_num(bsal_gatt_app_srv_def_t *p_srv, bsal_gatt_res_t *att_res)
+{
+//      const struct bsal_gatt_app_srv_def *svc;
+//      const struct bsal_gatt_app_chr_def *chr;
+    BSAL_ASSERT_PTR(p_srv);
+    BSAL_ASSERT_PTR(att_res);
+    bsal_gatt_app_srv_def_t *tmp_srv;
+    bsal_gatt_chr_def_t      *tmp_chr;
+    uint8_t i = 0;
+    uint8_t j = 0;
+    uint8_t x = 0;
+    uint8_t y = 0;
+    memset(att_res, 0, sizeof(bsal_gatt_res_t));
+    for (i = 0; p_srv[i].type != 0; i++)
+    {
+        //service
+        tmp_srv = p_srv + i;
+        if ((tmp_srv->type != BSAL_GATT_UUID_PRIMARY_SERVICE) &&
+                (tmp_srv->type != BSAL_GATT_UUID_SECONDARY_SERVICE))
+        {
+            bsal_osif_printf_err("wrong tmp_srv->type:%x", tmp_srv->type);
+            return;
+        }
+        att_res->attrs++;
+        att_res->svcs++;
+        if (tmp_srv->includes != NULL)
+        {
+            for (j = 0; tmp_srv->includes[j] != NULL; j++)
+            {
+                att_res->attrs++;
+                att_res->incs++;
+            }
+        }
+
+        if (tmp_srv->characteristics != NULL)
+        {
+
+            for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++)
+            {
+                tmp_chr = tmp_srv->characteristics + x;
+                att_res->chrs++;
+                att_res->attrs += 2;
+                if ((tmp_chr->properties & BSAL_ATT_P_NOTIFY) ||
+                        (tmp_chr->properties & BSAL_ATT_P_INDICATE))
+                {
+                    att_res->dscs++;
+                    att_res->cccds++;
+                    att_res->attrs++;
+                }
+
+                if (tmp_chr->descriptors != NULL)
+                {
+                    for (y = 0; tmp_chr->descriptors[y].uuid != NULL; y++)
+                    {
+                        att_res->dscs++;
+                        att_res->attrs++;
+                    }
+                }
+            }
+        }
+    }
+}
+
+uint16_t bsal_profile_get_start_handle(void *stack_ptr, uint16_t value_handle)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(start_handle);
+    uint8_t i = 0;
+    static uint16_t last_handle;
+
+    bsal_stack_obj_t *p_bsal_stack = stack_ptr;
+    last_handle = p_bsal_stack->bsal_srv_objs[0].start_handle;
+
+    for (i = 0; i < p_bsal_stack->srv_num; i++)
+    {
+        if (value_handle < p_bsal_stack->bsal_srv_objs[i].start_handle) //find the next value handle
+        {
+            if (value_handle > last_handle)
+            {
+                return last_handle;
+            }
+        }
+        else
+        {
+            last_handle = p_bsal_stack->bsal_srv_objs[i].start_handle;
+        }
+    }
+}
+
+
+
+uint16_t bsal_srv_get_start_handle(void *stack_ptr, bsal_uuid_any_t uuid)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    if (uuid.u_type == 16)
+    {
+        return bsal_profile_get_start_handle_by_16_uuid(stack_ptr, uuid.u16.value);
+    }
+    else
+    {
+        /* TODO deal with the 128 bit*/
+    }
+    return 0;
+}
+
+BSAL_STATUS bsal_profile_insert(void *stack_ptr, uint16_t handle, void *callback, bsal_uuid_any_t uuid)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    uint8_t i = 0;
+    bsal_stack_obj_t *p_bsal_stack = stack_ptr;
+
+    if (handle == 0xffff)
+    {
+        //add the end
+        i = p_bsal_stack->srv_num - 1;
+        p_bsal_stack->bsal_srv_objs[i].bsal_srv_fn_cb = (P_BSAL_PROFILE_CB)callback;
+        p_bsal_stack-> bsal_srv_objs[i].start_handle = handle;
+        memcpy(&p_bsal_stack-> bsal_srv_objs[i].srv_uuid, &uuid, sizeof(bsal_uuid_any_t));
+        return BSAL_RESULT_SUCCESS;
+    }
+
+
+    for (i = 0 ; i < p_bsal_stack->srv_num; i++)
+    {
+        if (p_bsal_stack->bsal_srv_objs[i].start_handle == 0)
+        {
+            p_bsal_stack->bsal_srv_objs[i].bsal_srv_fn_cb = (P_BSAL_PROFILE_CB)callback;
+            p_bsal_stack-> bsal_srv_objs[i].start_handle = handle;
+            memcpy(&p_bsal_stack-> bsal_srv_objs[i].srv_uuid, &uuid, sizeof(bsal_uuid_any_t));
+            //find device
+            return BSAL_RESULT_SUCCESS;
+        }
+    }
+    return BSAL_RESULT_FAIL;
+}
+
+
+bsal_srv_callback_t *bsal_profile_get(void *stack_ptr, uint16_t start_handle)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(start_handle);
+    uint8_t i = 0;
+
+    bsal_stack_obj_t *p_bsal_stack = stack_ptr;
+    for (i = 0 ; i < p_bsal_stack->srv_num; i++)
+    {
+        if (p_bsal_stack->bsal_srv_objs[i].start_handle == start_handle)
+        {
+            return &(p_bsal_stack->bsal_srv_objs[i]);
+        }
+    }
+
+    return NULL;
+}
+
+
+uint16_t bsal_profile_get_start_handle_by_16_uuid(void *stack_ptr, uint16_t uuid)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    uint8_t i = 0;
+    bsal_stack_obj_t *p_bsal_stack =  stack_ptr;
+    for (i = 0 ; i < p_bsal_stack->srv_num; i++)
+    {
+        if ((p_bsal_stack->bsal_srv_objs[i].srv_uuid.u_type == 16) && (p_bsal_stack->bsal_srv_objs[i].srv_uuid.u16.value == uuid))
+        {
+            return p_bsal_stack->bsal_srv_objs[i].start_handle;
+        }
+    }
+    return NULL;
+}
+//bond about
+
+uint8_t io_capablity[3][2] =
+{
+    {BSAL_GAP_IO_CAP_NO_INPUT_NO_OUTPUT, BSAL_GAP_IO_CAP_DISPLAY_ONLY},
+    {BSAL_GAP_IO_CAP_NO_INPUT_NO_OUTPUT, BSAL_GAP_IO_CAP_DISPLAY_YES_NO},
+    {BSAL_GAP_IO_CAP_KEYBOARD_ONLY, BSAL_GAP_IO_CAP_KEYBOARD_DISPLAY},
+};
+
+static uint8_t bsal_get_in_out_capability(uint8_t input, uint8_t output)
+{
+    return io_capablity[input][output];
+}
+
+//=======================ATT====OPERATE==========================
+
+int bsal_srv_write_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length, uint8_t *value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.cov_handle_to_u_handle);
+    return bsal_att_write_entry(stack_ptr, u_handle, value_length , value);
+}
+
+int bsal_srv_read_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t *value_length, uint8_t **value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    return bsal_att_read_entry(stack_ptr, u_handle, value_length , value);
+}
+
+int bsal_srv_create_att_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    return bsal_att_create_entry(stack_ptr, u_handle, value_length);
+}
+
+
+int bsal_srv_write_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.cov_handle_to_u_handle);
+    return bsal_att_write_entry(stack_ptr, p_ops->bsal_ops.cov_handle_to_u_handle(start_handle, offset_handle), value_length , value);
+}
+
+int bsal_srv_read_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t *value_length, uint8_t **value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    return bsal_att_read_entry(stack_ptr, p_ops->bsal_ops.cov_handle_to_u_handle(start_handle, offset_handle), value_length , value);
+}
+
+int bsal_srv_create_att(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    return bsal_att_create_entry(stack_ptr, p_ops->bsal_ops.cov_handle_to_u_handle(start_handle, offset_handle), value_length);
+}
+
+int bsal_srv_send_notify_data(void *stack_ptr, uint16_t conn_id, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    //check the MTU SIZE
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.le_srv_send_data);
+    return p_ops->bsal_ops.le_srv_send_data(conn_id, start_handle, offset_handle, value_length , value, BSAL_SEND_DATA_TYPE_ANY);
+}
+
+int bsal_srv_send_ind_data(void *stack_ptr, uint16_t conn_id, uint16_t service_id, uint16_t offset_handle, uint16_t value_length, uint8_t *value)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    //TODO check the MTU SIZE
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.le_srv_send_data);
+    return p_ops->bsal_ops.le_srv_send_data(conn_id, service_id, offset_handle, value_length , value, BSAL_SEND_DATA_TYPE_ANY);
+}
+//===============================================================STACK OPERATE=============================================
+
+void *bsal_find_stack_ptr(char *stack_name)
+{
+
+    bsal_osif_printf_dbg("%s line:%d: param %s", __FUNCTION__, __LINE__, stack_name);
+    //find the device name
+    //When init the rtk object has been insert the object
+    /*TODO */
+#ifdef PKG_BSAL_NIMBLE_STACK
+    extern bsal_stack_obj_t nimble_obj;
+    return &nimble_obj;
+#else
+    extern bsal_stack_obj_t rtk_obj;
+    return &rtk_obj;
+#endif
+
+
+}
+
+
+void bsal_stack_le_srv_begin(void *stack_ptr, uint8_t num, void *p_fun_cb)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_osif_printf_dbg("%s line:%d: param %d", __FUNCTION__, __LINE__, num);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.le_srv_reg_begin(false, num, p_fun_cb);
+
+    p_ops->bsal_srv_objs =  bsal_osif_malloc((num + 1) * sizeof(bsal_srv_callback_t));
+    p_ops->srv_num = num + 1;
+    //add common service callback
+    bsal_uuid_any_t srv_uuid;
+    srv_uuid.u_type = BSAL_UUID_TYPE_16BIT;
+    srv_uuid.u16.value = BSAL_SRV_UUID_GENERAL;
+    // add the generate uuid for except common profile
+    bsal_profile_insert(stack_ptr, 0xffff, p_fun_cb, srv_uuid);
+}
+
+int bsal_stack_le_srv_reg_func(void *stack_ptr, void *srv_def, P_SRV_GENERAL_CB *callback)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_osif_printf_dbg("%s line:%d: param srv_def :%p, callback: %p", __FUNCTION__, __LINE__, srv_def, callback);
+    //reg the serverice
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    //parse the struct
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.le_srv_reg_fun);
+    return p_ops->bsal_ops.le_srv_reg_fun(srv_def, callback);
+}
+void bsal_stack_le_srv_end(void *stack_ptr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_osif_printf_dbg("%s line:%d: param statck:%p", __FUNCTION__, __LINE__, stack_ptr);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    BSAL_ASSERT_PTR(p_ops->bsal_ops.le_srv_reg_end);
+    p_ops->bsal_ops.le_srv_reg_end();
+}
+
+
+
+int bsal_stack_init(void *stack_ptr, void *callback)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    BSAL_ASSERT_PTR(callback);
+    bsal_osif_printf_dbg("%s line:%d: param callback %p", __FUNCTION__, __LINE__, callback);
+
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+#define BSAL_BLE_STACK        0x01
+#define BSAL_LEGACY_STACK     0x02
+#define BSAL_MESH_STACK       0x04
+    p_ops->bsal_ops.init(BSAL_BLE_STACK);
+
+
+    //save the callback to the ops
+    p_ops->app_all_callbak = callback;
+
+
+    //set default param
+    //1. set scan respnse data
+    uint8_t tmp_data[32] = {0};
+    le_adv_ltv_t ltv;
+    ltv.length = 3;
+    ltv.type = BSAL_GAP_TYPE_APPEARANCE;
+    uint16_t tmp_uuid = BSAL_GAP_APPEARANCE_UNKNOWN;
+    ltv.value = (uint8_t *)&tmp_uuid;
+    bsal_le_adv_data_add_ltv(tmp_data, &ltv);
+    bsal_set_le_scan_rsp_data_user(stack_ptr, tmp_data);
+
+    //2. set adv param
+    /** @brief  Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */
+#define DEFAULT_ADVERTISING_INTERVAL_MIN            320
+    /** @brief  Default maximum advertising interval */
+#define DEFAULT_ADVERTISING_INTERVAL_MAX            320
+    bsal_adv_param_t temp_adv_param;
+    memset(&temp_adv_param, 0, sizeof(bsal_adv_param_t));
+    temp_adv_param.adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX;
+    temp_adv_param.adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN;
+    temp_adv_param.adv_type    = BSAL_GAP_ADTYPE_ADV_IND;
+    temp_adv_param.own_address_type = BSAL_GAP_REMOTE_ADDR_LE_PUBLIC;
+    temp_adv_param.direct_address_type = BSAL_GAP_REMOTE_ADDR_LE_PUBLIC;
+    temp_adv_param.channel_map = BSAL_GAP_ADVCHAN_ALL;
+    temp_adv_param.filter_policy = BSAL_GAP_ADV_FILTER_ANY;
+    bsal_set_le_adv_parm(stack_ptr, &temp_adv_param);
+
+//SET GAP NAME
+
+
+//
+    bsal_gaps_param_t gaps_param =
+    {
+        // .name = bsal_get_device_name(stack_ptr),
+        .apperance =   BSAL_GAP_APPEARANCE_UNKNOWN,
+    };
+    memcpy(gaps_param.name, bsal_get_device_name(stack_ptr), BSAL_MAX_NAME_LENGTH);
+    bsal_set_gap_param(stack_ptr, &gaps_param);
+    //load default;
+    bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false);
+
+    p_ops->g_att_index = 0;
+    return 0;
+}
+
+void bsal_stack_startup(void *stack_ptr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_osif_printf_dbg("%s line:%d: param stack_ptr %p", __FUNCTION__, __LINE__, stack_ptr);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.startup();
+}
+
+///PARAM
+//name
+int bsal_stack_set_gap_name(void *stack_ptr, uint8_t length, uint8_t *name)
+{
+
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_osif_printf_dbg("%s line:%d: param stack_ptr %p: length:%d, name:%s", __FUNCTION__, __LINE__, stack_ptr, length, name);
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    // p_ops->bsal_ops.set_gaps_param(length, name);
+
+    return 0;
+}
+
+int bsal_stack_get_gap_name(void *stack_ptr, uint8_t *name, uint8_t *length)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    return 0;
+}
+
+//mac address only get
+int bsal_stack_get_mac_addr(void *stack_ptr, uint8_t *bd_addr)
+{
+//    BSAL_ASSERT_PTR(stack_ptr);
+//    BSAL_ASSERT_PTR(bd_addr);
+//    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    return 0;
+}
+
+//adv
+int bsal_le_set_adv_param(void *stack_ptr, uint16_t value_length, bsal_adv_param_t *adv_param)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.le_set_adv_param(adv_param);
+    return 0;
+}
+
+int bsal_le_get_adv_param(void *stack_ptr, bsal_adv_param_t *adv_param)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.le_get_adv_param(adv_param);
+    return 0;
+}
+int bsal_set_device_name(void *stack_ptr, uint8_t length, uint8_t *name)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    memcpy(p_ops->bsal_info.device_name, name, length);
+    return 0;
+}
+
+uint8_t *bsal_get_device_name(void *stack_ptr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    return p_ops->bsal_info.device_name;
+}
+
+
+int bsal_sm_set_bond_mode(void *stack_ptr, bsal_bond_param_t *bond_type)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.set_bond_param(bond_type);
+    return 0;
+}
+
+int bsal_sm_get_bond_mode(void *stack_ptr, bsal_bond_param_t *bond_type)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.get_bond_param(bond_type);
+    return 0;
+}
+
+int bsal_get_bd_address(void *stack_ptr, uint8_t *bd_addr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.get_mac_address(BSAL_GAP_REMOTE_ADDR_LE_PUBLIC, bd_addr);
+    return 0;
+}
+
+int bsal_stack_start_adv(void *stack_ptr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.le_adv_enable(true);
+    return 0;
+}
+int bsal_stack_stop_adv(void *stack_ptr)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->bsal_ops.le_adv_enable(false);
+    return 0;
+}
+
+
+uint16_t bsal_set_device_le_bond_type(void *stack_ptr, bool is_bond, uint8_t input, uint8_t output, uint8_t bond_type, bool oob_enable)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_bond_param_t temp_bond_type;
+    temp_bond_type.bonding_flag = is_bond;
+    temp_bond_type.auth_type = bond_type;
+    temp_bond_type.oob_flag = oob_enable;
+    temp_bond_type.io_capability = bsal_get_in_out_capability(input, output);
+    temp_bond_type.sm_req_enable = false;
+    temp_bond_type.force_auth_type = 0;
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    p_ops->bsal_ops.set_bond_param(&temp_bond_type);
+    return 0;
+}
+
+uint16_t bsal_set_device_le_bond_param(void *stack_ptr, bsal_bond_param_t *bond_param)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    p_ops->bsal_ops.set_bond_param(bond_param);
+    return 0;
+}
+
+
+void bsal_set_le_adv_data(void *stack_ptr, uint8_t length, uint8_t *data)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    bsal_adv_param_t temp_adv_param;
+    temp_adv_param.set_param_flag = BSAL_SET_LE_ADV_DATA;
+    memcpy(temp_adv_param.adv_data, data, length);
+    if (length < 31)
+    {
+        p_ops->bsal_ops.le_set_adv_param(&temp_adv_param);
+    }
+    else
+    {
+        //ERROR
+    }
+
+}
+void bsal_set_le_adv_data_user(void *stack_ptr, uint8_t *adv_data)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_set_le_adv_data(stack_ptr, adv_data[0] + 1 , adv_data);
+}
+
+
+
+void bsal_set_le_srp_data(void *stack_ptr, uint8_t length, uint8_t *data)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    bsal_adv_param_t temp_adv_param;
+    temp_adv_param.set_param_flag = BSAL_SET_LE_SCAN_RSP_DATA;
+    memcpy(temp_adv_param.scan_rsp_data, data, length);
+    if (length < 31)
+    {
+        p_ops->bsal_ops.le_set_adv_param(&temp_adv_param);
+    }
+    else
+    {
+        //ERROR
+    }
+}
+
+void bsal_set_le_scan_rsp_data_user(void *stack_ptr, uint8_t *scan_rsp_data)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_set_le_srp_data(stack_ptr, scan_rsp_data[0] + 1 , scan_rsp_data);
+}
+
+void bsal_set_le_adv_parm(void *stack_ptr, bsal_adv_param_t *adv_param)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    adv_param->set_param_flag = BSAL_SET_LE_ADV_PARAM;
+    p_ops->bsal_ops.le_set_adv_param(adv_param);
+}
+
+
+void bsal_set_gap_param(void *stack_ptr, bsal_gaps_param_t *gaps_param)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    bsal_stack_obj_t *p_ops = (bsal_stack_obj_t *)stack_ptr;
+    p_ops->bsal_ops.set_gaps_param(gaps_param);
+}
+
+//API FOR CALLBACK  CALLED BY STACK
+int bsal_stack_ready(void *stack_ptr, bool status)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    //true is ready
+    //false is fail
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    if (status == true)
+    {
+        p_ops->app_all_callbak(p_ops, BSAL_CB_LAYER_GAP, BSAL_CB_STACK_READY, 0 , NULL);
+    }
+    else
+    {
+        p_ops->app_all_callbak(p_ops, BSAL_CB_LAYER_GAP, BSAL_CB_STACK_ERROR, 0 , NULL);
+    }
+    return 0;
+}
+
+int bsal_gap_connect_status(void *stack_ptr, uint16_t conn_handle, uint8_t connect_status, uint16_t disconnect_status)
+{
+    BSAL_ASSERT_PTR(stack_ptr);
+    T_BSAL_GAP_MSG_DATA  bsal_gap_msg_data;
+    bsal_gap_msg_data.gap_conn_state_change.new_state = connect_status;
+    bsal_gap_msg_data.gap_conn_state_change.conn_id = conn_handle;
+    bsal_gap_msg_data.gap_conn_state_change.disc_cause = disconnect_status;
+    struct bsal_stack_obj *p_ops = (struct bsal_stack_obj *)stack_ptr;
+    p_ops->app_all_callbak(p_ops, BSAL_CB_LAYER_GAP, BSAL_CB_CONNECT_STATUS, sizeof(bsal_gap_msg_data) , &bsal_gap_msg_data);
+    return 0;
+}
+