├── LICENSE ├── README.md ├── SConscript ├── doc ├── RT-Thread BSAL软件包介绍及移植指南.md └── figures │ ├── BSAL_INTERAL.jpg │ ├── adv.png │ ├── bal_framework.jpg │ ├── ble_soc.jpg │ ├── image-20200618155732239.png │ ├── mcu_ble_soc.jpg │ ├── menuconfig.png │ ├── sal_framework.jpg │ └── srv_table.png ├── inc ├── bsal.h ├── bsal_app_api.h ├── bsal_common.h ├── bsal_int.h ├── bsal_osif.h ├── bsal_sig.h └── bsal_stack_api.h ├── port ├── NIMBLE │ ├── bsal_nimble.c │ ├── bsal_nimble.h │ └── bsal_osif.c ├── empty_stack │ ├── bsal_osal_empty.c │ ├── bsal_stack_empty.c │ └── bsal_stack_empty.h └── realtek │ ├── bsal_osif.c │ ├── bsal_rtk.c │ └── bsal_rtk.h ├── profiles └── service │ ├── basl_bas │ ├── bsal_srv_bas.c │ └── bsal_srv_bas.h │ ├── bsal_blufi │ ├── bsal_srv_blufi.c │ └── bsal_srv_blufi.h │ ├── bsal_dis │ ├── bsal_srv_dis.c │ └── bsal_srv_dis.h │ ├── bsal_hid │ ├── README.md │ ├── Softdevice │ │ ├── ble_hids.c │ │ ├── ble_hids.h │ │ └── main.c │ ├── bsal_srv_hid.c │ ├── bsal_srv_hid.h │ ├── btsnoop_hci_hid.cfa │ └── images │ │ ├── 2021-10-12135211.jpg │ │ ├── 2021-10-12135502.jpg │ │ └── 2021-10-12145729.jpg │ ├── bsal_hrs │ ├── bsal_srv_hrs.c │ └── bsal_srv_hrs.h │ ├── bsal_lbs │ ├── bsal_srv_lbs.c │ └── bsal_srv_lbs.h │ └── bsal_uart │ ├── bsal_srv_uart.c │ └── bsal_srv_uart.h ├── samples ├── ble_bas_blufi_app.c ├── ble_bas_only_app.c ├── ble_hogp_app.c ├── ble_hrs_app.c ├── ble_lbs_app.c └── ble_nus_app.c └── src └── bsal.c /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BSAL 2 | 3 | ## 1. BSAL 软件包介绍 4 | 5 | BSAL (Bluetooth Stack Abstract Layer)软件包是由 RT-Thread 针对不同 蓝牙协议栈接口实现的,目前支持的 协议栈有:nimble,realtek 等协议栈。 6 | 7 | > 提示:目前支持芯片为 Realtek 和 Nordic,若在其他芯片上使用该软件包,编译将通不过。 8 | 9 | ### 1.1 背景介绍 10 | 11 | Bluetooth Stack Abstract Layer 蓝牙协议栈抽象层。用于适配各家协议栈以及底层卡片。 12 | 13 | 主要在协议栈基础之上封装一层抽象层接口。 14 | 15 | ## 2. BSAL 使用说明 16 | 17 | BSAL 配置如下图所示: 18 | 19 | ![img](./doc/figures/menuconfig.png) 20 | 21 | 选择需要生成的角色(默认选择 Peripheral 即可): 22 | 23 | - Peripheral role: 24 | - Central role 25 | - Broadcaster role 26 | - Observer role 27 | 28 | 选择不同的示例可以实现不同的 APP 功能: 29 | 30 | - Battery service 单 battery servcie 测试 sample 31 | - battery and blufi service 两个 profile servic(blufi 配网, bas)测试 sample 32 | 33 | 再选择对应的协议栈: 34 | 35 | - nimble (nimble 协议栈适配层) 36 | - realtek (realtek 协议栈适配层) 37 | - empty_stack (移植协议栈模板) 38 | 39 | ## 3. BSAL 依赖 40 | 41 | BSAL 依赖对应的协议栈,比如 nimble,需要先有 nimble+RTT 的 sample 工程,首先确保可以跑对应协议栈的原生的 sample。再试着添加 BSAL 层跑 sample 42 | 43 | 每个 sample 对应一个 cmd: 44 | 45 | - battery service: bsal_bas_app 46 | - battery and blufi service: bsal_bas_blufi_app 47 | 48 | 输入对应的 cmd 即可。 49 | 50 | ## 4. 测试验证工具 51 | 52 | 输入 cmd bsal_bas_blufi_app 启动 sample 53 | 54 | 手机下载 nRF Connect 工具(apple 使用 lightblue) 55 | 56 | [nRF Connect](https://github.com/NordicSemiconductor/Android-nRF-Connect/releases) 57 | 58 | 搜索广播看到如下界面: 59 | 60 | ![image-20200618164034578](./doc/figures/adv.png) 61 | 62 | 点击 connect 连接上之后: 63 | 64 | ![image-20200618164126725](./doc/figures/srv_table.png) 65 | 66 | 可以看到 battery service 和 0xffff 配网 blufi service,说明 sample 运行成功。 67 | 68 | ## 5. BSAL 入门指引 69 | 70 | 1. 如果没有蓝牙开发的经验,可以先学习一下基础知识:[supperthomas_wiki](https://supperthomas-wiki.readthedocs.io/en/latest/index.html#) 71 | 72 | 2. 简单入门 BSAL:[文档地址](https://github.com/WaterFishJ/Summer2021_docs/tree/master/%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8BSAL) 73 | 3. bas_sample 分析:[文档地址](https://github.com/WaterFishJ/Summer2021_docs/blob/master/pca10056%E7%9A%84bsal%E5%B1%82bas_sample%E8%A7%A3%E6%9E%90/pca10056%E7%9A%84bsal%E5%B1%82bas_sample%E8%A7%A3%E6%9E%90.md) 74 | 4. BSAL 实现 HRS:[文档地址](https://github.com/WaterFishJ/Summer2021_docs/blob/master/bsal%E5%B1%82%E5%AE%9E%E7%8E%B0HRS/bsal%E5%B1%82%E5%AE%9E%E7%8E%B0HRS.md) 75 | 76 | 3. 蓝牙技术联盟的 SPEC:[链接地址](https://www.bluetooth.com/specifications/specs/) 77 | 78 | 4. UUID 列表:[链接地址](https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf) -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | from building import * 2 | import rtconfig 3 | 4 | cwd = GetCurrentDir() 5 | path = [cwd] 6 | src = [] 7 | 8 | path += [ 9 | cwd + '/inc'] 10 | 11 | # Host stack 12 | src += Split(''' 13 | src/bsal.c 14 | ''') 15 | 16 | if GetDepend(['PKG_BSAL_SRV_BAS']): 17 | path += [cwd + '/profiles/service/basl_bas'] 18 | src += Split(""" 19 | profiles/service/basl_bas/bsal_srv_bas.c 20 | """) 21 | 22 | if GetDepend(['PKG_BSAL_SRV_BLUFI']): 23 | path += [cwd + '/profiles/service/bsal_blufi'] 24 | src += Split(""" 25 | profiles/service/bsal_blufi/bsal_srv_blufi.c 26 | """) 27 | 28 | if GetDepend(['PKG_BSAL_SRV_NUS']): 29 | path += [cwd + '/profiles/service/bsal_uart'] 30 | src += Split(""" 31 | profiles/service/bsal_uart/bsal_srv_uart.c 32 | """) 33 | 34 | if GetDepend(['PKG_BSAL_SRV_LBS']): 35 | path += [cwd + '/profiles/service/bsal_lbs'] 36 | src += Split(""" 37 | profiles/service/bsal_lbs/bsal_srv_lbs.c 38 | """) 39 | 40 | if GetDepend(['PKG_BSAL_SRV_DIS']): 41 | path += [cwd + '/profiles/service/bsal_dis'] 42 | src += Split(""" 43 | profiles/service/bsal_dis/bsal_srv_dis.c 44 | """) 45 | 46 | if GetDepend(['PKG_BSAL_SRV_HRS']): 47 | path += [cwd + '/profiles/service/bsal_hrs'] 48 | src += Split(""" 49 | profiles/service/bsal_hrs/bsal_srv_hrs.c 50 | """) 51 | 52 | if GetDepend(['PKG_BSAL_SAMPLE_BAS_ONLY']): 53 | src += Split(""" 54 | samples/ble_bas_only_app.c 55 | """) 56 | elif GetDepend(['PKG_BSAL_SAMPLE_BAS_BLUFI_COMBINE']): 57 | src += Split(""" 58 | samples/ble_bas_blufi_app.c 59 | """) 60 | elif GetDepend(['PKG_BSAL_SAMPLE_NUS_ONLY']): 61 | src += Split(""" 62 | samples/ble_nus_app.c 63 | """) 64 | elif GetDepend(['PKG_BSAL_SAMPLE_LBS_ONLY']): 65 | src += Split(""" 66 | samples/ble_lbs_app.c 67 | """) 68 | elif GetDepend(['PKG_BSAL_SAMPLE_HRS_ONLY']): 69 | src += Split(""" 70 | samples/ble_hrs_app.c 71 | """) 72 | 73 | 74 | if GetDepend(['PKG_BSAL_NIMBLE_STACK']): 75 | path += [cwd + '/port/nimble'] 76 | src += Split(""" 77 | port/nimble/bsal_nimble.c 78 | port/nimble/bsal_osif.c 79 | """) 80 | 81 | elif GetDepend(['PKG_BSAL_RTK_STACK']): 82 | path += [cwd + '/port/realtek'] 83 | src += Split(""" 84 | port/realtek/bsal_rtk.c 85 | port/realtek/bsal_osif.c 86 | """) 87 | 88 | elif GetDepend(['PKG_BSAL_EMPTY_STACK']): 89 | path += [cwd + '/port/empty_stack'] 90 | src += Split(""" 91 | port/empty_stack/bsal_osal_empty.c 92 | port/empty_stack/bsal_stack_empty.c 93 | """) 94 | 95 | if rtconfig.CROSS_TOOL == 'keil': 96 | LOCAL_CCFLAGS = ' --gnu' 97 | 98 | group = DefineGroup('bsal', src, depend = ['PKG_USING_BSAL'], CPPPATH = path, LOCAL_CCFLAGS = LOCAL_CCFLAGS) 99 | 100 | Return('group') 101 | -------------------------------------------------------------------------------- /doc/RT-Thread BSAL软件包介绍及移植指南.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # RT-Thread BSAL软件包介绍及移植指南 4 | 5 | ## 1. BSAL 软件包介绍 6 | 7 | BSAL (Bluetooth Stack Abstract Layer)软件包是由 RT-Thread 针对不同 蓝牙协议栈接口实现的,目前支持的 协议栈有:nimble,realtek等协议栈 。 8 | 9 | ### 1.1 背景介绍 10 | 11 | Bluetooth Stack Abstract Layer 蓝牙协议栈抽象层。用于适配各家协议栈以及底层卡片。 12 | 13 | 主要在协议栈基础之上封装一层抽象层接口。 14 | 15 | #### 1.1.1 具体问题介绍 16 | 17 | - 各家厂商都有自己独有的协议栈,协议栈接口之间不通用。 18 | - 根据SIG标准的profile,各家都基于自家协议栈实现代码,工作量比较大而不通用。 19 | - 基于ble profile的代码,大部分厂家的代码都是开放的。 20 | - BLE GATT的操作比较统一,适合整合成一套统一的接口。 21 | - GAP抽象接口行为一致,但各家接口都不统一 22 | - 各家的profile和ble相关的app代码只能适配自家代码 23 | - 基于开源协议栈的接口,也不够通用 24 | 25 | 基于这些问题,我们推出BSAL层接口,为了兼容多家MCU的协议栈和方便后续拓展性。 26 | 27 | ### 1.2 应用场景 28 | 29 | #### 1.2.1 应用场景框架 30 | 31 | 针对该接口的使用场景,总结出以下几个应用场景: 32 | 33 | - 点对点自定义协议栈蓝牙GATT透传自定义协议(这种profile自定义,只需要数据传输过去即可,完成数据收发)通常作为service端。 34 | - 基于BLE 标准PROFILE的SIG sample(比如:心率计(HRS), HID设备(HOGP), 设备信息(DIS),电池服务(BAS)通常作为service端, central端比较少,通常central为手机。 35 | - 基于PB-ADV的MESH协议栈,通常作为broadcaster, observer 36 | - blufi 配网 对于特定的带有WIFI模块的芯片 37 | - MCU + BT SOC通信调用,BT SOC作为BSAL层的执行端,MCU作为BSAL的发起端 38 | 39 | #### 1.2.2 应用产品 40 | 41 | 基于上面的API,可以开发出对应的蓝牙应用产品: 42 | 43 | - 电子名片(可以用于手机编辑,以及WIFI配网,IOT控制LED小灯等操作) 44 | - 手机微信小程序控制小车(作为遥控器,控制带有ble的小车系统),作为一个遥控器来控制,可以不用依赖红外那种指向性的,比WIFI省电。 45 | - 蓝牙遥控器。手机小程序有遥控器界面,来控制带有USB设备的电脑,电视以及等等设备,用蓝牙模拟HID设备。解决的痛点主要是经常遥控器断电,遥控器找不到了。 46 | - 蓝牙小键盘。带USB的两颗蓝牙卡片,一个做成小键盘,一个做成USB HID device 47 | - 蓝牙pos机,基于自定义透传协议。 48 | - 阿里mesh智能家居小灯等设备。 49 | - micropython对应的python ubluetooth应用。 50 | - MCU + BT_soc 轻量级的控制的场景 51 | - 智能穿戴BLE操作,后续会考虑支持BR/EDR的接口操作 52 | - 智能音响,mesh,A2DP,HFP,ble 53 | - 自行车码表 54 | 55 | ### 1.3 软件包的介绍 56 | 57 | BSAL作为一层通用层,隔开app和stack之间的接口。因为要尽量兼容各家协议栈的不同类型的接口,所以需要一些额外的开支。当然这个可以在进一步的迭代过程中逐步优化。 58 | 59 | #### 1.3.1 框架介绍 60 | 61 | ![BAL 系统框架图](./figures/bal_framework.jpg) 62 | 63 | #### 1.3.2 主要功能介绍 64 | 65 | ##### 1.3.2.1 适配性 66 | 67 | 可以适配大部分的厂商的蓝牙协议栈接口,如果接口不适配,也有冗余接口进行拓展适配。 68 | 69 | 当然如果没有协议栈,可以使用nimble+RTT的方式进行HCI 层对接适配,也是可以使用BSAL上层的接口的。 70 | 71 | ##### 1.3.2.2 可移植性 72 | 73 | 可以方便移植到不同平台,BSAL层尽量做到能适配大部分的BLE STACK平台,只做上层逻辑的接口的优化和实现,并不针对某个特定的硬件或者协议栈。 74 | 75 | #### 1.3.3 目录结构 76 | 77 | BSAL目录结构: 78 | 79 | ``` 80 | ├───docs // 相关文档 81 | ├───inc // 组件头文件 82 | │ ├───bsal.h // bsal总头文件 83 | │ ├───bsal_app_api.h // bsalAPP和profile需要调的API接口 84 | │ ├───bsal_common.h // bsal通用结构体定义 85 | │ ├───bsal_int.h // bsal移植协议栈需要了解的接口 86 | │ ├───bsal_sig.h // bsal中根据SIG规定的接口和标准值 87 | │ ├───bsal_stack_api.h // bsal协议栈接口API 88 | │ └───bsal_osif.h // bsal调用到的OS相关的接口 89 | ├───port // 移植适配文件 90 | │ ├───empty_stack // 空协议栈平台(给第一次移植需要使用的空模板) 91 | │ ├───realtek // REALTEK协议栈适配文件 92 | │ └───nimble // NIMBLE协议栈适配源文件 93 | ├───src 94 | │ └───bsal.c //将stack接口封装一层,供profile调用 95 | ├───profile // 各种 蓝牙 profile 文件 96 | │ ├───client // profile作为主机端的操作源文件 97 | │ ├───service // profile作为service端的操作源文件 98 | │ ├───basl_bas // battery service 源文件头文件 99 | │ ├───bsal_srv_bas.h // bas service 头文件 100 | │ └───bsal_srv_bas.c // bas service 源文件 101 | │ ├───bsal_blufi // blufi 蓝牙wifi配网 102 | │ ├───bsal_srv_blufi.h // bas service 头文件 103 | │ └───bsal_srv_blufi.c // bas service 源文件 104 | ├───sample 105 | │ ├───ble_bas_only_app.c // 只有battery servcie的源文件 106 | │ └───ble_bas_blufi_app.c // 带有bas和blufi两个profile的源文件 107 | ├───README.md // 108 | └───SConscript //软件包scons脚本 109 | ``` 110 | 111 | 112 | 113 | #### 1.3.4 配置选项 114 | 115 | BSAL 组件配置: 116 | 117 | ``` 118 | [*] BSAL: The Bluetooth Stack Abstract Layer 119 | [ ] Bluetooth Role support ---> // BLE 支持角色 120 | [*] Peripheral role // perpheral 角色 121 | [ ] Central Role // central 角色 122 | [ ] Broadcaster Role // broadcaster 角色 123 | [ ] Observer Role // Observer role 124 | (1) The maximum link of supported ble link // BLE 最大link数 125 | [ ] Bluetooth sample ----> // sample 126 | [ ] BLE peripheral 127 | [ ] ble battery service sample // ble battery service sample 128 | [ ] ble bluefi sample // ble 配网 sample 129 | [ ] BSAL STACK SELECT---> // 单选 130 | () RTK // 支持realtek的协议栈 131 | () Nordic softdevice // 支持nordic的协议栈 132 | () NIMBLE // 支持nimble开源协议栈 133 | ``` 134 | 135 | 配置选项可以选择不同协议栈、不同profile service的支持,以及角色的支持 136 | 137 | #### 1.3.5 API接口介绍 138 | 139 | API接口主要分为两部分,一部分对于用户来讲,写APP和profile需要知道的接口。还有一部分对于协议栈和蓝牙卡片来讲,需要实现的接口。 140 | 141 | ##### 1.3.5.1 APP用户接口介绍 142 | 143 | 对于 用户APP和profile来言,需要了解协议栈初始化接口,以及 144 | 145 | ````c 146 | //1. STACK API 应用层调用 147 | /* stack 根据name 找到stack指针*/ 148 | void *bsal_find_stack_ptr(char *stack_name); 149 | 150 | /* stack 初始化,并注册协议栈的callback函数 */ 151 | int bsal_stack_init(void *stack_ptr, void *callback); 152 | 153 | /* stack 开始注册profile service , 并注册通用profile的回调函数*/ 154 | void bsal_stack_le_srv_begin(void *stack_ptr, uint8_t num, void *p_fun_cb); 155 | 156 | /* stack 结束注册profile service*/ 157 | void bsal_stack_le_srv_end(void *stack_ptr); 158 | 159 | /* stack 开始运行*/ 160 | void bsal_stack_startup(void *stack_ptr); 161 | 162 | //2. SERVICE API 163 | /* profile 注册自己的service table,并注册回调函数*/ 164 | typedef BSAL_STATUS(*P_SRV_GENERAL_CB)(void *p_para); 165 | int bsal_stack_le_srv_reg_func(void *stack_ptr, void *srv_def, P_SRV_GENERAL_CB *callback); 166 | 167 | //3. SERVICE SEND DATA 168 | /* service 发送NOTIFY数据 */ 169 | 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); 170 | 171 | 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); 172 | 173 | ```` 174 | 175 | #### 1.3.6 使用说明(BLE 流程 for APP) 176 | 177 | ##### 1.3.6.1 广播使用流程 178 | 179 | 对于peripheral而言,首先需要打广播 180 | 181 | 广播样例代码如下: 182 | 183 | ```c 184 | //1. 申请一个32byte的数组,用于存放广播内容 185 | uint8_t tmp_data[32] = {0} ; //must be zero 186 | //2. 添加广播中的flag 187 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 188 | //3. 添加广播中的名字 189 | char *adv_name = "rtt_ble"; 190 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 191 | //4. 添加广播中的服务内容 192 | bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 193 | //5. 设置广播内容 194 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 195 | //6. 开始广播 196 | bsal_stack_start_adv(stack_ptr); 197 | ``` 198 | 199 | ##### 1.3.6.2 profile service 的TX RX使用流程 200 | 201 | 了解TX RX需要知道一个相对handle和绝对handle。 202 | 203 | 绝对handle是该ATT在整个project中的绝对地址,BSAL存储的是绝对地址,该地址是惟一的。profile处理的是相对handle,该handle是相对于profile的相对偏移,off_handle就是相对偏移,u_handle就是绝对偏移, 204 | 205 | 只要保证u_handle唯一即可,这个需要根据 协议栈的callback的接口来定位。 206 | 207 | - service READ REQUEST操作 208 | 209 | 手机或者central给service 发送READ 数据的时候,以nimble为例 210 | 211 | 原生stack先唤醒nimble中的回调函数: 212 | 213 | ``` 214 | nimble_chrs[x].access_cb = bsal_ble_svc_bas_access; 215 | ``` 216 | 217 | bsal_ble_svc_bas_access这个函数处理的事件: 218 | 219 | BLE_GATT_ACCESS_OP_READ_CHR: 220 | 221 | 这个时候,先从bsal_srv_objs service table中找到回调函数,然后先通知到profile层。 222 | 223 | profile对数据进行解析之后,判断是否要通知APP层,对端来读取数据,如果觉得不需要通知,直接返回对应的值即可。 224 | 225 | PROFILE如果对于某个值需要进行更新,调用BSAL提供的接口: 226 | 227 | ``` 228 | //这个接口主要讲数据值写入到att数据库中,方便BSAL读取该值返回给STACK 229 | int bsal_srv_write_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value); 230 | ``` 231 | 232 | - service WRITE requst/cmd 操作 233 | 234 | 手机或者central要给service 写入某个值的时候,以nimble为例: 235 | 236 | 根据callback中的BLE_GATT_ACCESS_OP_WRITE_CHR事件,由STACK回调上来, 237 | 这个时候,先从bsal_srv_objs service table中找到回调函数,然后先通知到profile层。 238 | 239 | PROFILE如果需要存储该值,做对应的处理即可,自行选择什么时候通知上层APP。 240 | 241 | write 本质上并没有长度上的限制,由profile决定数据该如何处理即可。 242 | 243 | - service notify 操作 244 | 245 | service 如果想要主动给client端发数据,client端必须先打开CCCD。 并且service 中的该character需要有notify这个属性。主要打开,service 才可以发数据给client端。 246 | 247 | 发送调用接口: 248 | 249 | ``` 250 | 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); 251 | ``` 252 | 253 | ### 1.4 软件包的使用 254 | 255 | 可以选择不同的 sample 做对应的 app 应用开发 256 | 257 | ## 2. 移植指南 258 | 259 | ### 2.1 STACK 移植接口介绍: 260 | 261 | 先介绍下协议栈 object 指针内容: 262 | 263 | ```c 264 | struct bsal_stack_obj 265 | { 266 | /* stack 是否 ready */ 267 | bool stack_ready_flag; 268 | /* stack 主要 OP 操作 */ 269 | bsal_stack_ops_t bsal_ops; 270 | /* att 数据库 */ 271 | bsal_gatt_value_entry_t *db; 272 | /* service profile 的数据库,存放 profile 的callback */ 273 | bsal_srv_callback_t *bsal_srv_objs; 274 | 275 | /* 存放 static 临时信息: */ 276 | bsal_stack_info_t bsal_info; 277 | /* gatt index 的handle的全局变量 */ 278 | uint16_t g_att_index; 279 | /* 注册的profile的数量 */ 280 | uint8_t srv_num; 281 | /* 存放APP注册的stack的回调函数 */ 282 | void (*app_all_callbak)(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value); 283 | }; 284 | ``` 285 | 286 | 这个结构体是贯穿整个BSAL api体系的指针接口。 287 | 288 | 协议栈主要需要实现的接口是bsal_ops里面的接口,如下所示: 289 | 290 | ```c 291 | struct bsal_stack_ops 292 | { 293 | /* 设置LE 协议栈的参数 (预留,暂时不用实现) */ 294 | BSAL_STATUS(*le_set_stack_param)(uint32_t value_length, uint8_t *value); 295 | /* 获取LE 协议栈的参数 (预留,暂时不用实现) */ 296 | BSAL_STATUS(*le_get_stack_param)(uint32_t value_length, uint8_t *value); 297 | /* 获取MAC 地址 */ 298 | void (*get_mac_address)(uint8_t addr_type, uint8_t *bd_addr); /* 协议栈初始化 */ 299 | void (*init)(uint8_t stack_type); /* 协议栈启动 */ 300 | void (*startup)(void); /* 设置bond 相关参数*/ 301 | void (*set_bond_param)(bsal_bond_param_t *value); 302 | /* 获取bond相关的参数*/ 303 | void (*get_bond_param)(bsal_bond_param_t *value); 304 | /*设置广播 相关参数*/ 305 | void (*le_set_adv_param)(bsal_adv_param_t *adv_param); 306 | /* 获取广播 相关参数*/ 307 | void (*le_get_adv_param)(bsal_adv_param_t *adv_param); 308 | /* 开始广播 */ 309 | BSAL_STATUS(*le_adv_enable)(bool enable); 310 | /* 设置GAPS层的参数 */ 311 | void (*set_gaps_param)(bsal_gaps_param_t *gaps_param); 312 | 313 | /* 对于service提供的接口*/ 314 | /* 从相对的service id和offset_handle转换成绝对的唯一的handle*/ 315 | uint32_t (*cov_handle_to_u_handle)(uint16_t service_id, uint16_t offset_handle); /* 开始注册service */ 316 | BSAL_STATUS(*le_srv_reg_begin)(bool is_continue, uint8_t service_num, void *p_func); 317 | /* 注册service table*/ 318 | BSAL_STATUS(*le_srv_reg_fun)(struct bsal_gatt_app_srv_def *p_srv, void *p_func); 319 | /* 结束注册service */ 320 | BSAL_STATUS(*le_srv_reg_end)(void); 321 | /* servcie发送数据 */ 322 | 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); 323 | /* service 发送数据完成 (预留)*/ 324 | BSAL_STATUS(*send_notify_complete)(uint32_t credits); /*TODO*/ 325 | }; 326 | ``` 327 | 328 | 这边预留的接口比较多,需要实现的接口如下面介绍的接口,下面接口是必须要实现的,并且要优先实现的,其他接口可以慢慢实现。 329 | 330 | - init: 这个完成协议栈的初始化自身的初始化 331 | - startup: 这个接口实现协议栈开始启动的函数 332 | - le_srv_send_data: service 端给client端notify数据或者indicate数据。 333 | 334 | 优先实现上述接口。 335 | 336 | 其他接口可以按照下面的移植流程中的步骤,慢慢理解实现。 337 | 338 | 需要提醒的是:对于STACK内部移植,需要了解BLE里面的GATT基本原理,需要有比较详细的了解。 339 | 340 | ### 2.2 移植流程 341 | 342 | 以nimble的移植为例 。 343 | 344 | #### 2.2.1 步骤一 建工程 345 | 346 | 先找一个nimble的最简单的,带有battery service 一个profile操作的工程,确保手机可以搜索到battery service。并且可以连接上。最好这个工程能有RTT的支持, 347 | 348 | 以nimble+nrf52840的工程为例 349 | 350 | #### 2.2.2 步骤二 加入 BSAL 移植框架,编译通过 351 | 352 | 从RTT软件包里面选中BSAL软件包。 353 | 354 | ![image-20200618155732239](.\figures\image-20200618155732239.png) 355 | 356 | scons 加入 empty_stack ,里面的协议栈相关的函数都已经注释掉了,编译通过。 357 | 358 | #### 2.2.3 步骤三 实现 init startup 359 | 360 | 先实现ops 中的 init 和 startup 函数,确保协议栈在BSAL上面初始化和启动正常; 361 | 362 | - init :调用移植协议栈的初始化函数。(包含协议栈参数设置,广播参数,bas service 注册) 363 | - startup: 启动协议栈的函数。 364 | 365 | #### 2.2.4 步骤四 实现TX RX流程 366 | 367 | **功能实现** 368 | 369 | 首先用原始service 的service table和adv enable 370 | 371 | - 将 gap callback 的函数放到BSAL里面 372 | - bas service 注册的时候,把APP的callback 通过接口bsal_profile_insert注册到BSAL数据库中 373 | - 在nimble的READ回调函数中,根据handle来调用对应service的回调函数bsal_srv_fn_cb 374 | - 在nimble的WRITE 回调中,掉对应的service的回调函数bsal_srv_fn_cb通知service 375 | 376 | 完成可以read write notify等接口即可。(确保数据可以根据handle来传输即可) 377 | 378 | **功能验证** 379 | 380 | 用手机nrf connect 验证TX RX 381 | 382 | 【图片】 383 | 384 | #### 2.2.5 步骤四 转换profile table 385 | 386 | **功能实现** 387 | 388 | 将BSAL定义的BAS TABLE数组接口: 389 | 390 | ```c 391 | struct bsal_gatt_app_srv_def ble_svc_bas_defs[] = 392 | { 393 | { 394 | /*** Battery Service. */ 395 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 396 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),//(bsal_uuid_any_t *)&battery_srv,//BSAL_UUID16_DECLARE(GATT_UUID_BATTERY), 397 | .characteristics = (bsal_gatt_chr_def_t[]) 398 | { 399 | { 400 | /*** Battery level characteristic */ 401 | .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), 402 | .properties = BSAL_ATT_P_READ 403 | | BSAL_ATT_P_NOTIFY 404 | , 405 | .permission = GATT_PERM_READ, 406 | .value_length = 1, 407 | }, 408 | { 409 | 0, /* No more characteristics in this service. */ 410 | } 411 | }, 412 | }, 413 | 414 | { 415 | 0, /* No more services. */ 416 | }, 417 | }; 418 | ``` 419 | 420 | 想办法转换成nimble可以识别的接口。 421 | 422 | 在函数le_srv_reg_fun中实现对应的service功能。 423 | 424 | 这一步纯粹是本地代码的转换工作,确保BSAL注册的service 转换成nimble对应的service 注册进去,能够将ATT的属性等信息完全相同即可。 425 | 426 | **功能验证** 427 | 428 | 先用bas service 验证, 429 | 430 | 后面用blufi service 功能验证 431 | 432 | #### 2.2.5 步骤五 完善广播等其他接口 433 | 434 | 这一步也是纯粹代码的转换工作,主要是将广播数据(小于32byte)设置到协议栈中去,至于如何转换,根据协议栈的接口来调用相应的接口即可。 435 | 436 | -------------------------------------------------------------------------------- /doc/figures/BSAL_INTERAL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/BSAL_INTERAL.jpg -------------------------------------------------------------------------------- /doc/figures/adv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/adv.png -------------------------------------------------------------------------------- /doc/figures/bal_framework.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/bal_framework.jpg -------------------------------------------------------------------------------- /doc/figures/ble_soc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/ble_soc.jpg -------------------------------------------------------------------------------- /doc/figures/image-20200618155732239.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/image-20200618155732239.png -------------------------------------------------------------------------------- /doc/figures/mcu_ble_soc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/mcu_ble_soc.jpg -------------------------------------------------------------------------------- /doc/figures/menuconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/menuconfig.png -------------------------------------------------------------------------------- /doc/figures/sal_framework.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/sal_framework.jpg -------------------------------------------------------------------------------- /doc/figures/srv_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/doc/figures/srv_table.png -------------------------------------------------------------------------------- /inc/bsal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #ifndef __BSAL_H__ 12 | #define __BSAL_H__ 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #include 18 | #include 19 | 20 | #define BSAL_SW_VERSION "0.1.0" 21 | #define BSAL_SW_VERSION_NUM 0x01000 22 | 23 | #include "bsal_sig.h" 24 | 25 | #include "bsal_common.h" 26 | #include "bsal_app_api.h" 27 | 28 | //CALLBACK_EVENT 29 | typedef enum 30 | { 31 | BSAL_CB_LAYER_GAP = 0xF1, 32 | BSAL_CB_LAYER_GATT_PROFILE, 33 | BSAL_CB_LAYER_SM, 34 | BSAL_CB_LAYER_COMMON, 35 | BSAL_CB_LAYER_UNKNOWN 36 | } T_BSAL_APP_CB_LAYER_TYPE; 37 | 38 | typedef enum 39 | { 40 | BSAL_CB_STACK_READY = 0xD1, 41 | BSAL_CB_CONNECT_STATUS, 42 | BSAL_CB_STACK_ERROR = 0xFF, 43 | } T_BSAL_GAP_SUBEVENT_TYPE; 44 | 45 | typedef enum 46 | { 47 | BSAL_GAP_CONN_STATE_DISCONNECTED, //!< Disconnected. 48 | BSAL_GAP_CONN_STATE_CONNECTING, //!< Connecting. 49 | BSAL_GAP_CONN_STATE_CONNECTED, //!< Connected. 50 | BSAL_GAP_CONN_STATE_DISCONNECTING //!< Disconnecting. 51 | } T_BSAL_GAP_CONN_STATE; 52 | 53 | struct bsal_gap_conn_status 54 | { 55 | uint8_t conn_id; 56 | uint8_t new_state; 57 | uint16_t disc_cause; 58 | }; 59 | typedef struct bsal_gap_conn_status bsal_gap_conn_status_t; 60 | 61 | typedef union 62 | { 63 | bsal_gap_conn_status_t gap_conn_state_change; 64 | } T_BSAL_GAP_MSG_DATA; 65 | 66 | 67 | //bit 0...3 is read permision bit 4..7 write permission bit 8...12 notify indicate permision 68 | 69 | #define BSAL_GATT_PERM_NONE 0x00 70 | #define BSAL_GATT_PERM_ALL 0x01 71 | #define BSAL_GATT_PERM_AUTHEN_REQ 0x02 72 | #define BSAL_GATT_PERM_AUTHEN_MITM_REQ 0x03 73 | #define BSAL_GATT_PERM_AUTHOR_REQ 0x04 /**< bits 2 (rd), 6 (wr), 10 (notif/ind) */ 74 | #define BSAL_GATT_PERM_ENCRYPTED_REQ 0x08 /**< bits 3 (rd), 7 (wr), 11 (notif/ind) */ 75 | #define BSAL_GATT_PERM_AUTHEN_SC_REQ 0x09 76 | 77 | #define BSAL_GATT_PERM_READ_NONE BSAL_GATT_PERM_NONE 78 | #define BSAL_GATT_PERM_READ BSAL_GATT_PERM_ALL 79 | #define BSAL_GATT_PERM_READ_AUTHEN_REQ BSAL_GATT_PERM_AUTHEN_REQ 80 | #define BSAL_GATT_PERM_READ_AUTHEN_MITM_REQ BSAL_GATT_PERM_AUTHEN_MITM_REQ 81 | #define BSAL_GATT_PERM_READ_AUTHOR_REQ BSAL_GATT_PERM_AUTHOR_REQ 82 | #define BSAL_GATT_PERM_READ_ENCRYPTED_REQ BSAL_GATT_PERM_ENCRYPTED_REQ 83 | #define BSAL_GATT_PERM_READ_AUTHEN_SC_REQ BSAL_GATT_PERM_AUTHEN_SC_REQ 84 | 85 | #define BSAL_GATT_PERM_GET_READ(x) (x & 0x0f) 86 | 87 | #define BSAL_GATT_PERM_WRITE_NONE (BSAL_GATT_PERM_NONE << 4) 88 | #define BSAL_GATT_PERM_WRITE (BSAL_GATT_PERM_ALL << 4) 89 | #define BSAL_GATT_PERM_WRITE_AUTHEN_REQ (BSAL_GATT_PERM_AUTHEN_REQ << 4) 90 | #define BSAL_GATT_PERM_WRITE_AUTHEN_MITM_REQ (BSAL_GATT_PERM_AUTHEN_MITM_REQ << 4) 91 | #define BSAL_GATT_PERM_WRITE_AUTHOR_REQ (BSAL_GATT_PERM_AUTHOR_REQ << 4) 92 | #define BSAL_GATT_PERM_WRITE_ENCRYPTED_REQ (BSAL_GATT_PERM_ENCRYPTED_REQ << 4) 93 | #define BSAL_GATT_PERM_WRITE_AUTHEN_SC_REQ (BSAL_GATT_PERM_AUTHEN_SC_REQ<<4) 94 | 95 | #define BSAL_GATT_PERM_GET_WRITE(x) ((x>>4) & 0x0f) 96 | 97 | #define BSAL_GATT_PERM_NOTIFY_IND_NONE (BSAL_GATT_PERM_NONE << 8) 98 | #define BSAL_GATT_PERM_NOTIFY_IND (BSAL_GATT_PERM_ALL << 8) 99 | #define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_REQ (BSAL_GATT_PERM_AUTHEN_REQ << 8) 100 | #define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_MITM_REQ (BSAL_GATT_PERM_AUTHEN_MITM_REQ << 8) 101 | #define BSAL_GATT_PERM_NOTIFY_IND_AUTHOR_REQ (BSAL_GATT_PERM_AUTHOR_REQ << 8) 102 | #define BSAL_GATT_PERM_NOTIFY_IND_ENCRYPTED_REQ (BSAL_GATT_PERM_ENCRYPTED_REQ << 8) 103 | #define BSAL_GATT_PERM_NOTIFY_IND_AUTHEN_SC_REQ (BSAL_GATT_PERM_AUTHEN_SC_REQ<<8) 104 | 105 | #define BSAL_GATT_PERM_GET_NOTIFY_IND(x) ((x>>8)& 0xf) 106 | 107 | 108 | #define BSAL_GATT_GET_ENC_TYPE(x) (x & BSAL_GATT_PERM_ALL) 109 | #define BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(x) (x & BSAL_GATT_PERM_AUTHEN_REQ) 110 | #define BSAL_GATT_GET_ENC_TYPE_AUTHEN_MITM_REQ(x) (x & BSAL_GATT_PERM_AUTHEN_MITM_REQ) 111 | #define BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(x) (x & BSAL_GATT_PERM_AUTHOR_REQ) 112 | #define BSAL_GATT_GET_ENC_TYPE_ENCRYPTED_REQ(x) (x & BSAL_GATT_PERM_READ_ENCRYPTED_REQ) 113 | #define BSAL_GATT_GET_ENC_AUTHEN_SC_REQ(x) (x & BSAL_GATT_PERM_READ_AUTHEN_SC_REQ) 114 | 115 | 116 | 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | #endif 122 | 123 | -------------------------------------------------------------------------------- /inc/bsal_app_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #ifndef __BSAL_APP_API_H__ 12 | #define __BSAL_APP_API_H__ 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #include 18 | #include 19 | #include "bsal_common.h" 20 | 21 | //0. CALLED BY STACK 22 | /** 23 | * BSAL connect status callback 24 | * 25 | * @param stack_ptr the point of the stack object 26 | * @param conn_handle the connect handle of link 27 | * @param conn_status the connection status 28 | * @Note callback the connect status called by stack 29 | */ 30 | int bsal_gap_connect_status(void *stack_ptr, uint16_t conn_handle, uint8_t connect_status, uint16_t disconnect_status); 31 | 32 | //====================================ENTER MAIN============================== 33 | 34 | //=================================APP API CALLED BY APP======================= 35 | 36 | /** 37 | * BSAL find the stack ptr 38 | * 39 | * @param stack_ptr the point of the stack object 40 | * @param stack_name the name of the stack 41 | * @Note find the object ptr of the stack by the name 42 | * called by APP 43 | */ 44 | void *bsal_find_stack_ptr(char *stack_name); 45 | 46 | /** 47 | * BSAL init the stack 48 | * 49 | * @param stack_ptr the point of the stack object 50 | * @param callback the function to deal with the event 51 | * @Note find the object ptr of the stack by the name 52 | * called by APP 53 | */ 54 | int bsal_stack_init(void *stack_ptr, void *callback); 55 | 56 | 57 | /** 58 | * BSAL start register the profile table 59 | * 60 | * @param stack_ptr the point of the stack object 61 | * @param num the all number of the profile table 62 | * @param p_fun_cb the function of the profile to callback 63 | * @Note start to register the profile with the num 64 | */ 65 | 66 | void bsal_stack_le_srv_begin(void *stack_ptr, uint8_t num, void *p_fun_cb); 67 | 68 | /** 69 | * BSAL end register the profile table 70 | * 71 | * @param stack_ptr the point of the stack object 72 | * @Note the end to register the profile with the num 73 | */ 74 | void bsal_stack_le_srv_end(void *stack_ptr); 75 | 76 | /** 77 | * BSAL start the stack 78 | * 79 | * @param stack_ptr the point of the stack object 80 | * @Note to start the stack 81 | */ 82 | void bsal_stack_startup(void *stack_ptr); 83 | 84 | //2. SERVICE CALLBACK API APP NEED KNOWN 85 | 86 | typedef enum 87 | { 88 | BSAL_CALLBACK_TYPE_READ_CHAR_VALUE = 1, /**< client read event */ 89 | BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE = 2, /**< client write event */ 90 | BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION = 3, /**< CCCD update event */ 91 | BSAL_CALLBACK_TYPE_HANDLE_TABLE = 4, /**< handle event */ 92 | } T_BSAL_SRV_CB_TYPE; 93 | 94 | struct bsal_callbak_data 95 | { 96 | void *stack_ptr; 97 | uint8_t conn_id; 98 | T_BSAL_SRV_CB_TYPE msg_type; 99 | uint16_t start_handle; 100 | uint32_t off_handle; 101 | uint16_t length; 102 | uint8_t *data; 103 | uint32_t value; /**< CCCD save the temp value */ 104 | bsal_uuid_any_t srv_uuid; 105 | }; 106 | typedef struct bsal_callbak_data bsal_callbak_data_t; 107 | 108 | 109 | //3.ADV OPERATE 110 | struct le_adv_ltv 111 | { 112 | uint8_t length; 113 | uint8_t type; 114 | uint8_t *value; 115 | }; 116 | typedef struct le_adv_ltv le_adv_ltv_t; 117 | /** 118 | * BSAL ADD FLAG LTV TO adv_data. 119 | * 120 | * @param adv_data the array of adv_data 121 | * @param flag the flag value of adv_type 122 | * @Note the function is used for add flag 123 | */ 124 | 125 | void bsal_le_adv_data_add_flag(uint8_t *adv_data , uint8_t flag); 126 | /** 127 | * BSAL ADD name 128 | * 129 | * @param adv_data the array of adv_data 130 | * @param name_length the length of name 131 | * @note the function is used for add fla g 132 | */ 133 | void bsal_adv_data_add_name(uint8_t *adv_data, uint8_t name_length, char *name); 134 | 135 | /** 136 | * BSAL ADD ONE UUID 137 | * 138 | * @param adv_data the array of adv_data 139 | * @param uuid the uuid valule of service 140 | * @note the function is used for add UUID 141 | */ 142 | void bsal_adv_data_add_uuid16(uint8_t *adv_data, uint16_t uuid); 143 | /** 144 | * BSAL add LTV TO adv_data. 145 | * 146 | * @param adv_data the array of adv_data 147 | * @param ltv the struct of lengthTypeValue 148 | * @param timeout the maximum response time 149 | * @Note the function is used in combine the adv_data of ltv 150 | */ 151 | void bsal_le_adv_data_add_ltv(uint8_t *adv_data, le_adv_ltv_t *ltv); 152 | /** 153 | * BSAL Set the adv data to stack. 154 | * 155 | * @param stack_ptr the object of the stack 156 | * @param adv_data the array of adv_data 157 | * @Note the function is used for add the data to stack 158 | */ 159 | void bsal_set_le_adv_data_user(void *stack_ptr, uint8_t *adv_data); 160 | /** 161 | * BSAL Set the scan rsp data to stack. 162 | * 163 | * @param stack_ptr the object of the stack 164 | * @param scan_rsp_data the array of scan_rsp_data 165 | * @Note the function is used for add the scan response data to stack 166 | */ 167 | void bsal_set_le_scan_rsp_data_user(void *stack_ptr, uint8_t *scan_rsp_data); 168 | 169 | /** @defgroup BSAL_SET_LE_PARAM_TYPE 170 | * @{ 171 | */ 172 | #define BSAL_SET_LE_ADV_PARAM BIT(0) 173 | #define BSAL_SET_LE_SCAN_RSP_DATA BIT(1) 174 | #define BSAL_SET_LE_ADV_DATA BIT(2) 175 | /** 176 | * @} 177 | */ 178 | struct bsal_adv_param 179 | { 180 | uint8_t set_param_flag; //!< set the param bit see #BSAL_SET_LE_PARAM_TYPE 181 | uint16_t adv_int_min; //!< set adv interval min 182 | uint16_t adv_int_max; //!< set adv interval max 183 | uint8_t adv_type; //!< set adv type 184 | uint8_t own_address_type; //!< own address type 185 | uint8_t direct_address_type; //!< set direct bt mac address type 186 | uint8_t direct_address[6]; //!< set the direct mac address 187 | uint8_t channel_map; //!< set the channel map see @ref BTCHANNEL_MAP 188 | uint8_t filter_policy; //!< the filter policy see @ref ADV_PARAM_FILTER_POLICY 189 | 190 | uint8_t scan_rsp_data[BSAL_MAX_ADV_SCAN_DATA_LENGTH]; //the scan rsp data 191 | 192 | uint8_t adv_data[BSAL_MAX_ADV_SCAN_DATA_LENGTH]; //the adv data 193 | }; 194 | typedef struct bsal_adv_param bsal_adv_param_t; 195 | /** 196 | * BSAL set le advertising param. 197 | * 198 | * @param stack_ptr the object of the stack 199 | * @param adv_param the point of the adv_param 200 | * @Note the function is used for set the adv param 201 | */ 202 | void bsal_set_le_adv_parm(void *stack_ptr, bsal_adv_param_t *adv_param); 203 | /** 204 | * BSAL start adv 205 | * 206 | * @param stack_ptr the object of the stack 207 | * @Note the function is used for start tx the adv 208 | */ 209 | int bsal_stack_start_adv(void *stack_ptr); 210 | /** 211 | * BSAL stop adv 212 | * 213 | * @param stack_ptr the object of the stack 214 | * @Note the function is used for stop tx the adv 215 | */ 216 | int bsal_stack_stop_adv(void *stack_ptr); 217 | //BOND 218 | //self define 219 | typedef enum 220 | { 221 | BSAL_NO_INPUT, 222 | BSAL_INPUT_YES_NO, 223 | BSAL_INPUT_KEYBOARD, 224 | } T_BSAL_GAP_INPUT_CAP; 225 | 226 | typedef enum 227 | { 228 | BSAL_NO_OUTPUT, 229 | BSAL_YES_OUTPUT, 230 | } T_BSAL_GAP_OUTPUT_CAP; 231 | //bond 232 | struct bsal_bond_param 233 | { 234 | uint8_t LE_BR_EDR_FLAG; // LE is 1 BR/EDR is 0 235 | bool bonding_flag; //is bond 236 | uint8_t oob_flag; //not support; 237 | uint8_t auth_type; //AuthReq flag of device 238 | uint8_t io_capability; //io_capability 239 | 240 | //useless 241 | uint8_t force_auth_type; 242 | bool fixed_key_flag; 243 | uint32_t fixed_key; 244 | bool sm_req_enable; 245 | }; 246 | typedef struct bsal_bond_param bsal_bond_param_t; 247 | 248 | /** 249 | * BSAL set the bond type 250 | * 251 | * @param stack_ptr the object of the stack see 252 | * @param is_bond the bool about is needed bond 253 | * @param input the ability of input see #T_BSAL_GAP_INPUT_CAP 254 | * @param output the ability of output see #T_BSAL_GAP_OUTPUT_CAP 255 | * @param bond_type the bond type of the #BSAL_GAP_AUTH_TYPE 256 | * @Note the function is used for stop tx the adv 257 | */ 258 | 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); 259 | 260 | 261 | /** 262 | * BSAL set the bond param 263 | * 264 | * @param stack_ptr the object of the stack see 265 | * @param bond_param the param of the bond 266 | * @Note the function is used for le bond param directly 267 | */ 268 | uint16_t bsal_set_device_le_bond_param(void *stack_ptr, bsal_bond_param_t *bond_param); 269 | struct bsal_gaps_param 270 | { 271 | uint8_t name[BSAL_MAX_NAME_LENGTH]; //!< The GAP's SHOW NAME MAX LENGTH IS 40 272 | uint16_t apperance; //!< The GAP's apperance 273 | }; 274 | typedef struct bsal_gaps_param bsal_gaps_param_t; 275 | /** 276 | * BSAL set gap param set the param of gap 277 | * 278 | * @param stack_ptr the object of the stack 279 | * @param gaps_param the struct of the gaps_param see #bsal_gaps_param_t 280 | * @Note the function is set the gap param 281 | */ 282 | void bsal_set_gap_param(void *stack_ptr, bsal_gaps_param_t *gaps_param); 283 | /** 284 | * BSAL set set the device name 285 | * 286 | * @param stack_ptr the object of the stack 287 | * @param length the length of the name 288 | * @param name the buffer of the name 289 | * @Note the function is set the device name 290 | */ 291 | int bsal_set_device_name(void *stack_ptr, uint8_t length, uint8_t *name); 292 | /** 293 | * BSAL set get the device name 294 | * 295 | * @param stack_ptr the object of the stack 296 | * @Note the function is get the device name 297 | */ 298 | uint8_t *bsal_get_device_name(void *stack_ptr); 299 | 300 | //========================================PROFILE API==CALLED BY SERVICE=========================== 301 | //2. SERVICE API 302 | typedef BSAL_STATUS(*P_SRV_GENERAL_CB)(void *p_para); 303 | 304 | /** 305 | * BSAL register the profile table 306 | * 307 | * @param stack_ptr the object of the stack 308 | * @param srv_def the table of the service 309 | * @param callback the callback function of the profile 310 | * @Note the function is used for register the servcie table 311 | * called by the profile 312 | */ 313 | int bsal_stack_le_srv_reg_func(void *stack_ptr, void *srv_def, P_SRV_GENERAL_CB *callback); 314 | 315 | //3. SERVICE SEND DATA 316 | 317 | /** 318 | * BSAL send the notify data 319 | * 320 | * @param stack_ptr the object of the stack 321 | * @param conn_id the connect id of the link(like conn_handle) 322 | * @param service_id the identify of the profile 323 | * @param offset_handle the offset handle of the att in the profile 324 | * @param value_length the data length of the data 325 | * @param value the buff of the data 326 | * @Note called by the profile to send the notify 327 | */ 328 | 329 | 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); 330 | 331 | /** 332 | * BSAL send the indicate data 333 | * 334 | * @param stack_ptr the object of the stack 335 | * @param conn_id the connect id of the link(like conn_handle) 336 | * @param service_id the identify of the profile 337 | * @param offset_handle the offset handle of the att in the profile 338 | * @param value_length the data length of the data 339 | * @param value the buff of the data 340 | * @Note called by the profile to send the indicate 341 | */ 342 | 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); 343 | 344 | /** 345 | * BSAL get the start handle 346 | * 347 | * @param stack_ptr the object of the stack 348 | * @param uuid the profile main service uuid 349 | * @Note called by the profile to get the start handle 350 | */ 351 | uint16_t bsal_srv_get_start_handle(void *stack_ptr, bsal_uuid_any_t uuid); 352 | /** 353 | * BSAL get the start handle by value handle 354 | * 355 | * @param stack_ptr the object of the stack 356 | * @param handle the u_handle of the device 357 | * @Note called by the profile to get the start handle 358 | */ 359 | uint16_t bsal_profile_get_start_handle(void *stack_ptr, uint16_t value_handle); 360 | 361 | 362 | 363 | 364 | /** 365 | * BSAL WRITE ATT 366 | * 367 | * @param p_db the database of data 368 | * @param u_handle the unique handle of mcu 369 | * @note the function is used for read attribute 370 | */ 371 | int bsal_srv_write_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length, uint8_t *value); 372 | 373 | /** 374 | * BSAL READ ATT 375 | * 376 | * @param p_db the database of data 377 | * @param u_handle the unique handle of mcu 378 | * @note the function is used for read attribute 379 | */ 380 | int bsal_srv_read_data(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t *value_length, uint8_t **value); 381 | 382 | /** 383 | * BSAL CREATE ATT 384 | * 385 | * @param p_db the database of data 386 | * @param u_handle the unique handle of mcu 387 | * @note the function is used for read attribute 388 | */ 389 | int bsal_srv_create_att(void *stack_ptr, uint16_t start_handle, uint16_t offset_handle, uint16_t value_length); 390 | /** 391 | * BSAL WRITE ATT 392 | * 393 | * @param p_db the database of data 394 | * @param u_handle the unique handle of mcu 395 | * @note the function is used for read attribute 396 | */ 397 | int bsal_srv_write_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length, uint8_t *value); 398 | 399 | /** 400 | * BSAL READ ATT 401 | * 402 | * @param p_db the database of data 403 | * @param u_handle the unique handle of mcu 404 | * @note the function is used for read attribute 405 | */ 406 | int bsal_srv_read_data_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t *value_length, uint8_t **value); 407 | 408 | /** 409 | * BSAL CREATE ATT 410 | * 411 | * @param p_db the database of data 412 | * @param u_handle the unique handle of mcu 413 | * @note the function is used for read attribute 414 | */ 415 | int bsal_srv_create_att_by_handle(void *stack_ptr, uint16_t u_handle, uint16_t value_length); 416 | 417 | //=========================================STACK API ==CALLED BY STACK=========== 418 | /** 419 | * BSAL READ ATT EVENT 420 | * 421 | * @param stack_ptr point of the stack 422 | * @param conn_handle conn id of the link 423 | * @param start_handle the start handle of the profile 424 | * @param offset_handle the att value of the handle 425 | * @param length the length of the value 426 | * @param[out] the buffer address of the value 427 | * @note read the callback event, called by the stack 428 | */ 429 | 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); 430 | /** 431 | * @brief BSAL write ATT EVENT 432 | * 433 | * @param stack_ptr point of the stack 434 | * @param conn_handle conn id of the link 435 | * @param start_handle the start handle of the profile 436 | * @param offset_handle the att value of the handle 437 | * @param length the length of the value 438 | * @param value the data buffer address 439 | * @note write the callback event, called by the stack 440 | */ 441 | 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); 442 | /** 443 | * @brief BSAL CCCD ATT EVENT 444 | * 445 | * @param stack_ptr point of the stack 446 | * @param conn_handle conn id of the link 447 | * @param start_handle the start handle of the profile 448 | * @param offset_handle the att offset handle 449 | * @param length the length of the value 450 | * @param value the cccd_bit of the device 451 | * @note cccd the callback event, called by the stack 452 | */ 453 | void bsal_gatt_cccd_callback_event(void *stack_ptr, uint16_t conn_handle, uint16_t start_handle, uint16_t offset_handle, uint16_t value); 454 | /** 455 | * BSAL READ ATT EVENT 456 | * 457 | * @param stack_ptr point of the stack 458 | * @param conn_handle conn id of the link 459 | * @param u_handle the unique handle of the device 460 | * @param length the length of the value 461 | * @param[out] the buffer address of the value 462 | * @note read the callback event, called by the stack 463 | */ 464 | 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); 465 | /** 466 | * @brief BSAL write ATT EVENT 467 | * 468 | * @param stack_ptr point of the stack 469 | * @param conn_handle conn id of the link 470 | * @param u_handle the unique handle of the device 471 | * @param length the length of the value 472 | * @param value the data buffer address 473 | * @note write the callback event, called by the stack 474 | */ 475 | 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); 476 | /** 477 | * @brief BSAL CCCD ATT EVENT 478 | * 479 | * @param stack_ptr point of the stack 480 | * @param conn_handle conn id of the link 481 | * @param u_handle the unique handle of the device 482 | * @param value the CCCD value of the device 483 | * @note cccd the callback event, called by the stack 484 | */ 485 | void bsal_gatt_cccd_callback_event_by_handle(void *stack_ptr, uint16_t conn_handle, uint16_t u_handle , uint16_t value); 486 | 487 | #ifdef __cplusplus 488 | } 489 | #endif 490 | 491 | #endif 492 | 493 | -------------------------------------------------------------------------------- /inc/bsal_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #ifndef __BSAL_COMMON_H__ 12 | #define __BSAL_COMMON_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | #include 18 | 19 | #define BIT(x) (1< 20 | #include 21 | #include "bsal.h" 22 | 23 | struct bsal_uuid 24 | { 25 | uint8_t type; 26 | uint8_t data[16]; 27 | uint16_t propertiy; 28 | uint16_t permision; 29 | uint32_t *handle; 30 | }; 31 | typedef struct bsal_uuid bsal_uuid_t; 32 | 33 | struct bsal_gatt_value_entry 34 | { 35 | uint32_t u_handle; 36 | uint8_t *value; 37 | uint16_t value_length; 38 | uint32_t alloc_size; 39 | bool append;///for future 40 | struct bsal_gatt_value_entry *next_entry; 41 | }; 42 | typedef struct bsal_gatt_value_entry bsal_gatt_value_entry_t; 43 | 44 | struct bsal_stack_ops 45 | { 46 | BSAL_STATUS(*le_set_stack_param)(uint32_t value_length, uint8_t *value); //set param param_type firstbit 1:br/edr param 0: ble 47 | BSAL_STATUS(*le_get_stack_param)(uint32_t value_length, uint8_t *value); //get param param_type firstbit 1:br/edr param 0: ble 48 | void (*get_mac_address)(uint8_t addr_type, uint8_t *bd_addr); //get mac addr 49 | void (*init)(uint8_t stack_type); //stack init //set the default param stack_type: bit 0 :BR/EDR. bit 1: BLE, bit2:mesh 50 | void (*startup)(void); //stack init 51 | //GAP OPERATE 52 | //bond 53 | void (*set_bond_param)(bsal_bond_param_t *value); //set adv param 54 | void (*get_bond_param)(bsal_bond_param_t *value); 55 | //ADV PARAM 56 | void (*le_set_adv_param)(bsal_adv_param_t *adv_param); //set adv param 57 | void (*le_get_adv_param)(bsal_adv_param_t *adv_param); 58 | BSAL_STATUS(*le_adv_enable)(bool enable); // set adv param 59 | void (*set_gaps_param)(bsal_gaps_param_t *gaps_param); //set device name 60 | 61 | //service profile 62 | uint32_t (*cov_handle_to_u_handle)(uint16_t service_id, uint16_t offset_handle); // bsal_hanlde_to_stack_handle 63 | BSAL_STATUS(*le_srv_reg_begin)(bool is_continue, uint8_t service_num, void *p_func); 64 | BSAL_STATUS(*le_srv_reg_fun)(struct bsal_gatt_app_srv_def *p_srv, void *p_func); //tobe define 65 | BSAL_STATUS(*le_srv_reg_end)(void); 66 | 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); 67 | BSAL_STATUS(*send_notify_complete)(uint32_t credits); /*TODO*/ 68 | //client profile 69 | // TO BE CALLED BY BSAL_RTK.C 70 | }; 71 | typedef struct bsal_stack_ops bsal_stack_ops_t; 72 | 73 | //load the static info 74 | struct bsal_stack_info 75 | { 76 | uint8_t public_bd_addr[6]; 77 | uint8_t device_name[BSAL_MAX_NAME_LENGTH]; 78 | uint16_t le_mtu_size; 79 | uint16_t le_srv_tx_credits; 80 | bsal_adv_param_t adv_param; 81 | bsal_bond_param_t bond_param; 82 | }; 83 | typedef struct bsal_stack_info bsal_stack_info_t; 84 | 85 | typedef BSAL_STATUS(*P_BSAL_PROFILE_CB)(void *p_para); 86 | struct bsal_srv_callback 87 | { 88 | P_BSAL_PROFILE_CB bsal_srv_fn_cb; 89 | uint16_t start_handle; 90 | bsal_uuid_any_t srv_uuid; 91 | }; 92 | typedef struct bsal_srv_callback bsal_srv_callback_t; 93 | 94 | struct bsal_stack_obj 95 | { 96 | bool stack_ready_flag; 97 | bsal_stack_ops_t bsal_ops; 98 | //att 99 | bsal_gatt_value_entry_t *db; 100 | //service 101 | bsal_srv_callback_t *bsal_srv_objs; 102 | //static info: 103 | bsal_stack_info_t bsal_info; 104 | 105 | uint16_t g_att_index; 106 | uint8_t srv_num; 107 | //register 108 | void (*app_all_callbak)(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value); 109 | }; 110 | typedef struct bsal_stack_obj bsal_stack_obj_t; 111 | 112 | /** 113 | * BSAL create the att first init 114 | * 115 | * @param stack_ptr the point of the stack object 116 | * @param u_handle the unique handle of the att 117 | * @param value_length the length of the value 118 | * @param value the buffer of the value 119 | * @Note create the attribute with the unique handle 120 | */ 121 | 122 | int bsal_att_create_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length); 123 | 124 | /** 125 | * BSAL read the attribute with u_handle 126 | * 127 | * @param stack_ptr the point of the stack object 128 | * @param u_handle the unique handle of the att 129 | * @param value_length the length of the value 130 | * @param save the value the buffer of the value 131 | * @Note create the attribute with the unique handle 132 | */ 133 | int bsal_att_read_entry(void *stack_ptr, uint32_t u_handle, uint16_t *value_length, uint8_t **value); 134 | 135 | /** 136 | * BSAL write the attribute with u_handle 137 | * 138 | * @param stack_ptr the point of the stack object 139 | * @param u_handle the unique handle of the att 140 | * @param value_length the length of the value 141 | * @param value the buffer of the value 142 | * @Note create the attribute with the unique handle 143 | */ 144 | int bsal_att_write_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, uint8_t *value); 145 | 146 | /** 147 | * BSAL change the attribute size with u_handle 148 | * 149 | * @param stack_ptr the point of the stack object 150 | * @param u_handle the unique handle of the att 151 | * @param value_length the length of the value 152 | * @param append the flag of append the value 153 | * @Note change the size of value the attribute with the unique handle 154 | */ 155 | int bsal_att_resize_entry(void *stack_ptr, uint32_t u_handle, uint16_t value_length, bool append); 156 | 157 | //send data 158 | typedef enum 159 | { 160 | BSAL_SEND_DATA_TYPE_ANY = 0x00, /**< Any PDU type. */ 161 | BSAL_SEND_DATA_TYPE_NOTIFICATION = 0x01, /**< Notification PDU type. */ 162 | BSAL_SEND_DATA_TYPE_INDICATION = 0x02 /**< Indication PDU type. */ 163 | } T_BSAL_SEND_DATA_TYPE; 164 | 165 | /** 166 | * BSAL find the start handle by the uuid 167 | * 168 | * @param stack_ptr the point of the stack object 169 | * @param uuid the 16 bit of the uuid 170 | * @Note get the profile start handle by the uuid 171 | */ 172 | uint16_t bsal_profile_get_start_handle_by_16_uuid(void *stack_ptr, uint16_t uuid); 173 | 174 | /** 175 | * BSAL find the start handle by the uuid 176 | * 177 | * @param stack_ptr the point of the stack object 178 | * @param uuid the 32 bit of the uuid 179 | * @Note get the profile start handle by the uuid 180 | */ 181 | uint16_t bsal_profile_get_start_handle_by_32_uuid(void *stack_ptr, uint32_t uuid); 182 | 183 | /** 184 | * BSAL find the start handle by the uuid 185 | * 186 | * @param stack_ptr the point of the stack object 187 | * @param uuid the point of the 128 bit of the uuid 188 | * @Note get the profile start handle by the uuid 189 | */ 190 | uint16_t bsal_profile_get_start_handle_by_128_uuid(void *stack_ptr, uint8_t *uuid); 191 | 192 | /** 193 | * BSAL get the profile entry by the start handle 194 | * 195 | * @param stack_ptr the point of the stack object 196 | * @param the start handle 197 | * @Note get the profile entry by the start_handle 198 | */ 199 | bsal_srv_callback_t *bsal_profile_get(void *stack_ptr, uint16_t start_handle); 200 | 201 | #ifdef __cplusplus 202 | } 203 | #endif 204 | 205 | #endif 206 | 207 | 208 | -------------------------------------------------------------------------------- /inc/bsal_osif.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #ifndef __BSAL_OSIF_H__ 13 | #define __BSAL_OSIF_H__ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | 19 | #include 20 | #include 21 | #include 22 | /** 23 | * BSAL OSIF malloc the buffer 24 | * 25 | * @param len the buffer size of the buffer 26 | * @Note malloc the buffer 27 | */ 28 | void *bsal_osif_malloc(uint32_t len); 29 | 30 | /** 31 | * BSAL OSIF free the buffer 32 | * 33 | * @param p the point of the buffer 34 | * @Note free the buffer 35 | */ 36 | void bsal_osif_free(void *p); 37 | 38 | /** 39 | * BSAL OSIF delay 40 | * 41 | * @param ms the ms of delay time 42 | * @Note delay the time 43 | */ 44 | void bsal_osif_delay(uint32_t ms); 45 | 46 | 47 | 48 | #if 0 49 | int bsal_osif_printf_dbg(const char *fmt, ...); 50 | int bsal_osif_printf_err(const char *fmt, ...); 51 | int bsal_osif_printf_info(const char *fmt, ...); 52 | int bsal_osif_printf_warn(const char *fmt, ...); 53 | #else 54 | #define bsal_osif_printf_dbg rt_kprintf 55 | #define bsal_osif_printf_err rt_kprintf 56 | #define bsal_osif_printf_info rt_kprintf 57 | #define bsal_osif_printf_warn rt_kprintf 58 | 59 | #endif 60 | 61 | #ifdef BSAL_ASSERT_DEBUG 62 | 63 | #define BSAL_ASSERT_PTR(x) if(x==NULL) \ 64 | {bsal_osif_printf_err("%s line:%d: the point is NULL:%p",__FUNCTION__, __LINE__,x); while(1);} 65 | #else 66 | #define BSAL_ASSERT_PTR(x) 67 | #endif 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | #endif 72 | -------------------------------------------------------------------------------- /inc/bsal_stack_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #ifndef __BSAL_STACK_API_H__ 13 | #define __BSAL_STACK_API_H__ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include "bsal_common.h" 19 | 20 | #include 21 | #include 22 | 23 | 24 | /** 25 | * BSAL compute the sum of the srv handle number. 26 | * 27 | * @param[in] p_srv the service table of the p_srv 28 | * @param[out] att_res the result of the att resource 29 | * @Note compute the number of the service 30 | */ 31 | uint8_t bsal_util_sum_handle_num(struct bsal_gatt_app_srv_def *p_srv, bsal_gatt_res_t *att_res); 32 | 33 | /** 34 | * BSAL save the profile 35 | * 36 | * @param[in] stack_ptr the point of the stack ptr 37 | * @param[in] handle the start_handle of the device 38 | * @param[in] callback the callback function of the service 39 | * @param[in] uuid the uuid of the service 40 | * @Note 41 | */ 42 | BSAL_STATUS bsal_profile_insert(void *stack_ptr, uint16_t handle, void *callback, bsal_uuid_any_t uuid); 43 | 44 | /** 45 | * BSAL Stack ready callback 46 | * 47 | * @param[in] stack_ptr the point of the stack ptr 48 | * @param[in] status true is the stack ready, false is stack fail 49 | * @Note 50 | */ 51 | int bsal_stack_ready(void *stack_ptr, bool status); 52 | 53 | /** 54 | * BSAL Stack ready callback 55 | * 56 | * @param[in] stack_ptr the point of the stack ptr 57 | * @param[in] conn_handle the conn_handle of the link 58 | * @param[in] conn_status the connect status of the link 59 | * @param[in] disconnect_status the disconnect reason of the link 60 | * @Note callback the link status of the devcie 61 | */ 62 | int bsal_gap_connect_status(void *stack_ptr, uint16_t conn_handle, uint8_t connect_status, uint16_t disconnect_status); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif 69 | 70 | 71 | -------------------------------------------------------------------------------- /port/NIMBLE/bsal_nimble.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #include 13 | #include 14 | 15 | #include "bsal.h" 16 | #include "bsal_osif.h" 17 | #include "bsal_int.h" 18 | #include "bsal_stack_api.h" 19 | #ifdef PKG_BSAL_NIMBLE_STACK 20 | #include "bsal_nimble.h" 21 | bsal_stack_obj_t nimble_obj; 22 | #endif 23 | 24 | static void *bsal_get_local_stack_obj() 25 | { 26 | return &nimble_obj; 27 | } 28 | #ifdef PKG_BSAL_NIMBLE_STACK 29 | static int 30 | bsal_nimble_gap_event(struct ble_gap_event *event, void *arg) 31 | { 32 | struct ble_gap_conn_desc desc; 33 | int rc; 34 | uint16_t cccbits = 0; 35 | switch (event->type) 36 | { 37 | case BLE_GAP_EVENT_CONNECT: 38 | if (event->connect.status == 0) 39 | { 40 | rc = ble_gap_conn_find(event->connect.conn_handle, &desc); 41 | //save the connect_handle; 42 | //BSAL CALLBACK 43 | bsal_gap_connect_status(arg, event->connect.conn_handle, BSAL_GAP_CONN_STATE_CONNECTED, 0); 44 | } 45 | break; 46 | case BLE_GAP_EVENT_DISCONNECT: 47 | //BSAL CALLBACK 48 | bsal_gap_connect_status(arg, event->connect.conn_handle, BSAL_GAP_CONN_STATE_DISCONNECTED, 0); 49 | break; 50 | case BLE_GAP_EVENT_SUBSCRIBE: 51 | /* TODO NOTIFY ENABLE DISABLE*/ 52 | MODLOG_DFLT(INFO, "subscribe event; conn_handle=%d attr_handle=%d " 53 | "reason=%d prevn=%d curn=%d previ=%d curi=%d\n", 54 | event->subscribe.conn_handle, 55 | event->subscribe.attr_handle, 56 | event->subscribe.reason, 57 | event->subscribe.prev_notify, 58 | event->subscribe.cur_notify, 59 | event->subscribe.prev_indicate, 60 | event->subscribe.cur_indicate); 61 | 62 | if (event->subscribe.cur_notify == 1) 63 | { 64 | cccbits |= BSAL_GATT_CCC_NOTIFY; 65 | } 66 | 67 | if (event->subscribe.cur_indicate == 1) 68 | { 69 | cccbits |= BSAL_GATT_CCC_INDICATE; 70 | } 71 | //BSAL CALLBACK 72 | bsal_gatt_cccd_callback_event_by_handle(bsal_get_local_stack_obj(), event->subscribe.conn_handle, event->subscribe.attr_handle + 1, cccbits); 73 | break; 74 | default: 75 | break; 76 | } 77 | return 0; 78 | } 79 | //===============================================STACK ABOUT CODE================================= 80 | 81 | 82 | static void 83 | basl_nimble_on_reset(int reason) 84 | { 85 | MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); 86 | //BSAL CALLBACK 87 | bsal_stack_ready(bsal_get_local_stack_obj(), false); 88 | while (1); 89 | } 90 | 91 | static void 92 | bsal_nimble_on_sync(void) 93 | { 94 | int rc; 95 | //BSAL CALLBACK 96 | bsal_stack_ready(bsal_get_local_stack_obj(), true); 97 | } 98 | 99 | static void 100 | bsal_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) 101 | { 102 | char buf[BLE_UUID_STR_LEN]; 103 | 104 | switch (ctxt->op) 105 | { 106 | case BLE_GATT_REGISTER_OP_SVC: 107 | MODLOG_DFLT(INFO, "registered service %s with handle=%d\n", 108 | ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), 109 | ctxt->svc.handle); 110 | break; 111 | case BLE_GATT_REGISTER_OP_CHR: 112 | MODLOG_DFLT(INFO, "registering characteristic %s with " 113 | "def_handle=%d val_handle=%d\n", 114 | ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), 115 | ctxt->chr.def_handle, 116 | ctxt->chr.val_handle); 117 | //load the last srv handle 118 | bsal_srv_create_att_by_handle(bsal_get_local_stack_obj(), ctxt->chr.val_handle, ctxt->chr.chr_def->min_key_size); 119 | break; 120 | case BLE_GATT_REGISTER_OP_DSC: 121 | 122 | /* TODO no need templete*/ 123 | MODLOG_DFLT(INFO, "registering descriptor %s with handle=%d\n", 124 | ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), 125 | ctxt->dsc.handle); 126 | break; 127 | default: 128 | assert(0); 129 | break; 130 | } 131 | } 132 | 133 | 134 | 135 | int 136 | bsal_ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle, 137 | struct ble_gatt_access_ctxt *ctxt, 138 | void *arg) 139 | { 140 | int rc; 141 | 142 | uint16_t p_length; 143 | uint8_t *pp_value; 144 | 145 | // * o BLE_GATT_ACCESS_OP_READ_CHR 146 | // * o BLE_GATT_ACCESS_OP_WRITE_CHR 147 | // * o BLE_GATT_ACCESS_OP_READ_DSC 148 | // * o BLE_GATT_ACCESS_OP_WRITE_DSC 149 | 150 | switch (ctxt->op) 151 | { 152 | case BLE_GATT_ACCESS_OP_READ_CHR: 153 | case BLE_GATT_ACCESS_OP_READ_DSC: 154 | bsal_gatt_read_callback_event_by_handle(bsal_get_local_stack_obj(), conn_handle, *ctxt->chr->val_handle, &p_length, &pp_value); 155 | rc = os_mbuf_append(ctxt->om, (const void *) pp_value, p_length); 156 | return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; 157 | break; 158 | case BLE_GATT_ACCESS_OP_WRITE_CHR: 159 | case BLE_GATT_ACCESS_OP_WRITE_DSC: 160 | 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); 161 | break; 162 | default: 163 | break; 164 | } 165 | } 166 | #endif 167 | //=================================================END============================================ 168 | 169 | //================================BSAL.C========================== 170 | static void bsal_stack_int_init(uint8_t stack_type) 171 | { 172 | #ifdef PKG_BSAL_NIMBLE_STACK 173 | ble_hs_cfg.reset_cb = basl_nimble_on_reset; //fail callback 174 | ble_hs_cfg.sync_cb = bsal_nimble_on_sync; 175 | ble_hs_cfg.gatts_register_cb = bsal_gatt_svr_register_cb; 176 | ble_hs_cfg.gatts_register_arg = bsal_get_local_stack_obj(); 177 | ble_hs_cfg.store_status_cb = ble_store_util_status_rr; 178 | #endif 179 | } 180 | 181 | static void bsal_stack_int_startup(void) 182 | { 183 | #ifdef PKG_BSAL_NIMBLE_STACK 184 | ble_hs_thread_startup(); 185 | #endif 186 | } 187 | 188 | 189 | static BSAL_STATUS bsal_stack_int_le_adv_enable(bool enable) 190 | { 191 | bsal_stack_obj_t *p_bsal_stack = bsal_get_local_stack_obj(); 192 | 193 | if (enable == true) 194 | { 195 | /* ENABLE ADV */ 196 | #ifdef PKG_BSAL_NIMBLE_STACK 197 | struct ble_gap_adv_params adv_param; 198 | memset(&adv_param, 0, sizeof(struct ble_gap_adv_params)); 199 | 200 | if (p_bsal_stack->bsal_info.adv_param.adv_type == BSAL_GAP_ADTYPE_ADV_IND) 201 | { 202 | adv_param.conn_mode = BLE_GAP_CONN_MODE_UND; 203 | adv_param.disc_mode = BLE_GAP_DISC_MODE_GEN; 204 | } 205 | 206 | adv_param.channel_map = p_bsal_stack->bsal_info.adv_param.channel_map; 207 | adv_param.filter_policy = p_bsal_stack->bsal_info.adv_param.filter_policy; 208 | adv_param.itvl_max = p_bsal_stack->bsal_info.adv_param.adv_int_max; 209 | adv_param.itvl_min = p_bsal_stack->bsal_info.adv_param.adv_int_min; 210 | ble_addr_t direct_address; 211 | direct_address.type = p_bsal_stack->bsal_info.adv_param.direct_address_type; 212 | memcpy(direct_address.val, p_bsal_stack->bsal_info.adv_param.direct_address, 6); 213 | ble_gap_adv_start(p_bsal_stack->bsal_info.adv_param.own_address_type, &direct_address , BLE_HS_FOREVER, 214 | &adv_param, bsal_nimble_gap_event, p_bsal_stack); 215 | #endif 216 | } 217 | else 218 | { 219 | /* DISABLE ADV */ 220 | #ifdef PKG_BSAL_NIMBLE_STACK 221 | ble_gap_adv_stop(); 222 | #endif 223 | } 224 | return BSAL_RESULT_SUCCESS; 225 | } 226 | 227 | //for app 228 | static BSAL_STATUS bsal_int_srv_profile_srv_begin(bool is_continue, uint8_t service_num, void *p_fnc_callback) 229 | { 230 | return BSAL_RESULT_SUCCESS; 231 | } 232 | 233 | //common utils 234 | static BSAL_STATUS bsal_int_srv_profile_reg_service( 235 | struct bsal_gatt_app_srv_def *p_srv, 236 | void *p_func //callback 237 | ) 238 | { 239 | #ifdef PKG_BSAL_NIMBLE_STACK 240 | uint16_t att_num = 0; 241 | uint8_t att_index = 0; 242 | uint16_t sum_of_descript = 0; 243 | uint8_t write_index = 0; 244 | uint8_t i = 0; 245 | uint8_t j = 0; 246 | uint8_t x = 0; 247 | uint8_t y = 0; 248 | bsal_gatt_res_t res; 249 | bsal_util_sum_handle_num(p_srv, &res); 250 | att_num = res.attrs; 251 | bsal_stack_obj_t *p_bsal_stack = bsal_get_local_stack_obj(); 252 | //malloc memory: 253 | struct ble_gatt_svc_def *nimble_srvs = bsal_osif_malloc(sizeof(struct ble_gatt_svc_def) * (res.svcs + 1)); 254 | struct bsal_gatt_app_srv_def *tmp_srv; 255 | bsal_gatt_chr_def_t *tmp_chr; 256 | uint8_t srv_idx = 0; 257 | uint8_t chr_idx = 0; 258 | uint8_t dsc_idx = 0; 259 | 260 | //combine the srv 261 | for (i = 0; p_srv[i].type != 0; i++) 262 | { 263 | tmp_srv = p_srv + i; 264 | 265 | //add service============================================ 266 | if ((tmp_srv->type != BSAL_GATT_UUID_PRIMARY_SERVICE) && 267 | (tmp_srv->type != BSAL_GATT_UUID_SECONDARY_SERVICE)) 268 | { 269 | return BSAL_RESULT_FAIL; 270 | } 271 | nimble_srvs[srv_idx].type = BLE_GATT_SVC_TYPE_PRIMARY; 272 | write_index++; 273 | if (tmp_srv->uuid->u_type == BSAL_UUID_TYPE_16BIT) 274 | { 275 | ble_uuid16_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid16_t)); 276 | tmp_uuid->u.type = BLE_UUID_TYPE_16; 277 | tmp_uuid->value = tmp_srv->uuid->u16.value; 278 | //nimble_srvs->uuid = &tmp_uuid->u; 279 | nimble_srvs[srv_idx].uuid = &tmp_uuid->u; 280 | } 281 | else if (tmp_srv->characteristics[x].uuid->u_type == BSAL_UUID_TYPE_128BIT) 282 | { 283 | ble_uuid128_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid128_t)); 284 | tmp_uuid->u.type = BLE_UUID_TYPE_128; 285 | memcpy(tmp_uuid->value, tmp_srv->uuid->u128.value,16); 286 | //nimble_srvs->uuid = &tmp_uuid->u; 287 | nimble_srvs[srv_idx].uuid = &tmp_uuid->u; 288 | } 289 | write_index++; 290 | //add include============================================================= 291 | if (tmp_srv->includes != NULL) 292 | { 293 | for (j = 0; tmp_srv->includes[j] != NULL; j++) 294 | { 295 | // att_res->attrs++; 296 | // att_res->incs++; 297 | //add include /*TODO*/ 298 | write_index++; 299 | } 300 | } 301 | //add char========================================================= 302 | if (tmp_srv->characteristics != NULL) 303 | { 304 | for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++) 305 | { 306 | //figure the chr_num 307 | } 308 | write_index++; 309 | //write_index++; 310 | struct ble_gatt_chr_def *nimble_chrs = bsal_osif_malloc(sizeof(struct ble_gatt_chr_def) * (x + 1)); 311 | nimble_srvs[srv_idx].characteristics = nimble_chrs; 312 | for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++) 313 | { 314 | tmp_chr = tmp_srv->characteristics + x; 315 | 316 | if (tmp_chr->uuid->u_type == BSAL_UUID_TYPE_16BIT) 317 | { 318 | ble_uuid16_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid16_t)); 319 | tmp_uuid->u.type = BLE_UUID_TYPE_16; 320 | tmp_uuid->value = tmp_srv->characteristics[x].uuid->u16.value; 321 | 322 | nimble_chrs[x].uuid = &tmp_uuid->u; 323 | } 324 | else if (tmp_srv->characteristics[x].uuid->u_type == BSAL_UUID_TYPE_128BIT) 325 | { 326 | ble_uuid128_t *tmp_uuid = bsal_osif_malloc(sizeof(ble_uuid128_t)); 327 | tmp_uuid->u.type = BLE_UUID_TYPE_128; 328 | memcpy(tmp_uuid->value, tmp_srv->characteristics[x].uuid->u128.value,16); 329 | nimble_chrs[x].uuid = &tmp_uuid->u; 330 | } 331 | nimble_chrs[x].access_cb = bsal_ble_svc_bas_access; 332 | nimble_chrs[x].arg = bsal_get_local_stack_obj(); 333 | nimble_chrs[x].flags = tmp_srv->characteristics[x].properties; 334 | nimble_chrs[x].min_key_size = tmp_srv->characteristics[x].value_length; 335 | nimble_chrs[x].val_handle = bsal_osif_malloc(tmp_srv->characteristics[x].value_length); 336 | //read 337 | 338 | if (BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission) != 0) ///ENCRYTYED 339 | { 340 | /* TODO*/ 341 | if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission))) 342 | { 343 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ_AUTHEN; 344 | } 345 | else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_READ(tmp_srv->characteristics[x].permission))) 346 | { 347 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ_AUTHOR; 348 | } 349 | else 350 | { 351 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_READ; 352 | } 353 | } 354 | //write 355 | if (BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission) != 0) ///ENCRYTYED 356 | { 357 | /* TODO*/ 358 | if (BSAL_GATT_GET_ENC_TYPE_AUTHEN_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission))) 359 | { 360 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE_AUTHEN; 361 | } 362 | else if (BSAL_GATT_GET_ENC_TYPE_AUTHOR_REQ(BSAL_GATT_PERM_GET_WRITE(tmp_srv->characteristics[x].permission))) 363 | { 364 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE_AUTHOR; 365 | } 366 | else 367 | { 368 | nimble_chrs[x].flags |= BLE_GATT_CHR_F_WRITE; 369 | } 370 | } 371 | //no need add NOTIFY STACK WILL ADD 372 | write_index++; 373 | } 374 | } 375 | srv_idx++; 376 | } 377 | 378 | for (i = 0; p_srv[i].type != 0; i++) 379 | { 380 | bsal_uuid_any_t srv_uuid; 381 | switch (p_srv[i].uuid->u_type) 382 | { 383 | case BSAL_UUID_TYPE_16BIT: 384 | srv_uuid.u_type = BSAL_UUID_TYPE_16BIT; //16bit 385 | srv_uuid.u16.value = p_srv[i].uuid->u16.value; 386 | break; 387 | case BSAL_UUID_TYPE_32BIT: 388 | srv_uuid.u_type = BSAL_UUID_TYPE_32BIT; //32bit 389 | srv_uuid.u32.value = p_srv[i].uuid->u32.value; 390 | break; 391 | case BSAL_UUID_TYPE_128BIT: 392 | srv_uuid.u_type = BSAL_UUID_TYPE_128BIT; //128bit 393 | memcpy(srv_uuid.u128.value, p_srv[i].uuid->u128.value, 16); 394 | break; 395 | } 396 | tmp_srv = p_srv + i; 397 | p_bsal_stack->g_att_index++; 398 | bsal_profile_insert(bsal_get_local_stack_obj(), p_bsal_stack->g_att_index, p_func, srv_uuid); 399 | if (tmp_srv->characteristics != NULL) 400 | { 401 | for (x = 0; tmp_srv->characteristics[x].uuid != NULL; x++) 402 | { 403 | //ONLY READ NEED ADD THIS ATT 404 | tmp_chr = tmp_srv->characteristics + x; 405 | p_bsal_stack->g_att_index++; 406 | p_bsal_stack->g_att_index++; 407 | bsal_att_create_entry(bsal_get_local_stack_obj(), p_bsal_stack->g_att_index, tmp_chr->value_length); 408 | 409 | if ((tmp_srv->characteristics[x].properties & BSAL_ATT_P_NOTIFY) || (tmp_srv->characteristics[x].properties & BSAL_ATT_P_INDICATE)) 410 | { 411 | p_bsal_stack->g_att_index ++; 412 | } 413 | } 414 | } 415 | } 416 | 417 | int rc; 418 | /* Ensure this function only gets called by sysinit. */ 419 | SYSINIT_ASSERT_ACTIVE(); 420 | 421 | rc = ble_gatts_count_cfg(nimble_srvs); 422 | SYSINIT_PANIC_ASSERT(rc == 0); 423 | 424 | rc = ble_gatts_add_svcs(nimble_srvs); 425 | SYSINIT_PANIC_ASSERT(rc == 0); 426 | #endif 427 | return BSAL_RESULT_SUCCESS; 428 | } 429 | 430 | //FOR APP 431 | static BSAL_STATUS bsal_int_srv_profile_srv_end(void) 432 | { 433 | //all register service is end 434 | //NIMBLE NO NEED 435 | return BSAL_RESULT_SUCCESS; 436 | } 437 | static uint32_t bsal_stack_get_unique_handle(uint16_t start_handle, uint16_t offset_handle) 438 | { 439 | return (start_handle + offset_handle); 440 | } 441 | 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) 442 | { 443 | #ifdef PKG_BSAL_NIMBLE_STACK 444 | int rc; 445 | struct os_mbuf *om; 446 | /*TODO*/ 447 | om = ble_hs_mbuf_from_flat(value, value_len); 448 | if (send_type != BSAL_SEND_DATA_TYPE_INDICATION) 449 | { 450 | rc = ble_gattc_notify_custom(conn_id, bsal_stack_get_unique_handle(service_id, offset_handle), om); 451 | } 452 | else 453 | { 454 | rc = ble_gattc_indicate_custom(conn_id, bsal_stack_get_unique_handle(service_id, offset_handle), om); 455 | } 456 | #endif 457 | 458 | return BSAL_RESULT_SUCCESS; 459 | } 460 | 461 | static void bsal_stack_set_bond_param(bsal_bond_param_t *bond_param) 462 | { 463 | #ifdef PKG_BSAL_NIMBLE_STACK 464 | /* TODO*/ 465 | 466 | if (bond_param->bonding_flag == false) 467 | { 468 | ble_hs_cfg.sm_bonding = 0; 469 | return; 470 | } 471 | else 472 | { 473 | ble_hs_cfg.sm_bonding = 1; 474 | } 475 | //set iocapability 476 | ble_hs_cfg.sm_io_cap = bond_param->io_capability; 477 | //set mitm 478 | if (bond_param->io_capability != BSAL_GAP_IO_CAP_NO_INPUT_NO_OUTPUT) 479 | { 480 | //maybe have mitm 481 | if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_MITM_FLAG) 482 | { 483 | ble_hs_cfg.sm_mitm = 1; 484 | } 485 | if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_SC_FLAG) 486 | { 487 | ble_hs_cfg.sm_sc = 1; 488 | } 489 | if (bond_param->auth_type & BSAL_GAP_AUTHEN_BIT_KEYPRESS_FLAG) 490 | { 491 | ble_hs_cfg.sm_keypress = 1; 492 | } 493 | } 494 | 495 | if (bond_param->oob_flag == true) 496 | { 497 | ble_hs_cfg.sm_oob_data_flag = 1; 498 | } 499 | #endif 500 | } 501 | 502 | static void bsal_stack_le_set_adv_param(bsal_adv_param_t *adv_param) 503 | { 504 | if (adv_param->set_param_flag & BSAL_SET_LE_ADV_PARAM) 505 | { 506 | //save to local adv_param 507 | bsal_stack_obj_t *p_bsal_stack = bsal_get_local_stack_obj(); 508 | //save the adv param 509 | memcpy(&p_bsal_stack->bsal_info.adv_param, adv_param, sizeof(bsal_adv_param_t)); 510 | } 511 | else if (adv_param->set_param_flag & BSAL_SET_LE_ADV_DATA) 512 | { 513 | #ifdef PKG_BSAL_NIMBLE_STACK 514 | ble_gap_adv_set_data((void *)((uint32_t)(adv_param->adv_data) + 1), adv_param->adv_data[0]); 515 | #endif 516 | } 517 | else if (adv_param->set_param_flag & BSAL_SET_LE_SCAN_RSP_DATA) 518 | { 519 | #ifdef PKG_BSAL_NIMBLE_STACK 520 | ble_gap_adv_rsp_set_data((void *)((uint32_t)(adv_param->scan_rsp_data) + 1), adv_param->scan_rsp_data[0]); 521 | #endif 522 | } 523 | } 524 | static void bsal_stack_set_gas_param(bsal_gaps_param_t *adv_param) 525 | { 526 | /* TODO*/ 527 | uint8_t slave_init_mtu_req = false; 528 | } 529 | 530 | bsal_stack_obj_t nimble_obj = 531 | { 532 | .bsal_ops = { 533 | .init = bsal_stack_int_init , 534 | .startup = bsal_stack_int_startup, 535 | .le_adv_enable = bsal_stack_int_le_adv_enable, 536 | .le_srv_reg_begin = bsal_int_srv_profile_srv_begin, 537 | .le_srv_reg_fun = bsal_int_srv_profile_reg_service, 538 | .le_srv_reg_end = bsal_int_srv_profile_srv_end, 539 | .le_srv_send_data = bsal_int_stack_srv_send_data, 540 | .cov_handle_to_u_handle = bsal_stack_get_unique_handle, 541 | .set_bond_param = bsal_stack_set_bond_param, 542 | .le_set_adv_param = bsal_stack_le_set_adv_param, 543 | .set_gaps_param = bsal_stack_set_gas_param, 544 | //callback 545 | }, 546 | }; 547 | 548 | 549 | 550 | -------------------------------------------------------------------------------- /port/NIMBLE/bsal_nimble.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #ifndef __BSAL_RTK_H__ 13 | #define __BSAL_RTK_H__ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | 19 | #include "host/ble_hs.h" 20 | #include "sysinit/sysinit.h" 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | 28 | #endif 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /port/NIMBLE/bsal_osif.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "bsal_osif.h" 18 | 19 | void *bsal_osif_malloc(uint32_t len) 20 | { 21 | void *p = NULL; 22 | p = rt_malloc(len); 23 | memset(p, 0, len); 24 | return p; 25 | } 26 | 27 | void bsal_osif_free(void *p) 28 | { 29 | rt_free(p); 30 | } 31 | 32 | #if 0 33 | int bsal_osif_printf_warn(const char *fmt, ...) 34 | { 35 | rt_kprintf("\r\n [BSAL][WARN]:"); 36 | va_list args; 37 | va_start(args, fmt); 38 | rt_kprintf(fmt, args); 39 | va_end(args); 40 | return 0; 41 | } 42 | 43 | int bsal_osif_printf_info(const char *fmt, ...) 44 | { 45 | rt_kprintf("\r\n [BSAL][INFO]:"); 46 | va_list args; 47 | va_start(args, fmt); 48 | rt_kprintf(fmt, args); 49 | va_end(args); 50 | return 0; 51 | } 52 | 53 | int bsal_osif_printf_dbg(const char *fmt, ...) 54 | { 55 | rt_kprintf("\r\n [BSAL][DEBUG]:"); 56 | va_list args; 57 | va_start(args, fmt); 58 | rt_kprintf(fmt, args); 59 | va_end(args); 60 | rt_kprintf("\r\n"); 61 | return 0; 62 | } 63 | 64 | 65 | int bsal_osif_printf_err(const char *fmt, ...) 66 | { 67 | rt_kprintf("\r\n [BSAL][ERROR]:"); 68 | va_list args; 69 | va_start(args, fmt); 70 | rt_kprintf(fmt, args); 71 | va_end(args); 72 | rt_kprintf("\r\n"); 73 | return 0; 74 | } 75 | #endif 76 | 77 | void bsal_osif_delay(uint32_t ms) 78 | { 79 | rt_thread_mdelay(ms); 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /port/empty_stack/bsal_osal_empty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "bsal_osif.h" 17 | 18 | 19 | void *bsal_osif_malloc(uint32_t len) 20 | { 21 | void *p = NULL; 22 | 23 | /* TODO */ 24 | return p; 25 | } 26 | 27 | void bsal_osif_free(void *p) 28 | { 29 | /* TODO */ 30 | } 31 | 32 | #if 0 33 | int bsal_osif_printf_warn(const char *fmt, ...) 34 | { 35 | /* TODO */ 36 | return 0; 37 | } 38 | 39 | int bsal_osif_printf_info(const char *fmt, ...) 40 | { 41 | /* TODO */ 42 | return 0; 43 | } 44 | 45 | int bsal_osif_printf_dbg(const char *fmt, ...) 46 | { 47 | /* TODO */ 48 | return 0; 49 | } 50 | 51 | 52 | int bsal_osif_printf_err(const char *fmt, ...) 53 | { 54 | /* TODO */ 55 | return 0; 56 | } 57 | #endif 58 | 59 | void bsal_osif_delay(uint32_t ms) 60 | { 61 | /* TODO */ 62 | 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /port/empty_stack/bsal_stack_empty.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #include 13 | #include 14 | 15 | #include "bsal.h" 16 | #include "bsal_osif.h" 17 | #include "bsal_int.h" 18 | #include "bsal_stack_api.h" 19 | 20 | 21 | //#include "bsal_stack.h" 22 | 23 | bsal_stack_obj_t rtk_obj; 24 | 25 | static void *bsal_get_rtk_obj() 26 | { 27 | return &rtk_obj; 28 | } 29 | //================================BSAL.C========================== 30 | static void bsal_rtk_stack_init(uint8_t stack_type) 31 | { 32 | /* TODO*/ 33 | } 34 | 35 | static void bsal_rtk_stack_startup(void) 36 | { 37 | /* TODO*/ 38 | } 39 | 40 | static BSAL_STATUS bsal_rtk_le_adv_enable(bool enable) 41 | { 42 | if (enable == true) 43 | { 44 | /* TODO*/ 45 | } 46 | else 47 | { 48 | /* TODO*/ 49 | } 50 | return BSAL_RESULT_SUCCESS; 51 | } 52 | //for app 53 | static BSAL_STATUS bsal_srv_profile_srv_begin(bool is_continue, uint8_t service_num, void *p_fnc_callback) 54 | { 55 | /* TODO */ 56 | return BSAL_RESULT_SUCCESS; 57 | } 58 | //common utils 59 | static BSAL_STATUS bsal_srv_profile_reg_service( 60 | struct bsal_gatt_app_srv_def *p_srv, 61 | void *p_func //callback 62 | ) 63 | { 64 | uint16_t att_num = 0; 65 | uint8_t att_index = 0; 66 | uint16_t sum_of_descript = 0; 67 | uint8_t write_index = 0; 68 | uint8_t i = 0; 69 | uint8_t j = 0; 70 | uint8_t x = 0; 71 | uint8_t y = 0; 72 | 73 | 74 | bsal_gatt_res_t res; 75 | bsal_util_sum_handle_num(p_srv, &res); 76 | att_num = res.attrs; 77 | return BSAL_RESULT_SUCCESS; 78 | } 79 | 80 | 81 | //FOR APP 82 | static BSAL_STATUS bsal_srv_profile_srv_end(void) 83 | { 84 | //all register service is end 85 | return BSAL_RESULT_SUCCESS; 86 | } 87 | 88 | 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) 89 | { 90 | /* TODO */ 91 | return BSAL_RESULT_FAIL; 92 | } 93 | 94 | static uint32_t bsal_stack_rtk_get_unique_handle(uint16_t start_id, uint16_t offset_handle) 95 | { 96 | /* TODO */ 97 | return 0; 98 | } 99 | 100 | static void bsal_stack_rtk_set_bond_param(bsal_bond_param_t *bond_param) 101 | { 102 | uint8_t auth_pair_mode; 103 | uint16_t auth_flags; 104 | /* TODO */ 105 | } 106 | 107 | static void bsal_rtk_le_set_adv_param(bsal_adv_param_t *adv_param) 108 | { 109 | /* TODO*/ 110 | } 111 | static void bsal_rtk_set_gas_param(bsal_gaps_param_t *adv_param) 112 | { 113 | uint8_t slave_init_mtu_req = false; 114 | /* TODO*/ 115 | } 116 | 117 | bsal_stack_obj_t rtk_obj = 118 | { 119 | .bsal_ops = { 120 | .init = bsal_rtk_stack_init, 121 | .startup = bsal_rtk_stack_startup, 122 | .le_adv_enable = bsal_rtk_le_adv_enable, 123 | .le_srv_reg_begin = bsal_srv_profile_srv_begin, 124 | .le_srv_reg_fun = bsal_srv_profile_reg_service, 125 | .le_srv_reg_end = bsal_srv_profile_srv_end, 126 | .le_srv_send_data = bsal_stack_srv_send_data, 127 | .cov_handle_to_u_handle = bsal_stack_rtk_get_unique_handle, 128 | .set_bond_param = bsal_stack_rtk_set_bond_param, 129 | .le_set_adv_param = bsal_rtk_le_set_adv_param, 130 | .set_gaps_param = bsal_rtk_set_gas_param, 131 | //callback 132 | }, 133 | }; 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /port/empty_stack/bsal_stack_empty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #ifndef __BSAL_STACK_H__ 13 | #define __BSAL_STACK_H__ 14 | 15 | /** 16 | * @brief Initialize App task 17 | * @return void 18 | */ 19 | 20 | 21 | 22 | #endif 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /port/realtek/bsal_osif.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "bsal_osif.h" 17 | #include "os_mem.h" 18 | #include "os_sched.h" 19 | 20 | 21 | void *bsal_osif_malloc(uint32_t len) 22 | { 23 | void *p = NULL; 24 | p = os_mem_alloc(RAM_TYPE_DATA_ON, len); 25 | memset(p, 0, len); 26 | return p; 27 | } 28 | 29 | void bsal_osif_free(void *p) 30 | { 31 | os_mem_free(p); 32 | } 33 | 34 | void bsal_osif_delay(uint32_t ms) 35 | { 36 | os_delay(ms); 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /port/realtek/bsal_rtk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #ifndef __BSAL_RTK_H__ 13 | #define __BSAL_RTK_H__ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include "os_mem.h" 19 | #include "os_msg.h" 20 | #include "os_task.h" 21 | #include "gap.h" 22 | #include "gap_le.h" 23 | #include "profile_server.h" 24 | #include "gap.h" 25 | #include "gap_adv.h" 26 | #include "gap_bond_le.h" 27 | #include "app_msg.h" 28 | #include "trace.h" 29 | #include "gap_bond_le.h" 30 | #include "gap_msg.h" 31 | #include "gap_conn_le.h" 32 | /** 33 | * @brief Initialize App task 34 | * @return void 35 | */ 36 | void app_task_init(void); 37 | static const T_FUN_GATT_SERVICE_CBS bsal_cbs; 38 | static T_APP_RESULT bsal_app_gap_callback(uint8_t cb_type, void *p_cb_data); 39 | static T_APP_RESULT bsal_app_profile_callback(T_SERVER_ID service_id, void *p_data); 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | 45 | 46 | #endif 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /profiles/service/basl_bas/bsal_srv_bas.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include "bsal.h" 14 | #include "bsal_osif.h" 15 | #include "bsal_srv_bas.h" 16 | 17 | 18 | static uint8_t bsal_bas_battery_level = 50; 19 | 20 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 21 | static void profile_callback(void *p) 22 | { 23 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 24 | bool is_app_cb = false; 25 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 26 | { 27 | if (GATT_SVC_BAS_BATTERY_LEVEL_INDEX == p_param->off_handle) 28 | { 29 | is_app_cb = true; 30 | //write db the battery_level 31 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(uint8_t), &bsal_bas_battery_level); 32 | } 33 | 34 | } 35 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 36 | { 37 | //do nothing 38 | is_app_cb = true; 39 | } 40 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 41 | { 42 | if (GATT_SVC_BAS_CHAR_CCCD_INDEX == p_param->off_handle) 43 | { 44 | if (p_param->length == 2) 45 | { 46 | //uint16_t ccdbit = (uint16_t)p_param->data; 47 | is_app_cb = true; 48 | } 49 | } 50 | } 51 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_HANDLE_TABLE) 52 | { 53 | //save the could notify u_handle 54 | // bsal_start_handle = p_param->start_handle; 55 | } 56 | 57 | if (is_app_cb && (pfn_bas_cb != NULL)) 58 | { 59 | pfn_bas_cb(p_param); 60 | } 61 | 62 | //read write the datebase 63 | 64 | } 65 | 66 | void bsal_le_bas_svr_init(void *stack_ptr, void *app_callback) 67 | { 68 | struct bsal_gatt_app_srv_def ble_svc_bas_defs[] = 69 | { 70 | { 71 | /*** Battery Service. */ 72 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 73 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BATTERY),//(bsal_uuid_any_t *)&battery_srv,//BSAL_UUID16_DECLARE(GATT_UUID_BATTERY), 74 | .characteristics = (bsal_gatt_chr_def_t[]) 75 | { 76 | { 77 | /*** Battery level characteristic */ 78 | .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), 79 | .properties = BSAL_ATT_P_READ 80 | | BSAL_ATT_P_NOTIFY 81 | , 82 | .permission = BSAL_GATT_PERM_READ_NONE, 83 | .value_length = 1, 84 | }, 85 | { 86 | 0, /* No more characteristics in this service. */ 87 | } 88 | }, 89 | }, 90 | 91 | { 92 | 0, /* No more services. */ 93 | }, 94 | }; 95 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_bas_defs, (P_SRV_GENERAL_CB *)profile_callback); 96 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 97 | } 98 | void bsal_le_bas_svr_deinit(void *stack_ptr) 99 | { 100 | //delete the service 101 | } 102 | 103 | 104 | //no notify 105 | void bsal_set_battery_level_static(uint8_t battery_level) 106 | { 107 | bsal_bas_battery_level = battery_level; 108 | } 109 | 110 | void bsal_bas_send_notify_level(void *stack_ptr, uint16_t conn_id, uint8_t battery_level) 111 | { 112 | /*TODO*/ 113 | if (battery_level > 100) 114 | { 115 | bsal_osif_printf_err("The battery is invalid:%d", battery_level); 116 | return; 117 | } 118 | bsal_uuid_any_t uuid_srv; 119 | uuid_srv.u_type = 16; 120 | uuid_srv.u16.value = GATT_UUID_BATTERY; 121 | uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv); 122 | bsal_bas_battery_level = battery_level; 123 | bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, GATT_SVC_BAS_BATTERY_LEVEL_INDEX, sizeof(uint8_t), &battery_level); 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /profiles/service/basl_bas/bsal_srv_bas.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | #ifndef __BSAL_SRV_BAS_H__ 12 | #define __BSAL_SRV_BAS_H__ 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | #include 17 | #include 18 | #include "bsal.h" 19 | #define GATT_UUID_BATTERY BSAL_GATT_SERVICE_BATTERY_SERVICE 20 | #define GATT_UUID_CHAR_BAS_LEVEL BSAL_UUID_CHAR_BATTERY_LEVEL 21 | 22 | #define GATT_SVC_BAS_BATTERY_LEVEL_INDEX 2 /**< @brief Index for battery level chars's value */ 23 | #define GATT_SVC_BAS_CHAR_CCCD_INDEX (GATT_SVC_BAS_BATTERY_LEVEL_INDEX+1) /**< @brief CCCD Index for battery level chars's value */ 24 | /** 25 | * BSAL battery service init 26 | * 27 | * @param stack_ptr the point of the stack object 28 | * @param app_callback the callback of the service 29 | * @Note init the service 30 | */ 31 | void bsal_le_bas_svr_init(void *stack_ptr, void *app_callback); 32 | 33 | /** 34 | * BSAL set the battery level local 35 | * 36 | * @param stack_ptr the point of the stack object 37 | * @param app_callback the callback of the service 38 | * @Note init the service 39 | */ 40 | void bsal_set_battery_level_static(uint8_t battery_level); 41 | 42 | /** 43 | * BSAL set the battery level and send notify 44 | * 45 | * @param stack_ptr the point of the stack object 46 | * @param conn_id the conn_handle of the link 47 | * @param battery_level the battery level of the battery service 48 | * @Note set the notify level 49 | */ 50 | void bsal_bas_send_notify_level(void *stack_ptr, uint16_t conn_id, uint8_t battery_level); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | #endif 56 | -------------------------------------------------------------------------------- /profiles/service/bsal_blufi/bsal_srv_blufi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include "bsal.h" 17 | #include "bsal_osif.h" 18 | #include "bsal_srv_blufi.h" 19 | 20 | #define BLUFI_RECV_BUFF_SIZE 200 21 | 22 | struct basl_blufi_recv_data 23 | { 24 | uint8_t buf[BLUFI_RECV_BUFF_SIZE]; 25 | uint16_t alloc_len; 26 | uint8_t recv_offset; 27 | }; 28 | 29 | 30 | static struct basl_blufi_recv_data blufi_data; 31 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 32 | uint8_t bsal_blufi_push_data(struct basl_blufi_recv_data *blufi_data, uint8_t length, uint8_t *data) 33 | { 34 | if (blufi_data->recv_offset + length > blufi_data->alloc_len) 35 | { 36 | //error 37 | return 1; 38 | } 39 | if (data[0] == '{') 40 | { 41 | //first entry 42 | blufi_data->recv_offset = 0; 43 | memset(blufi_data->buf, 0, blufi_data->alloc_len); 44 | } 45 | memcpy(&blufi_data->buf[blufi_data->recv_offset], data, length); 46 | blufi_data->recv_offset += length; 47 | //check the data 48 | if (data[length - 1] == '}') 49 | { 50 | return 0xff; 51 | } 52 | return 0; 53 | } 54 | 55 | 56 | static void profile_callback(void *p) 57 | { 58 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 59 | bool is_app_cb = false; 60 | //BSAL_STATUS bsal_result = BSAL_RESULT_SUCCESS; 61 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 62 | { 63 | //NO DEAL 64 | } 65 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 66 | { 67 | //do nothing 68 | if (BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX == p_param->off_handle) 69 | { 70 | uint8_t ret = bsal_blufi_push_data(&blufi_data, p_param->length, p_param->data); 71 | if (ret == 0xff) 72 | { 73 | //the data is ready 74 | is_app_cb = true; 75 | p_param->data = blufi_data.buf; 76 | p_param->length = blufi_data.recv_offset; 77 | //bsal_osif_printf("\r\n BLUFI: THE RECEIVE DATA IS :%s \r\n", p_param->data); 78 | } 79 | } 80 | } 81 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 82 | { 83 | if (BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX == p_param->off_handle) 84 | { 85 | if (p_param->length == 2) 86 | { 87 | // uint16_t ccdbit = (uint32_t)p_param->data; 88 | is_app_cb = true; 89 | } 90 | } 91 | } 92 | if (is_app_cb && (pfn_bas_cb != NULL)) 93 | { 94 | pfn_bas_cb(p_param); 95 | } 96 | } 97 | 98 | void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback) 99 | { 100 | struct bsal_gatt_app_srv_def ble_svc_blufi_defs[] = 101 | { 102 | { 103 | /*** Battery Service. */ 104 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 105 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BLUFI_PROFILE), 106 | .characteristics = (bsal_gatt_chr_def_t[]) 107 | { 108 | { 109 | /*** Battery level characteristic */ 110 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V2_WRITE), 111 | .properties = BSAL_ATT_P_WRITE 112 | , 113 | .permission = BSAL_GATT_PERM_WRITE_NONE, 114 | .value_length = 1, 115 | }, 116 | { 117 | /*** Battery level characteristic */ 118 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BLUFI_V4_INDICATE), 119 | .properties = BSAL_ATT_P_INDICATE 120 | , 121 | .permission = BSAL_GATT_PERM_WRITE_NONE | BSAL_GATT_PERM_READ_NONE, 122 | .value_length = 1, 123 | }, 124 | { 125 | 0, /* No more characteristics in this service. */ 126 | } 127 | }, 128 | }, 129 | 130 | { 131 | 0, /* No more services. */ 132 | }, 133 | }; 134 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_blufi_defs, (P_SRV_GENERAL_CB *)profile_callback); 135 | 136 | pfn_bas_cb = app_callback; 137 | blufi_data.alloc_len = BLUFI_RECV_BUFF_SIZE; 138 | blufi_data.recv_offset = 0; 139 | } 140 | 141 | void bsal_blufi_ble_send_v4_indicate(void *stack_ptr, uint16_t conn_id, void *p_value, uint16_t length) 142 | { 143 | bsal_uuid_any_t uuid_srv; 144 | uuid_srv.u_type = BSAL_UUID_TYPE_16BIT; 145 | uuid_srv.u16.value = GATT_UUID_BLUFI_PROFILE; 146 | uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv); 147 | bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX, length, p_value); 148 | } 149 | 150 | 151 | void bsal_le_blufi_svr_deinit(void *stack_ptr) 152 | { 153 | //deinit 154 | } 155 | 156 | 157 | -------------------------------------------------------------------------------- /profiles/service/bsal_blufi/bsal_srv_blufi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | 13 | 14 | #ifndef __BSAL_SRV_BLUFI_H__ 15 | #define __BSAL_SRV_BLUFI_H__ 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include 21 | #include 22 | 23 | #define GATT_UUID_BLUFI_PROFILE 0xFFFF 24 | #define GATT_UUID_CHAR_BLUFI_V2_WRITE 0xFF01 25 | #define GATT_UUID_CHAR_BLUFI_V4_INDICATE 0xFF02 26 | 27 | #define BLUEFI_BLE_SERVICE_CHAR_V2_WRITE_INDEX 0x02 28 | #define BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX 0x04 29 | #define BLUEFI_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX (BLUEFI_BLE_SERVICE_CHAR_V3_INDICATE_INDEX + 1) 30 | 31 | void bsal_le_blufi_svr_init(void *stack_ptr, void *app_callback); 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /profiles/service/bsal_dis/bsal_srv_dis.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-27 WaterFishJ the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include "bsal.h" 15 | #include "bsal_osif.h" 16 | #include "bsal_srv_dis.h" 17 | 18 | unsigned char MANUFACTURER_NAME_STRING[] = "RT-THREAD"; 19 | unsigned char PnP_ID[] = {0x02, 0x19, 0x15, 0xee, 0xee, 0x00, 0x01}; 20 | 21 | 22 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 23 | 24 | static void dis_profile_callback(void *p) 25 | { 26 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 27 | bool is_app_cb = false; 28 | 29 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 30 | { 31 | if (GATT_SVC_DIS_CHAR_MNS_INDEX == p_param->off_handle) 32 | { 33 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(MANUFACTURER_NAME_STRING), MANUFACTURER_NAME_STRING); 34 | } 35 | else if (GATT_SVC_DIS_CHAR_PNPID_INDEX == p_param->off_handle) 36 | { 37 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(PnP_ID), PnP_ID); 38 | } 39 | is_app_cb = true; 40 | } 41 | if (is_app_cb && (pfn_bas_cb != NULL)) 42 | { 43 | pfn_bas_cb(p_param); 44 | } 45 | } 46 | 47 | void bsal_le_dis_svr_init(void *stack_ptr, void *app_callback) 48 | { 49 | struct bsal_gatt_app_srv_def ble_svc_dis_defs[] = 50 | { 51 | { 52 | /*** Device Information Service. */ 53 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 54 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_DEVICE_INFORMATION), 55 | .characteristics = (bsal_gatt_chr_def_t[]) 56 | { 57 | { 58 | /*** Manufacturer Name String characteristic */ 59 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_MANUFACTURER_NAME_STRING), 60 | .properties = BSAL_ATT_P_READ, 61 | .permission = BSAL_GATT_PERM_READ_NONE, 62 | .value_length = 10, 63 | }, 64 | { 65 | /*** PnP ID characteristic */ 66 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_PNP_ID), 67 | .properties = BSAL_ATT_P_READ, 68 | .permission = BSAL_GATT_PERM_READ_NONE, 69 | .value_length = 7, 70 | }, 71 | { 72 | 0, /* No more characteristics in this service. */ 73 | } 74 | }, 75 | }, 76 | { 77 | 0, /* No more services. */ 78 | }, 79 | }; 80 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_dis_defs, (P_SRV_GENERAL_CB *)dis_profile_callback); 81 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 82 | } 83 | -------------------------------------------------------------------------------- /profiles/service/bsal_dis/bsal_srv_dis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-27 WaterFishJ the first version 9 | */ 10 | 11 | #ifndef __BSAL_SRV_DIS_H__ 12 | #define __BSAL_SRV_DIS_H__ 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | #include "stdint.h" 18 | #include "stdbool.h" 19 | 20 | #define GATT_UUID_DEVICE_INFORMATION BSAL_GATT_SERVICE_DEVICE_INFORMATION 21 | #define GATT_UUID_CHAR_MANUFACTURER_NAME_STRING BSAL_UUID_CHAR_MANUFACTURER_NAME_STRING 22 | #define GATT_UUID_CHAR_PNP_ID BSAL_UUID_CHAR_PNP_ID 23 | 24 | #define GATT_SVC_DIS_CHAR_MNS_INDEX 2 25 | #define GATT_SVC_DIS_CHAR_PNPID_INDEX 4 26 | 27 | 28 | void bsal_le_dis_svr_init(void *stack_ptr, void *app_callback); 29 | 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /profiles/service/bsal_hid/README.md: -------------------------------------------------------------------------------- 1 | # 关于未完成的 HOGP 2 | 3 | ## 一、简介 4 | 5 | HID over GATT Profile(HOGP),利用 LE 的基本协议 GATT 实现 HID Host 与 Device 的交互。 6 | 7 | 本项目目标是基于 BSAL 实现 HOGP,完成一个鼠标的 sample。 8 | 9 | 本项目目前开发使用的开发板是 PCA10056,BSAL 使用的协议栈是 Nimble。 10 | 11 | 12 | 13 | ## 二、参考 14 | 15 | 以 Nordic 官方 [nRF5_SDK_17.1.0](https://www.nordicsemi.com/Products/Development-software/nrf5-sdk/download) 中 \examples\ble_peripheral\ble_app_hids_mouse\pca10056\s140\arm5_no_packs 作参考。 16 | 17 | 相关文件已放在 Softdevice 文件夹内。 18 | 19 | ### 2.1 测试方法 20 | 21 | 打开官方 sdk 的 hid sample 工程,板子连接上之后,首先将板子完全擦除一遍。使用 sde 规则擦除芯片: 22 | 23 | 2021-10-12135211 24 | 25 | 擦除完芯片后,将工程切换至 Softdevice 目标,并下载(不需要编译): 26 | 27 | 2021-10-12135502 28 | 29 | 下载完 Softdevice 后,再将工程目标切换为 nrf52840_xxaa ,编译并下载。此时,打开串口工具,按下板子的复位键,就能看到有打印信息出来。 30 | 31 | 打开电脑的蓝牙,搜索设备,连接板子(此时板子是一个鼠标设备)。连接成功后,按下板子的按键,电脑的鼠标就能上下左右移动了。 32 | 33 | 手机(安卓)同理,打开蓝牙,搜索设备,连接板子。连接成功后,按下板子上的按键,手机屏幕上便会出现一个鼠标,这个鼠标也会移动。 34 | 35 | 需要注意的是,有时候会出现怎么也连不上板子蓝牙的情况。这时候需要将板子擦除一次,并重新烧录文件。有可能是程序对上一次连接的设备做了记录,导致下一次就不能连接其他设备了。 36 | 37 | ### 2.2 抓包 38 | 39 | 利用手机进行了一次抓包,抓包文件在当前目录下的 btsnoop_hci_hid.cfa 文件。可以使用 Frontline 查看文件。具体抓包与查看文件[教程链接](https://supperthomas-wiki.readthedocs.io/en/latest/03_xupenghu/04_btsnoop_hci/android_hci.html)。 40 | 41 | 抓包的操作过程:首先擦除芯片,重新烧录文件。然后手机开启抓包模式,在设置->蓝牙里,连接上板子。逐一按下板子的四个按键,鼠标向上下左右四个方向移动了一点距离,抓包操作结束。 42 | 43 | 44 | 45 | ## 三、目前进度 46 | 47 | ### 3.1 sample 需要的各种 Service 的注册已实现 48 | 49 | 按照参考的工程,各种 Service 的注册已实现,包括 HID,BAS,DIS 等等。即目前手机连接上后,用 nRF Connect 看到的 Service 与参考工程的一致。但 Service 里的功能尚未实现。比如说 hid上传到 bsal 层的各种中断还没处理。 50 | 51 | ### 3.2 目前卡在发送数组(Report Map 特性) 52 | 53 | #### 3.2.1 抓包的分析与结论 54 | 55 | 官方 sdk 中,有一个很长的配置用的数组(Report Map),用以告诉 host 一些配置信息。但是不是很清楚这个数组是何时、怎么发送过去的。分析抓包数据: 56 | 57 | 2021-10-12145729 58 | 59 | 可以看到,第2004帧,host 端发送一个读请求,请求读取 Report Map 数据。之后,设备分七次将 Report Map 数据发送过去。 60 | 61 | 因此,这个数组是 hid 下的 Report Map 特性的一个值,当 host 请求读取 Report Map 特性值时,便要将数组发送过去。要实现的就是这个发送过程。 62 | 63 | #### 3.2.2 手机请求读取 Report Map 数据时,没有中断传上来 64 | 65 | 手机用 nRF Connect 连接上设备后,读取 Report Map 特性无反应,调试发现读请求中断没有上传到 BSAL。 66 | 67 | 为了排除是服务、特性之间的影响,我只保留一个 Service 和一个特性,将其他全部注释掉(现在 bsal_srv_hid.c 便是如此)。发现 hid 服务下,除了几个特性以外,其他的特性的读、写请求中断均无法上传到 BSAL 层。 68 | 69 | 一开始怀疑是 BSAL 层某些部分未实现,尝试 debug 后发现,原来在 nimble 就已经没有中断上传上来了。不是 BSAL 的问题,便没有继续往 nimble 去 debug 了。 70 | 71 | 目前怀疑两个地方:一个是 nimble 的 rt-thread 接口部分会不会有 bug;一个是手机连接会不会有问题。 72 | 73 | - 第一个,nimble 的 ops 函数会不会有问题,特别是注册 Service 的那条函数,以及 nimble 的读写中断向 BSAL 传时会不会有 bug。 74 | 75 | - 第二个,在猜测有没有可能在连接时需要一些加密,或者验证等,才能继续后面读取 Report Map 操作。 76 | 77 | 78 | 79 | 项目未完,待续…… -------------------------------------------------------------------------------- /profiles/service/bsal_hid/bsal_srv_hid.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include "bsal.h" 14 | #include "bsal_osif.h" 15 | #include "bsal_srv_hid.h" 16 | 17 | 18 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 19 | 20 | 21 | static uint8_t rep_map_data[] = 22 | { 23 | 0x05, 0x01, // Usage Page (Generic Desktop) 24 | 0x09, 0x02, // Usage (Mouse) 25 | 26 | 0xA1, 0x01, // Collection (Application) 27 | 28 | // Report ID 1: Mouse buttons + scroll/pan 29 | 0x85, 0x01, // Report Id 1 30 | 0x09, 0x01, // Usage (Pointer) 31 | 0xA1, 0x00, // Collection (Physical) 32 | 0x95, 0x05, // Report Count (3) 33 | 0x75, 0x01, // Report Size (1) 34 | 0x05, 0x09, // Usage Page (Buttons) 35 | 0x19, 0x01, // Usage Minimum (01) 36 | 0x29, 0x05, // Usage Maximum (05) 37 | 0x15, 0x00, // Logical Minimum (0) 38 | 0x25, 0x01, // Logical Maximum (1) 39 | 0x81, 0x02, // Input (Data, Variable, Absolute) 40 | 0x95, 0x01, // Report Count (1) 41 | 0x75, 0x03, // Report Size (3) 42 | 0x81, 0x01, // Input (Constant) for padding 43 | 0x75, 0x08, // Report Size (8) 44 | 0x95, 0x01, // Report Count (1) 45 | 0x05, 0x01, // Usage Page (Generic Desktop) 46 | 0x09, 0x38, // Usage (Wheel) 47 | 0x15, 0x81, // Logical Minimum (-127) 48 | 0x25, 0x7F, // Logical Maximum (127) 49 | 0x81, 0x06, // Input (Data, Variable, Relative) 50 | 0x05, 0x0C, // Usage Page (Consumer) 51 | 0x0A, 0x38, 0x02, // Usage (AC Pan) 52 | 0x95, 0x01, // Report Count (1) 53 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 54 | 0xC0, // End Collection (Physical) 55 | 56 | // Report ID 2: Mouse motion 57 | 0x85, 0x02, // Report Id 2 58 | 0x09, 0x01, // Usage (Pointer) 59 | 0xA1, 0x00, // Collection (Physical) 60 | 0x75, 0x0C, // Report Size (12) 61 | 0x95, 0x02, // Report Count (2) 62 | 0x05, 0x01, // Usage Page (Generic Desktop) 63 | 0x09, 0x30, // Usage (X) 64 | 0x09, 0x31, // Usage (Y) 65 | 0x16, 0x01, 0xF8, // Logical maximum (2047) 66 | 0x26, 0xFF, 0x07, // Logical minimum (-2047) 67 | 0x81, 0x06, // Input (Data, Variable, Relative) 68 | 0xC0, // End Collection (Physical) 69 | 0xC0, // End Collection (Application) 70 | 71 | // Report ID 3: Advanced buttons 72 | 0x05, 0x0C, // Usage Page (Consumer) 73 | 0x09, 0x01, // Usage (Consumer Control) 74 | 0xA1, 0x01, // Collection (Application) 75 | 0x85, 0x03, // Report Id (3) 76 | 0x15, 0x00, // Logical minimum (0) 77 | 0x25, 0x01, // Logical maximum (1) 78 | 0x75, 0x01, // Report Size (1) 79 | 0x95, 0x01, // Report Count (1) 80 | 81 | 0x09, 0xCD, // Usage (Play/Pause) 82 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 83 | 0x0A, 0x83, 0x01, // Usage (AL Consumer Control Configuration) 84 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 85 | 0x09, 0xB5, // Usage (Scan Next Track) 86 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 87 | 0x09, 0xB6, // Usage (Scan Previous Track) 88 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 89 | 90 | 0x09, 0xEA, // Usage (Volume Down) 91 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 92 | 0x09, 0xE9, // Usage (Volume Up) 93 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 94 | 0x0A, 0x25, 0x02, // Usage (AC Forward) 95 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 96 | 0x0A, 0x24, 0x02, // Usage (AC Back) 97 | 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 98 | 0xC0 // End Collection 99 | }; 100 | 101 | 102 | static void hid_profile_callback(void *p) 103 | { 104 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 105 | bool is_app_cb = false; 106 | rt_kprintf("msg_type = %d\n", p_param->msg_type); 107 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 108 | { 109 | rt_kprintf("off_handle = %d\n", p_param->off_handle); 110 | if (GATT_SVC_HID_REPORT_MAP_INDEX == p_param->off_handle) 111 | { 112 | is_app_cb = true; 113 | rt_kprintf("report map\n"); 114 | // bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(rep_map_data), rep_map_data); 115 | } 116 | } 117 | if (is_app_cb && (pfn_bas_cb != NULL)) 118 | { 119 | pfn_bas_cb(p_param); 120 | } 121 | } 122 | 123 | 124 | void bsal_le_hid_svr_init(void *stack_ptr, void *app_callback) 125 | { 126 | struct bsal_gatt_app_srv_def ble_svc_hid_defs[] = 127 | { 128 | { 129 | /*** Hid Service. */ 130 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 131 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_HID), 132 | .characteristics = (bsal_gatt_chr_def_t[]) 133 | { 134 | // { 135 | // /*** Protocol Mode characteristic */ 136 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_PROTOCOL_MODE), 137 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE_WITHOUT_RESPONSE, 138 | // .permission = BSAL_GATT_PERM_READ_NONE, 139 | // .value_length = 1, 140 | // }, 141 | { 142 | /*** Input Report characteristics */ 143 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_INPUT_REPORT), 144 | .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE | BSAL_ATT_P_NOTIFY, 145 | .permission = BSAL_GATT_PERM_READ_NONE, 146 | .value_length = 1, 147 | }, 148 | // { 149 | // /*** Output Report characteristics */ 150 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_INPUT_REPORT), 151 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE | BSAL_ATT_P_NOTIFY, 152 | // .permission = BSAL_GATT_PERM_READ_NONE, 153 | // .value_length = 1, 154 | // }, 155 | // { 156 | // /*** Feature Report characteristics */ 157 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_INPUT_REPORT), 158 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE | BSAL_ATT_P_NOTIFY, 159 | // .permission = BSAL_GATT_PERM_READ_NONE, 160 | // .value_length = 1, 161 | // }, 162 | // { 163 | // /*** Report Map characteristics */ 164 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_REPORT_MAP), 165 | // .properties = BSAL_ATT_P_READ, 166 | // .permission = BSAL_GATT_PERM_READ_NONE, 167 | // .value_length = 1, 168 | //// .value_length = sizeof(rep_map_data), 169 | //// .val_handle = rep_map_data, 170 | // }, 171 | // { 172 | // /*** Boot Mouse Input Report characteristics */ 173 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BOOT_MOUSE_INPUT_REPORT), 174 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE | BSAL_ATT_P_NOTIFY, 175 | // .permission = BSAL_GATT_PERM_READ_NONE, 176 | // .value_length = 1, 177 | // }, 178 | // { 179 | // /*** HID Information characteristics */ 180 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_HID_INFORMATION), 181 | // .properties = BSAL_ATT_P_READ, 182 | // .permission = BSAL_GATT_PERM_READ_NONE, 183 | // .value_length = 1, 184 | // }, 185 | // { 186 | // /*** HID Control Point characteristics */ 187 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_HID_CONTROL_POINT), 188 | // .properties = BSAL_ATT_P_WRITE_WITHOUT_RESPONSE, 189 | // .permission = BSAL_GATT_PERM_READ_NONE, 190 | // .value_length = 1, 191 | // }, 192 | { 193 | 0, /* No more characteristics in this service. */ 194 | } 195 | }, 196 | }, 197 | // { 198 | // /*** Battery Service. */ 199 | // .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 200 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_BATTERY), 201 | // .characteristics = (bsal_gatt_chr_def_t[]) 202 | // { 203 | // { 204 | // /*** Battery Level characteristic */ 205 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL), 206 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_NOTIFY, 207 | // .permission = BSAL_GATT_PERM_READ_NONE, 208 | // .value_length = 1, 209 | // }, 210 | // { 211 | // 0, /* No more characteristics in this service. */ 212 | // } 213 | // }, 214 | // }, 215 | // { 216 | // /*** Device Information Service. */ 217 | // .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 218 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_DEVICE_INFORMATION), 219 | // .characteristics = (bsal_gatt_chr_def_t[]) 220 | // { 221 | // { 222 | // /*** Manufacturer Name String characteristic */ 223 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_MANUFACTURER_NAME_STRING), 224 | // .properties = BSAL_ATT_P_READ, 225 | // .permission = BSAL_GATT_PERM_READ_NONE, 226 | // .value_length = 1, 227 | // }, 228 | // { 229 | // /*** PnP ID characteristic */ 230 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_PNP_ID), 231 | // .properties = BSAL_ATT_P_READ, 232 | // .permission = BSAL_GATT_PERM_READ_NONE, 233 | // .value_length = 1, 234 | // }, 235 | // { 236 | // 0, /* No more characteristics in this service. */ 237 | // } 238 | // }, 239 | // }, 240 | // { 241 | // /*** Generic Attribute Service. */ 242 | // .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 243 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_GENERIC_ATTRIBUTE), 244 | // /* This service is empty */ 245 | // }, 246 | // { 247 | // /*** Generic Access Service. */ 248 | // .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 249 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_GENERIC_ACCESS), 250 | // .characteristics = (bsal_gatt_chr_def_t[]) 251 | // { 252 | // { 253 | // /*** Device Name characteristic */ 254 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_DEVICE_NAME), 255 | // .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE, 256 | // .permission = BSAL_GATT_PERM_READ_NONE, 257 | // .value_length = 1, 258 | // }, 259 | // { 260 | // /*** Appearance characteristic */ 261 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_GAP_APPEARANCE), 262 | // .properties = BSAL_ATT_P_READ, 263 | // .permission = BSAL_GATT_PERM_READ_NONE, 264 | // .value_length = 1, 265 | // }, 266 | // { 267 | // /*** Peripheral Preferred Connection Parameters characteristic */ 268 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_PPCP), 269 | // .properties = BSAL_ATT_P_READ, 270 | // .permission = BSAL_GATT_PERM_READ_NONE, 271 | // .value_length = 1, 272 | // }, 273 | // { 274 | // /*** Central Address Resolution characteristic */ 275 | // .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_CENTRAL_ADDRESS_RESOLUTION), 276 | // .properties = BSAL_ATT_P_READ, 277 | // .permission = BSAL_GATT_PERM_READ_NONE, 278 | // .value_length = 1, 279 | // }, 280 | // { 281 | // 0, /* No more characteristics in this service. */ 282 | // } 283 | // }, 284 | // }, 285 | { 286 | 0, /* No more services. */ 287 | }, 288 | }; 289 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_hid_defs, (P_SRV_GENERAL_CB *)hid_profile_callback); 290 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 291 | } 292 | 293 | 294 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /profiles/service/bsal_hid/bsal_srv_hid.h: -------------------------------------------------------------------------------- 1 | #ifndef __BSAL_SRV_HID_H__ 2 | #define __BSAL_SRV_HID_H__ 3 | 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | #include 9 | #include 10 | #include "bsal.h" 11 | 12 | 13 | 14 | #define GATT_UUID_HID BSAL_GATT_SERVICE_HUMAN_INTERFACE_DEVICE 15 | #define GATT_UUID_CHAR_PROTOCOL_MODE BSAL_UUID_CHAR_PROTOCOL_MODE 16 | #define GATT_UUID_CHAR_INPUT_REPORT BSAL_UUID_CHAR_REPORT 17 | #define GATT_UUID_CHAR_OUTPUT_REPORT BSAL_UUID_CHAR_REPORT 18 | #define GATT_UUID_CHAR_FEATURE_REPORT BSAL_UUID_CHAR_REPORT 19 | #define GATT_UUID_CHAR_REPORT_MAP BSAL_UUID_CHAR_REPORT_MAP 20 | #define GATT_UUID_CHAR_BOOT_MOUSE_INPUT_REPORT BSAL_UUID_CHAR_BOOT_MOUSE_INPUT_REPORT 21 | #define GATT_UUID_CHAR_HID_INFORMATION BSAL_UUID_CHAR_HID_INFORMATION 22 | #define GATT_UUID_CHAR_HID_CONTROL_POINT BSAL_UUID_CHAR_HID_CONTROL_POINT 23 | 24 | #define GATT_UUID_BATTERY BSAL_GATT_SERVICE_BATTERY_SERVICE 25 | #define GATT_UUID_CHAR_BAS_LEVEL BSAL_UUID_CHAR_BATTERY_LEVEL 26 | 27 | #define GATT_UUID_DEVICE_INFORMATION BSAL_GATT_SERVICE_DEVICE_INFORMATION 28 | #define GATT_UUID_CHAR_MANUFACTURER_NAME_STRING BSAL_UUID_CHAR_MANUFACTURER_NAME_STRING 29 | #define GATT_UUID_CHAR_PNP_ID BSAL_UUID_CHAR_PNP_ID 30 | 31 | #define GATT_UUID_GENERIC_ATTRIBUTE BSAL_GATT_SERVICE_GENERIC_ATTRIBUTE 32 | 33 | #define GATT_UUID_GENERIC_ACCESS BSAL_GATT_SERVICE_GENERIC_ACCESS 34 | #define GATT_UUID_CHAR_DEVICE_NAME BSAL_UUID_CHAR_GAP_DEVICE_NAME 35 | #define GATT_UUID_CHAR_GAP_APPEARANCE BSAL_UUID_CHAR_GAP_APPEARANCE 36 | #define GATT_UUID_CHAR_PPCP BSAL_UUID_CHAR_GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS 37 | #define GATT_UUID_CHAR_CENTRAL_ADDRESS_RESOLUTION BSAL_UUID_CHAR_GAP_CENTRAL_ADDRESS_RESOLUTION 38 | 39 | 40 | #define GATT_SVC_HID_REPORT_MAP_INDEX 35 41 | 42 | void bsal_le_hid_svr_init(void *stack_ptr, void *app_callback); 43 | #endif 44 | 45 | 46 | -------------------------------------------------------------------------------- /profiles/service/bsal_hid/btsnoop_hci_hid.cfa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/profiles/service/bsal_hid/btsnoop_hci_hid.cfa -------------------------------------------------------------------------------- /profiles/service/bsal_hid/images/2021-10-12135211.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/profiles/service/bsal_hid/images/2021-10-12135211.jpg -------------------------------------------------------------------------------- /profiles/service/bsal_hid/images/2021-10-12135502.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/profiles/service/bsal_hid/images/2021-10-12135502.jpg -------------------------------------------------------------------------------- /profiles/service/bsal_hid/images/2021-10-12145729.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RT-Thread-packages/bsal/6bf16cce27e05b307b591e986c2544619e9b3d1f/profiles/service/bsal_hid/images/2021-10-12145729.jpg -------------------------------------------------------------------------------- /profiles/service/bsal_hrs/bsal_srv_hrs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-010 WaterFishJ the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include "bsal.h" 18 | #include "bsal_osif.h" 19 | #include "bsal_srv_hrs.h" 20 | 21 | static uint16_t hrs_hrm_handle; 22 | 23 | /* Sensor location, set to "Chest" */ 24 | static uint8_t body_sens_loc = BODY_SENSOR_LOCATION_CHEST; 25 | 26 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 27 | static void hrs_profile_callback(void *p) 28 | { 29 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 30 | bool is_app_cb = false; 31 | 32 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 33 | { 34 | if (GATT_SVC_BODY_SENSOR_LOCATION_READ_INDEX == p_param->off_handle) 35 | { 36 | is_app_cb = true; 37 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, sizeof(uint8_t), &body_sens_loc); 38 | } 39 | } 40 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 41 | { 42 | is_app_cb = true; 43 | } 44 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 45 | { 46 | if (GATT_SVC_HRS_MEASUREMENT_CHAR_CCCD_INDEX == p_param->off_handle) 47 | { 48 | if (p_param->length == 2) 49 | { 50 | is_app_cb = true; 51 | } 52 | } 53 | } 54 | if (is_app_cb && (pfn_bas_cb != NULL)) 55 | { 56 | pfn_bas_cb(p_param); 57 | } 58 | } 59 | 60 | void bsal_le_hrs_svr_init(void *stack_ptr, void *app_callback) 61 | { 62 | struct bsal_gatt_app_srv_def ble_svc_hrs_defs[] = 63 | { 64 | { 65 | /*** Heart Rate Service. */ 66 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 67 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_HEART_RATE), 68 | .characteristics = (bsal_gatt_chr_def_t[]) 69 | { 70 | { 71 | /*** Heart Rate Measurement characteristic */ 72 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_HRS_MEASUREMENT), 73 | .properties = BSAL_ATT_P_NOTIFY, 74 | .val_handle = &hrs_hrm_handle, 75 | .permission = BSAL_GATT_PERM_READ_NONE, 76 | .value_length = 1, 77 | }, 78 | { 79 | /*** Body Sensor Location characteristic */ 80 | .uuid = BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BODY_SENSOR_LOCATION), 81 | .properties = BSAL_ATT_P_READ, 82 | .val_handle = &hrs_hrm_handle, 83 | .permission = BSAL_GATT_PERM_READ_NONE, 84 | .value_length = 1, 85 | }, 86 | { 87 | 0, /* No more characteristics in this service. */ 88 | } 89 | }, 90 | }, 91 | { 92 | 0, /* No more services. */ 93 | }, 94 | }; 95 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_hrs_defs, (P_SRV_GENERAL_CB *)hrs_profile_callback); 96 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 97 | } 98 | 99 | void bsal_hrs_send_notify_level(void *stack_ptr, uint16_t conn_id, uint8_t *hr_measurement) 100 | { 101 | bsal_uuid_any_t uuid_srv; 102 | uuid_srv.u_type = 16; 103 | uuid_srv.u16.value = GATT_UUID_HEART_RATE; 104 | uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv); 105 | bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, GATT_SVC_HRS_MEASUREMENT_CHAR_INDEX, sizeof(hr_measurement), hr_measurement); 106 | } 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /profiles/service/bsal_hrs/bsal_srv_hrs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-10 WaterFishJ the first version 9 | */ 10 | 11 | #ifndef __BSAL_SRV_HRS_H__ 12 | #define __BSAL_SRV_HRS_H__ 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | #include 17 | #include 18 | #include "bsal.h" 19 | #define GATT_UUID_HEART_RATE BSAL_GATT_SERVICE_HEART_RATE 20 | #define GATT_UUID_HRS_MEASUREMENT BSAL_UUID_CHAR_HEART_RATE_MEASUREMENT 21 | #define GATT_UUID_CHAR_BODY_SENSOR_LOCATION BSAL_UUID_CHAR_BODY_SENSOR_LOCATION 22 | #define GATT_UUID_SERVICE_DEVICE_INFORMATION BSAL_GATT_SERVICE_DEVICE_INFORMATION 23 | #define GATT_UUID_CHAR_MANUFACTURER_NAME_STRING BSAL_UUID_CHAR_MANUFACTURER_NAME_STRING 24 | #define GATT_UUID_CHAR_MODEL_NUMBER_STRING BSAL_UUID_CHAR_MODEL_NUMBER_STRING 25 | 26 | 27 | #define GATT_SVC_BODY_SENSOR_LOCATION_READ_INDEX 5 28 | #define GATT_SVC_HRS_MEASUREMENT_CHAR_INDEX 2 29 | #define GATT_SVC_HRS_MEASUREMENT_CHAR_CCCD_INDEX 3 30 | 31 | #define BODY_SENSOR_LOCATION_CHEST 0x01 32 | 33 | void bsal_le_hrs_svr_init(void *stack_ptr, void *app_callback); 34 | 35 | void bsal_hrs_send_notify_level(void *stack_ptr, uint16_t conn_id, uint8_t *hr_measurement); 36 | 37 | #endif 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /profiles/service/bsal_lbs/bsal_srv_lbs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-27 WaterFishJ the first version 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include "bsal.h" 18 | #include "bsal_osif.h" 19 | #include "bsal_srv_lbs.h" 20 | 21 | /* {00001523-1212-efde-1523-785feabcd123} */ 22 | static const struct bsal_uuid128 gatt_svr_svc_lbs_uuid = 23 | BSAL_UUID128_INIT(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 24 | 0xDE, 0xEF, 0x12, 0x12, 0x23, 0x15, 0x00, 0x00); 25 | 26 | /* {00001524-1212-efde-1523-785feabcd123} */ 27 | static const struct bsal_uuid128 gatt_svr_chr_button_uuid = 28 | BSAL_UUID128_INIT(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 29 | 0xDE, 0xEF, 0x12, 0x12, 0x24, 0x15, 0x00, 0x00); 30 | 31 | 32 | /* {00001525-1212-efde-1523-785feabcd123} */ 33 | static const struct bsal_uuid128 gatt_svr_chr_led_uuid = 34 | BSAL_UUID128_INIT(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 35 | 0xDE, 0xEF, 0x12, 0x12, 0x25, 0x15, 0x00, 0x00); 36 | 37 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 38 | uint8_t *button_cccd_flag; 39 | uint8_t led_flag = 0; 40 | static void lbs_profile_callback(void *p) 41 | { 42 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 43 | bool is_app_cb = false; 44 | 45 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 46 | { 47 | if (GATT_SVC_LBS_BUTTON_INDEX == p_param->off_handle) 48 | { 49 | is_app_cb = true; 50 | uint8_t button = !rt_pin_read(BUTTON_PIN); 51 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, 1, &button); 52 | } 53 | else if (GATT_SVC_LBS_LED_INDEX == p_param->off_handle) 54 | { 55 | bsal_srv_write_data(p_param->stack_ptr, p_param->start_handle, p_param->off_handle, 1, &led_flag); 56 | } 57 | } 58 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 59 | { 60 | if (GATT_SVC_LBS_LED_INDEX == p_param->off_handle) 61 | { 62 | is_app_cb = true; 63 | led_flag = *(p_param->data); 64 | rt_pin_write(LED_PIN, !led_flag); 65 | } 66 | } 67 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 68 | { 69 | if (GATT_SVC_LBS_BUTTON_CCCD_INDEX == p_param->off_handle) 70 | { 71 | if (p_param->length == 2) 72 | { 73 | uint16_t cccbits = p_param->value; 74 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 75 | { 76 | *button_cccd_flag = 1; 77 | } 78 | else *button_cccd_flag = 0; 79 | is_app_cb = true; 80 | } 81 | } 82 | } 83 | if (is_app_cb && (pfn_bas_cb != NULL)) 84 | { 85 | pfn_bas_cb(p_param); 86 | } 87 | } 88 | 89 | void bsal_le_lbs_svr_init(void *stack_ptr, void *app_callback, uint8_t *button_flag) 90 | { 91 | struct bsal_gatt_app_srv_def ble_svc_lbs_defs[] = 92 | { 93 | { 94 | /*** LBS Service. */ 95 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 96 | .uuid = BSAL_UUID128_DECLARE(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 97 | 0xDE, 0xEF, 0x12, 0x12, 0x23, 0x15, 0x00, 0x00), 98 | .characteristics = (bsal_gatt_chr_def_t[]) 99 | { 100 | { 101 | /*** Button characteristic */ 102 | .uuid = BSAL_UUID128_DECLARE(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 103 | 0xDE, 0xEF, 0x12, 0x12, 0x24, 0x15, 0x00, 0x00), 104 | .properties = BSAL_ATT_P_READ | BSAL_ATT_P_NOTIFY, 105 | .permission = BSAL_GATT_PERM_READ_NONE, 106 | .value_length = 1, 107 | }, 108 | { 109 | /*** LED characteristic */ 110 | .uuid = BSAL_UUID128_DECLARE(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 111 | 0xDE, 0xEF, 0x12, 0x12, 0x25, 0x15, 0x00, 0x00), 112 | .properties = BSAL_ATT_P_READ | BSAL_ATT_P_WRITE, 113 | .permission = BSAL_GATT_PERM_READ_NONE, 114 | .value_length = 1, 115 | }, 116 | { 117 | 0, /* No more characteristics in this service. */ 118 | } 119 | }, 120 | }, 121 | { 122 | 0, /* No more services. */ 123 | }, 124 | }; 125 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_lbs_defs, (P_SRV_GENERAL_CB *)lbs_profile_callback); 126 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 127 | button_cccd_flag = button_flag; 128 | } 129 | 130 | 131 | void bsal_lbs_send_notify_button(void *stack_ptr, uint16_t conn_id, uint8_t flag) 132 | { 133 | bsal_uuid_any_t uuid_srv; 134 | uuid_srv.u_type = 128; 135 | rt_memcpy(uuid_srv.u128.value, gatt_svr_svc_lbs_uuid.value, 16); 136 | uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv); 137 | bsal_srv_send_notify_data(stack_ptr, conn_id, start_handle, GATT_SVC_LBS_BUTTON_INDEX, sizeof(uint8_t), &flag); 138 | } 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /profiles/service/bsal_lbs/bsal_srv_lbs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-27 WaterFishJ the first version 9 | */ 10 | 11 | #ifndef __BSAL_SRV_LBS_H__ 12 | #define __BSAL_SRV_LBS_H__ 13 | 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "bsal.h" 24 | 25 | #define BUTTON_PIN 11 26 | #define LED_PIN 15 27 | 28 | #define GATT_SVC_LBS_BUTTON_INDEX 2 29 | #define GATT_SVC_LBS_BUTTON_CCCD_INDEX 3 30 | #define GATT_SVC_LBS_LED_INDEX 5 31 | 32 | void bsal_le_lbs_svr_init(void *stack_ptr, void *app_callback, uint8_t *button_flag); 33 | 34 | void bsal_lbs_send_notify_button(void *stack_ptr, uint16_t conn_id, uint8_t flag); 35 | 36 | #endif 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /profiles/service/bsal_uart/bsal_srv_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-09 WaterFishJ the first version 9 | * 2021-09-22 WaterFishJ fix the send bug 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include "bsal.h" 19 | #include "bsal_osif.h" 20 | #include "bsal_srv_uart.h" 21 | 22 | #define MYNEWT_VAL_BLEUART_MAX_INPUT 128 23 | 24 | #define ESC_KEY 0x1B 25 | #define BACKSPACE_KEY 0x08 26 | #define DELECT_KEY 0x7F 27 | 28 | /* {6E400001-B5A3-F393-E0A9-E50E24DCCA9E} */ 29 | static const struct bsal_uuid128 gatt_svr_svc_uart_uuid = 30 | BSAL_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 31 | 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e); 32 | 33 | /* {6E400002-B5A3-F393-E0A9-E50E24DCCA9E} */ 34 | static const struct bsal_uuid128 gatt_svr_chr_uart_write_uuid = 35 | BSAL_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 36 | 0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e); 37 | 38 | 39 | /* {6E400003-B5A3-F393-E0A9-E50E24DCCA9E} */ 40 | static const struct bsal_uuid128 gatt_svr_chr_uart_read_uuid = 41 | BSAL_UUID128_INIT(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 42 | 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e); 43 | 44 | /* Pointer to a console buffer */ 45 | static rt_uint8_t *console_buf; 46 | 47 | struct bleuart_console 48 | { 49 | struct rt_semaphore *rx_end; 50 | struct rt_ringbuffer *rx_fifo; 51 | rt_err_t (*old_rx_ind)(rt_device_t dev, rt_size_t size); 52 | }; 53 | 54 | static struct bleuart_console bleuart = {0}; 55 | 56 | static P_SRV_GENERAL_CB pfn_bas_cb = NULL; 57 | static void profile_callback(void *p) 58 | { 59 | bsal_callbak_data_t *p_param = (bsal_callbak_data_t *)p; 60 | bool is_app_cb = false; 61 | 62 | if (p_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 63 | { 64 | //NO DEAL had not finished 65 | is_app_cb = true; 66 | } 67 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 68 | { 69 | if (GATT_SVC_NUS_WRITE_INDEX == p_param->off_handle) 70 | { 71 | is_app_cb = true; 72 | rt_device_write(rt_console_get_device(), 0, (char *)p_param->data, p_param->length); 73 | } 74 | } 75 | else if (p_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 76 | { 77 | if (GATT_SVC_NUS_CHAR_CCCD_INDEX == p_param->off_handle) 78 | { 79 | if (p_param->length == 2) 80 | { 81 | is_app_cb = true; 82 | } 83 | } 84 | } 85 | if (is_app_cb && (pfn_bas_cb != NULL)) 86 | { 87 | pfn_bas_cb(p_param); 88 | } 89 | } 90 | 91 | void bsal_le_uart_svr_init(void *stack_ptr, void *app_callback) 92 | { 93 | struct bsal_gatt_app_srv_def ble_svc_uart_defs[] = 94 | { 95 | { 96 | /*** Uart Service. */ 97 | .type = BSAL_GATT_UUID_PRIMARY_SERVICE, 98 | .uuid = BSAL_UUID128_DECLARE(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 99 | 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e),//(bsal_uuid_any_t *)&battery_srv,//BSAL_UUID16_DECLARE(GATT_UUID_BATTERY), 100 | .characteristics = (bsal_gatt_chr_def_t[]) 101 | { 102 | { 103 | /*** Uart read characteristic */ 104 | .uuid = BSAL_UUID128_DECLARE(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 105 | 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e),//(bsal_uuid_any_t *)&bas_char_bas_level,//BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL), 106 | .properties = BSAL_ATT_P_NOTIFY, 107 | .permission = BSAL_GATT_PERM_READ_NONE, 108 | .value_length = 1, 109 | }, 110 | { 111 | /*** Uart write characteristic */ 112 | .uuid = BSAL_UUID128_DECLARE(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 113 | 0x93, 0xf3, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e),//(bsal_uuid_any_t *)&bas_char_bas_level,//BSAL_UUID16_DECLARE(GATT_UUID_CHAR_BAS_LEVEL), 114 | .properties = BSAL_ATT_P_WRITE 115 | | BSAL_ATT_P_WRITE_WITHOUT_RESPONSE 116 | , 117 | .permission = BSAL_GATT_PERM_WRITE_NONE, 118 | .value_length = 1, 119 | }, 120 | { 121 | 0, /* No more characteristics in this service. */ 122 | } 123 | }, 124 | }, 125 | 126 | { 127 | 0, /* No more services. */ 128 | }, 129 | }; 130 | bsal_stack_le_srv_reg_func(stack_ptr, &ble_svc_uart_defs, (P_SRV_GENERAL_CB *)profile_callback); 131 | pfn_bas_cb = (P_SRV_GENERAL_CB)app_callback; 132 | } 133 | 134 | static rt_err_t bleuart_rx_ind(rt_device_t dev, rt_size_t size) 135 | { 136 | uint8_t ch; 137 | int i; 138 | 139 | for(i = 0; i < size; i++) 140 | { 141 | /* read a char */ 142 | if (rt_device_read(dev, 0, &ch, 1)) 143 | { 144 | rt_ringbuffer_put_force(bleuart.rx_fifo, &ch, 1); 145 | rt_sem_release(bleuart.rx_end); 146 | } 147 | } 148 | 149 | return RT_EOK; 150 | } 151 | 152 | static uint8_t bleuart_read(void) 153 | { 154 | uint8_t ch; 155 | 156 | rt_sem_take(bleuart.rx_end, RT_WAITING_FOREVER); 157 | rt_ringbuffer_getchar(bleuart.rx_fifo, &ch); 158 | 159 | return ch; 160 | } 161 | 162 | void bsal_bleuart_deinit(void) 163 | { 164 | rt_base_t level; 165 | rt_device_t uart_console; 166 | 167 | level = rt_hw_interrupt_disable(); 168 | uart_console = rt_console_get_device(); 169 | if(uart_console) 170 | { 171 | rt_device_set_rx_indicate(uart_console, bleuart.old_rx_ind); 172 | } 173 | rt_hw_interrupt_enable(level); 174 | 175 | if (console_buf != RT_NULL) 176 | { 177 | rt_free(console_buf); 178 | console_buf = RT_NULL; 179 | } 180 | 181 | if (bleuart.rx_end != RT_NULL) 182 | { 183 | rt_sem_delete(bleuart.rx_end); 184 | bleuart.rx_end = RT_NULL; 185 | } 186 | 187 | if (bleuart.rx_fifo != RT_NULL) 188 | { 189 | rt_ringbuffer_destroy(bleuart.rx_fifo); 190 | bleuart.rx_fifo = RT_NULL; 191 | } 192 | } 193 | 194 | void bsal_bleuart_uart_proc(void *stack_ptr, uint16_t *conn_id) 195 | { 196 | int off = 0; 197 | char ch; 198 | struct os_mbuf *om; 199 | 200 | bsal_uuid_any_t uuid_srv; 201 | uuid_srv.u_type = BSAL_UUID_TYPE_128BIT; 202 | rt_memcpy(uuid_srv.u128.value, gatt_svr_svc_uart_uuid.value, 16); 203 | uint16_t start_handle = bsal_srv_get_start_handle(stack_ptr, uuid_srv); 204 | 205 | rt_kprintf("======== Welcome to enter bluetooth uart mode ========\n"); 206 | rt_kprintf("Press 'ESC' to exit.\n"); 207 | 208 | /* process user input */ 209 | while (ESC_KEY != (ch = bleuart_read())) 210 | { 211 | if(ch != '\r' && ch != '\n') 212 | { 213 | if(ch == BACKSPACE_KEY || ch == DELECT_KEY) 214 | { 215 | if(off) 216 | { 217 | console_buf[off--] = 0; 218 | rt_kprintf("\b \b"); 219 | } 220 | continue; 221 | } 222 | else 223 | { 224 | console_buf[off++] = ch; 225 | rt_kprintf("%c", ch); 226 | continue; 227 | } 228 | } 229 | console_buf[off] = '\0'; 230 | rt_kprintf("\n"); 231 | bsal_srv_send_notify_data(stack_ptr, *conn_id, start_handle, GATT_SVC_NUS_READ_INDEX, off + 1, console_buf); 232 | 233 | off = 0; 234 | } 235 | 236 | bsal_bleuart_deinit(); 237 | } 238 | 239 | 240 | int bsal_bleuart_init(void *stack_ptr, uint16_t *conn_id) 241 | { 242 | int rc; 243 | rt_base_t level; 244 | rt_device_t uart_console; 245 | 246 | /* create buffer for send */ 247 | console_buf = rt_malloc(MYNEWT_VAL_BLEUART_MAX_INPUT); 248 | if (console_buf == RT_NULL) 249 | { 250 | rc = -RT_ENOMEM; 251 | goto __exit; 252 | } 253 | 254 | /* create semaphore for the end of char recived */ 255 | bleuart.rx_end = rt_sem_create("bleuart", 0, RT_IPC_FLAG_FIFO); 256 | if (bleuart.rx_end == RT_NULL) 257 | { 258 | rc = -RT_ENOMEM; 259 | goto __exit; 260 | } 261 | 262 | /* create recived fifo */ 263 | bleuart.rx_fifo = rt_ringbuffer_create(MYNEWT_VAL_BLEUART_MAX_INPUT); 264 | if (bleuart.rx_fifo == RT_NULL) 265 | { 266 | rc = -RT_ENOMEM; 267 | goto __exit; 268 | } 269 | 270 | level = rt_hw_interrupt_disable(); 271 | uart_console = rt_console_get_device(); 272 | if(uart_console) 273 | { 274 | /* back uart console old indicate callback */ 275 | bleuart.old_rx_ind = uart_console->rx_indicate; 276 | rt_device_set_rx_indicate(uart_console, bleuart_rx_ind); 277 | } 278 | rt_hw_interrupt_enable(level); 279 | 280 | /* Reads console and sends data over BLE */ 281 | bsal_bleuart_uart_proc(stack_ptr, conn_id); 282 | 283 | return RT_EOK; 284 | 285 | __exit: 286 | if (console_buf != RT_NULL) 287 | { 288 | rt_free(console_buf); 289 | console_buf = RT_NULL; 290 | } 291 | 292 | if (bleuart.rx_end != RT_NULL) 293 | { 294 | rt_sem_delete(bleuart.rx_end); 295 | bleuart.rx_end = RT_NULL; 296 | } 297 | 298 | if (bleuart.rx_fifo != RT_NULL) 299 | { 300 | rt_ringbuffer_destroy(bleuart.rx_fifo); 301 | bleuart.rx_fifo = RT_NULL; 302 | } 303 | 304 | return rc; 305 | } 306 | 307 | -------------------------------------------------------------------------------- /profiles/service/bsal_uart/bsal_srv_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-09 WaterFishJ the first version 9 | * 2021-09-22 WaterFishJ fix the send bug 10 | */ 11 | 12 | #ifndef __BSAL_SRV_UART_H__ 13 | #define __BSAL_SRV_UART_H__ 14 | 15 | #include 16 | #include 17 | #include "bsal.h" 18 | 19 | 20 | #define GATT_SVC_NUS_READ_INDEX 2 21 | #define GATT_SVC_NUS_WRITE_INDEX 5 22 | #define GATT_SVC_NUS_CHAR_CCCD_INDEX 3 23 | 24 | 25 | 26 | int bsal_bleuart_init(void *stack_ptr, uint16_t *conn_id); 27 | 28 | void bsal_le_uart_svr_init(void *stack_ptr, void *app_callback); 29 | 30 | 31 | 32 | 33 | #endif 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /samples/ble_bas_blufi_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #include "bsal.h" 13 | #include 14 | #include 15 | #include "bsal_osif.h" 16 | #include "bsal_srv_blufi.h" 17 | #include "bsal_srv_bas.h" 18 | 19 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 20 | 21 | static void *bsal_stack_ptr = NULL; 22 | uint16_t bsal_app_conn_handle; 23 | static uint8_t battery_flag = 0; 24 | static uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ 25 | 26 | void bsa_app_set_adv_data(void *stack_ptr) 27 | { 28 | uint8_t tmp_data[32] = {0} ; //must be zero 29 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 30 | 31 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 32 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 33 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 34 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 35 | } 36 | 37 | void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value) 38 | { 39 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 40 | uint8_t bd_addr[6]; 41 | switch (cb_layer) 42 | { 43 | case BSAL_CB_LAYER_GAP: 44 | switch (cb_sub_event) 45 | { 46 | case BSAL_CB_STACK_READY: 47 | //get mac address 48 | 49 | bsal_osif_printf_info("============stack ready===========\r\n"); 50 | bsa_app_set_adv_data(stack_ptr); 51 | bsal_stack_start_adv(stack_ptr); 52 | break; 53 | case BSAL_CB_CONNECT_STATUS: 54 | bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 55 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 56 | { 57 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 58 | } 59 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 60 | { 61 | bsal_stack_start_adv(stack_ptr); 62 | battery_flag = 0; 63 | } 64 | bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x", 65 | 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); 66 | 67 | break; 68 | default: 69 | break; 70 | } 71 | 72 | if (cb_sub_event == BSAL_CB_STACK_READY) 73 | { 74 | //stack ready 75 | // APP_PRINT_INFO0("GAP stack ready"); 76 | 77 | } 78 | 79 | break; 80 | case BSAL_CB_LAYER_GATT_PROFILE: 81 | switch (cb_sub_event) 82 | { 83 | //save the service start_handle 84 | //case uuid profile save start_handle 85 | //case SRV_CALLBACK66 86 | //save the identity 87 | } 88 | break; 89 | case BSAL_CB_LAYER_SM: 90 | break; 91 | case BSAL_CB_LAYER_COMMON: 92 | //connected save the connect id 93 | 94 | break; 95 | case BSAL_CB_LAYER_UNKNOWN: 96 | break; 97 | default: 98 | break; 99 | } 100 | 101 | } 102 | 103 | void bsal_app_profile_callback(void *p) 104 | { 105 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 106 | 107 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 108 | { 109 | bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 110 | } 111 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 112 | { 113 | uint16_t cccbits = bsal_param->value; 114 | 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); 115 | if (bsal_param->srv_uuid.u16.value == BSAL_GATT_SERVICE_BATTERY_SERVICE) 116 | { 117 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 118 | { 119 | 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); 120 | battery_flag = 1; 121 | } 122 | else 123 | { 124 | 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); 125 | battery_flag = 0; 126 | } 127 | } 128 | else if (bsal_param->srv_uuid.u16.value == GATT_UUID_BLUFI_PROFILE) 129 | { 130 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 131 | { 132 | 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); 133 | } 134 | else 135 | { 136 | 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); 137 | } 138 | } 139 | } 140 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 141 | { 142 | bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data); 143 | } 144 | } 145 | 146 | //add the db for 147 | 148 | 149 | void bsal_ble_loop(void *p_param) 150 | { 151 | 152 | uint8_t count = 0; 153 | battery_flag = 1; 154 | while (1) 155 | { 156 | bsal_osif_delay(20000); 157 | bsal_osif_printf_info("====hello world===%d=\r\n", battery_flag); 158 | if (battery_flag == 1) 159 | { 160 | uint8_t battery_level = 90 - count * 10; 161 | count++; 162 | bsal_bas_send_notify_level(bsal_stack_ptr, bsal_app_conn_handle, battery_level); 163 | } 164 | bsal_osif_delay(2000); 165 | } 166 | } 167 | 168 | 169 | int bsal_bas_blufi_app(void) 170 | { 171 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 172 | if (stack_ptr == NULL) 173 | { 174 | //print error; 175 | return 1; 176 | } 177 | //set iocapability 178 | 179 | 180 | bsal_stack_ptr = stack_ptr; 181 | //1. init stack 182 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 183 | // set device name 184 | char *device_name = "ble_rtt"; 185 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 186 | //2. bond type 187 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 188 | //set the bond flag: 189 | 190 | //3. service begin 191 | bsal_stack_le_srv_begin(stack_ptr, 2, bsal_app_profile_callback); //will add 1 service 192 | //4. bas_init 193 | bsal_le_bas_svr_init(stack_ptr, bsal_app_profile_callback); //add battery servcie 194 | 195 | //5. blufi_init 196 | bsal_le_blufi_svr_init(stack_ptr, bsal_app_profile_callback); 197 | 198 | //6. srv_end 199 | bsal_stack_le_srv_end(stack_ptr); //end srv add 200 | 201 | //start stack 202 | bsal_stack_startup(stack_ptr); //start she 203 | 204 | return 0; 205 | } 206 | MSH_CMD_EXPORT_ALIAS(bsal_bas_blufi_app, bsal_bas_blufi_app, "bluetoooth blufi and bas sample"); 207 | 208 | 209 | 210 | 211 | 212 | //CMD 213 | 214 | 215 | -------------------------------------------------------------------------------- /samples/ble_bas_only_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2020, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-28 Supperthomas the first version 9 | */ 10 | 11 | 12 | #include "bsal.h" 13 | #include 14 | #include 15 | #include "bsal_osif.h" 16 | #include "bsal_srv_bas.h" 17 | #include 18 | #define DBG_TAG "BSAL" 19 | #define DBG_LVL DBG_LOG 20 | 21 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 22 | 23 | static void *bsal_stack_ptr = NULL; 24 | uint16_t bsal_app_conn_handle; 25 | static uint8_t battery_flag = 0; 26 | static uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ 27 | 28 | uint16_t battery_start_handle = 0; 29 | void bsa_app_set_adv_data(void *stack_ptr) 30 | { 31 | uint8_t tmp_data[32] = {0} ; //must be zero 32 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 33 | 34 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 35 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 36 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 37 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 38 | } 39 | 40 | void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length , void *value) 41 | { 42 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 43 | switch (cb_layer) 44 | { 45 | case BSAL_CB_LAYER_GAP: 46 | switch (cb_sub_event) 47 | { 48 | case BSAL_CB_STACK_READY: 49 | LOG_I("BSAL STACK READY"); 50 | 51 | bsa_app_set_adv_data(stack_ptr); 52 | 53 | bsal_stack_start_adv(stack_ptr); 54 | break; 55 | case BSAL_CB_CONNECT_STATUS: 56 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 57 | { 58 | LOG_I("REMOTE DEVICE CONNECT ID %d STATUS CONNECTED READY\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 59 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 60 | } 61 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 62 | { 63 | LOG_I("REMOTE DEVICE CONNECT ID %d STATUS DISCONNECT READY\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 64 | 65 | bsal_stack_start_adv(stack_ptr); 66 | battery_flag = 0; 67 | } 68 | bsal_osif_printf_info("conn_id %d old_state %d new_state %d, disc_cause 0x%x", 69 | 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); 70 | 71 | break; 72 | default: 73 | break; 74 | } 75 | 76 | break; 77 | case BSAL_CB_LAYER_GATT_PROFILE: 78 | switch (cb_sub_event) 79 | { 80 | //save the service start_handle 81 | //case uuid profile save start_handle 82 | //case SRV_CALLBACK66 83 | //save the identity 84 | } 85 | break; 86 | case BSAL_CB_LAYER_SM: 87 | break; 88 | case BSAL_CB_LAYER_COMMON: 89 | //connected save the connect id 90 | 91 | break; 92 | case BSAL_CB_LAYER_UNKNOWN: 93 | break; 94 | default: 95 | break; 96 | } 97 | 98 | } 99 | 100 | 101 | 102 | 103 | void bsal_app_profile_callback(void *p) 104 | { 105 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 106 | 107 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 108 | { 109 | LOG_I("GATT:READ CHAR VALUE OFF_HANDLE %x UUID:%x\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 110 | } 111 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 112 | { 113 | uint16_t cccbits = (uint16_t)bsal_param->value; 114 | LOG_I("GATT: NOTIFY HANDLE %x cccd %x UUID:%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value); 115 | 116 | if (bsal_param->srv_uuid.u16.value == BSAL_GATT_SERVICE_BATTERY_SERVICE) 117 | { 118 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 119 | { 120 | LOG_I("NOTIFY ENABLE from %x data cccd %x UUID:%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value); 121 | battery_flag = 1; 122 | } 123 | else 124 | { 125 | LOG_I("NOTIFY DISABLE from %x data cccd %x UUID%x\r\n", bsal_param->off_handle, cccbits, bsal_param->srv_uuid.u16.value); 126 | battery_flag = 0; 127 | } 128 | } 129 | } 130 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 131 | { 132 | LOG_I("\r\n Recv THE DATA IS :%s\r\n", bsal_param->data); 133 | } 134 | } 135 | 136 | //add the db for 137 | 138 | 139 | void bsal_ble_loop(void *p_param) 140 | { 141 | 142 | uint8_t count = 0; 143 | while (1) 144 | { 145 | bsal_osif_delay(2000); 146 | if (battery_flag == 1) 147 | { 148 | uint8_t battery_level = 90 - count * 10; 149 | count++; 150 | if (battery_level <= 0) 151 | { 152 | count = 0; 153 | } 154 | bsal_bas_send_notify_level(bsal_stack_ptr, bsal_app_conn_handle, battery_level); 155 | } 156 | } 157 | } 158 | 159 | 160 | int bsal_bas_app(void) 161 | { 162 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 163 | void *bsal_test_app_task; 164 | if (stack_ptr == NULL) 165 | { 166 | //print error; 167 | return 1; 168 | } 169 | //set iocapability 170 | 171 | 172 | bsal_stack_ptr = stack_ptr; 173 | 174 | //1. stack init 175 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 176 | char *device_name = "ble_rtt"; 177 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 178 | //2. set bond type 179 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 180 | //set the bond flag: 181 | //3. start add profile service 182 | bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service 183 | 184 | //4. add profile service 185 | bsal_le_bas_svr_init(stack_ptr, bsal_app_profile_callback); //add battery servcie 186 | 187 | //5. end add profile service 188 | bsal_stack_le_srv_end(stack_ptr); //end srv add 189 | 190 | //6. start ble stack 191 | bsal_stack_startup(stack_ptr); //start she 192 | 193 | //bsal_ble_loop(NULL); 194 | 195 | bsal_test_app_task = rt_thread_create("bsal_app", bsal_ble_loop, NULL, 2 * 256, 5, 10); 196 | if (bsal_test_app_task != RT_NULL) 197 | { 198 | 199 | rt_thread_startup(bsal_test_app_task); 200 | } 201 | return 0; 202 | } 203 | MSH_CMD_EXPORT_ALIAS(bsal_bas_app, bsal_bas_app, "bluetoooth battery service sample"); 204 | 205 | 206 | 207 | 208 | //CMD 209 | 210 | -------------------------------------------------------------------------------- /samples/ble_hogp_app.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #include "bsal.h" 7 | #include 8 | #include 9 | #include "bsal_osif.h" 10 | #include "bsal_srv_hid.h" 11 | #include "bsal_srv_dis.h" 12 | 13 | 14 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 15 | 16 | static void *bsal_stack_ptr = NULL; 17 | static uint16_t bsal_app_conn_handle; 18 | static rt_uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_CONNECTED; 19 | 20 | static void bsa_app_set_adv_data(void *stack_ptr) 21 | { 22 | uint8_t tmp_data[32] = {0} ; //must be zero 23 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 24 | 25 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 26 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 27 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 28 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 29 | } 30 | 31 | static void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length, void *value) 32 | { 33 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 34 | uint8_t bd_addr[6]; 35 | switch (cb_layer) 36 | { 37 | case BSAL_CB_LAYER_GAP: 38 | switch (cb_sub_event) 39 | { 40 | case BSAL_CB_STACK_READY: 41 | //get mac address 42 | 43 | bsal_osif_printf_info("============stack ready===========\r\n"); 44 | bsa_app_set_adv_data(stack_ptr); 45 | bsal_stack_start_adv(stack_ptr); 46 | break; 47 | case BSAL_CB_CONNECT_STATUS: 48 | bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 49 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 50 | { 51 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 52 | } 53 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 54 | { 55 | bsal_stack_start_adv(stack_ptr); 56 | } 57 | bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x", 58 | 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); 59 | 60 | break; 61 | default: 62 | break; 63 | } 64 | 65 | if (cb_sub_event == BSAL_CB_STACK_READY) 66 | { 67 | //stack ready 68 | } 69 | 70 | break; 71 | case BSAL_CB_LAYER_GATT_PROFILE: 72 | switch (cb_sub_event) 73 | { 74 | //save the service start_handle 75 | //case uuid profile save start_handle 76 | //case SRV_CALLBACK66 77 | //save the identity 78 | } 79 | break; 80 | case BSAL_CB_LAYER_SM: 81 | break; 82 | case BSAL_CB_LAYER_COMMON: 83 | //connected save the connect id 84 | 85 | break; 86 | case BSAL_CB_LAYER_UNKNOWN: 87 | break; 88 | default: 89 | break; 90 | } 91 | 92 | } 93 | 94 | static void bsal_app_profile_callback(void *p) 95 | { 96 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 97 | 98 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 99 | { 100 | bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 101 | } 102 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 103 | { 104 | uint16_t cccbits = bsal_param->value; 105 | 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); 106 | // if (nus_is_uuid(&(bsal_param->srv_uuid), BSAL_UUID128_DECLARE(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 107 | // 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e)))//uart_uuid 108 | // { 109 | // if (cccbits & BSAL_GATT_CCC_NOTIFY) 110 | // { 111 | // 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); 112 | // } 113 | // else 114 | // { 115 | // 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); 116 | // } 117 | // } 118 | } 119 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 120 | { 121 | bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data); 122 | } 123 | } 124 | 125 | int bsal_hogp_app(void) 126 | { 127 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 128 | if (stack_ptr == NULL) 129 | { 130 | //print error; 131 | return 1; 132 | } 133 | //set iocapability 134 | 135 | 136 | bsal_stack_ptr = stack_ptr; 137 | //1. init stack 138 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 139 | // set device name 140 | char *device_name = "ble_rtt_hogp"; 141 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 142 | //2. bond type 143 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 144 | //set the bond flag: 145 | 146 | //3. service begin 147 | bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service 148 | 149 | //4. uart init 150 | bsal_le_hid_svr_init(stack_ptr, bsal_app_profile_callback); 151 | 152 | 153 | // bsal_le_dis_svr_init(stack_ptr, bsal_app_profile_callback); 154 | 155 | //5. srv_end 156 | bsal_stack_le_srv_end(stack_ptr); //end srv add 157 | 158 | //6. start stack 159 | bsal_stack_startup(stack_ptr); //start she 160 | 161 | // bsal_bleuart_init(stack_ptr, &bsal_app_conn_handle); 162 | 163 | return 0; 164 | } 165 | MSH_CMD_EXPORT_ALIAS(bsal_hogp_app, bsal_hogp_app, "bluetoooth hogp sample"); 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /samples/ble_hrs_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-10 WaterFishJ the first version 9 | */ 10 | 11 | 12 | #include "bsal.h" 13 | #include 14 | #include 15 | #include "bsal_osif.h" 16 | #include "bsal_srv_hrs.h" 17 | 18 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 19 | 20 | static void *bsal_stack_ptr = NULL; 21 | static uint16_t bsal_app_conn_handle; 22 | static uint8_t heart_rate_flag = 0; 23 | static rt_uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_CONNECTED; 24 | 25 | static void bsa_app_set_adv_data(void *stack_ptr) 26 | { 27 | uint8_t tmp_data[32] = {0} ; //must be zero 28 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 29 | 30 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 31 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 32 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 33 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 34 | } 35 | 36 | static void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length, void *value) 37 | { 38 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 39 | uint8_t bd_addr[6]; 40 | switch (cb_layer) 41 | { 42 | case BSAL_CB_LAYER_GAP: 43 | switch (cb_sub_event) 44 | { 45 | case BSAL_CB_STACK_READY: 46 | //get mac address 47 | 48 | bsal_osif_printf_info("============stack ready===========\r\n"); 49 | bsa_app_set_adv_data(stack_ptr); 50 | bsal_stack_start_adv(stack_ptr); 51 | break; 52 | case BSAL_CB_CONNECT_STATUS: 53 | bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 54 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 55 | { 56 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 57 | } 58 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 59 | { 60 | bsal_stack_start_adv(stack_ptr); 61 | heart_rate_flag = 0; 62 | } 63 | bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x", 64 | 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); 65 | 66 | break; 67 | default: 68 | break; 69 | } 70 | 71 | if (cb_sub_event == BSAL_CB_STACK_READY) 72 | { 73 | //stack ready 74 | } 75 | 76 | break; 77 | case BSAL_CB_LAYER_GATT_PROFILE: 78 | switch (cb_sub_event) 79 | { 80 | //save the service start_handle 81 | //case uuid profile save start_handle 82 | //case SRV_CALLBACK66 83 | //save the identity 84 | } 85 | break; 86 | case BSAL_CB_LAYER_SM: 87 | break; 88 | case BSAL_CB_LAYER_COMMON: 89 | //connected save the connect id 90 | 91 | break; 92 | case BSAL_CB_LAYER_UNKNOWN: 93 | break; 94 | default: 95 | break; 96 | } 97 | 98 | } 99 | 100 | static void bsal_app_profile_callback(void *p) 101 | { 102 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 103 | 104 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 105 | { 106 | bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 107 | } 108 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 109 | { 110 | uint16_t cccbits = bsal_param->value; 111 | 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); 112 | if (bsal_param->srv_uuid.u16.value == GATT_UUID_HEART_RATE)//heart_rate_uuid 113 | { 114 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 115 | { 116 | 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); 117 | heart_rate_flag = 1; 118 | } 119 | else 120 | { 121 | 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); 122 | heart_rate_flag = 0; 123 | } 124 | } 125 | } 126 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 127 | { 128 | bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data); 129 | } 130 | } 131 | 132 | static void bsal_ble_loop(void *p_param) 133 | { 134 | static uint8_t hrm[2]; 135 | hrm[0] = 0x06; 136 | 137 | uint8_t heart_rate = 90; 138 | while (1) 139 | { 140 | bsal_osif_delay(1000); 141 | bsal_osif_printf_info("====hello world===%d=\r\n", heart_rate_flag); 142 | if (heart_rate_flag == 1) 143 | { 144 | if (heart_rate <= 120) 145 | { 146 | heart_rate++; 147 | } 148 | else 149 | { 150 | heart_rate = 90; 151 | } 152 | hrm[1] = heart_rate; 153 | bsal_hrs_send_notify_level(bsal_stack_ptr, bsal_app_conn_handle, hrm); 154 | } 155 | } 156 | } 157 | 158 | int bsal_hrs_app(void) 159 | { 160 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 161 | if (stack_ptr == NULL) 162 | { 163 | //print error; 164 | return 1; 165 | } 166 | //set iocapability 167 | 168 | bsal_stack_ptr = stack_ptr; 169 | //1. init stack 170 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 171 | // set device name 172 | char *device_name = "ble_rtt_hrs"; 173 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 174 | //2. bond type 175 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 176 | //set the bond flag: 177 | 178 | //3. service begin 179 | bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service 180 | //4. bas_init 181 | bsal_le_hrs_svr_init(stack_ptr, bsal_app_profile_callback); //add battery servcie 182 | 183 | //5. srv_end 184 | bsal_stack_le_srv_end(stack_ptr); //end srv add 185 | 186 | //start stack 187 | bsal_stack_startup(stack_ptr); //start she 188 | 189 | bsal_ble_loop(stack_ptr); 190 | 191 | return 0; 192 | } 193 | MSH_CMD_EXPORT_ALIAS(bsal_hrs_app, bsal_hrs_app, "bluetoooth heart rate sample"); 194 | 195 | -------------------------------------------------------------------------------- /samples/ble_lbs_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-27 WaterFishJ the first version 9 | */ 10 | 11 | #include "bsal.h" 12 | #include 13 | #include 14 | #include "bsal_osif.h" 15 | #include "bsal_srv_lbs.h" 16 | 17 | 18 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 19 | 20 | static void *bsal_stack_ptr = NULL; 21 | static uint16_t bsal_app_conn_handle; 22 | static rt_uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_CONNECTED; 23 | static rt_uint8_t button_cccd_flag; 24 | 25 | static void bsa_app_set_adv_data(void *stack_ptr) 26 | { 27 | uint8_t tmp_data[32] = {0} ; //must be zero 28 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 29 | 30 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 31 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 32 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 33 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 34 | } 35 | 36 | static void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length, void *value) 37 | { 38 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 39 | uint8_t bd_addr[6]; 40 | switch (cb_layer) 41 | { 42 | case BSAL_CB_LAYER_GAP: 43 | switch (cb_sub_event) 44 | { 45 | case BSAL_CB_STACK_READY: 46 | //get mac address 47 | 48 | bsal_osif_printf_info("============stack ready===========\r\n"); 49 | bsa_app_set_adv_data(stack_ptr); 50 | bsal_stack_start_adv(stack_ptr); 51 | break; 52 | case BSAL_CB_CONNECT_STATUS: 53 | bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 54 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 55 | { 56 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 57 | } 58 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 59 | { 60 | bsal_stack_start_adv(stack_ptr); 61 | } 62 | bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x", 63 | 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); 64 | 65 | break; 66 | default: 67 | break; 68 | } 69 | 70 | if (cb_sub_event == BSAL_CB_STACK_READY) 71 | { 72 | //stack ready 73 | } 74 | 75 | break; 76 | case BSAL_CB_LAYER_GATT_PROFILE: 77 | switch (cb_sub_event) 78 | { 79 | //save the service start_handle 80 | //case uuid profile save start_handle 81 | //case SRV_CALLBACK66 82 | //save the identity 83 | } 84 | break; 85 | case BSAL_CB_LAYER_SM: 86 | break; 87 | case BSAL_CB_LAYER_COMMON: 88 | //connected save the connect id 89 | 90 | break; 91 | case BSAL_CB_LAYER_UNKNOWN: 92 | break; 93 | default: 94 | break; 95 | } 96 | 97 | } 98 | 99 | bool lbs_is_uuid(bsal_uuid_any_t *s, bsal_uuid_any_t *u) 100 | { 101 | if (s->u_type == u->u_type) 102 | { 103 | switch (s->u_type) 104 | { 105 | case BSAL_UUID_TYPE_128BIT: 106 | for (rt_uint8_t i = 0; i < 16; i++) 107 | { 108 | if (s->u128.value[i] != u->u128.value[i]) return false; 109 | } 110 | return true; 111 | case BSAL_UUID_TYPE_16BIT: 112 | break; 113 | case BSAL_UUID_TYPE_32BIT: 114 | break; 115 | default: 116 | return false; 117 | } 118 | } 119 | else return false; 120 | } 121 | 122 | static void bsal_app_profile_callback(void *p) 123 | { 124 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 125 | 126 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 127 | { 128 | bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 129 | } 130 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 131 | { 132 | uint16_t cccbits = bsal_param->value; 133 | 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); 134 | if (lbs_is_uuid(&(bsal_param->srv_uuid), BSAL_UUID128_DECLARE(0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 135 | 0xDE, 0xEF, 0x12, 0x12, 0x23, 0x15, 0x00, 0x00)))//lbs_uuid 136 | { 137 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 138 | { 139 | 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); 140 | } 141 | else 142 | { 143 | 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); 144 | } 145 | } 146 | } 147 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 148 | { 149 | bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data); 150 | } 151 | } 152 | 153 | rt_sem_t button_sem = 0; 154 | void button_irq(void *p) 155 | { 156 | rt_sem_release(p); 157 | } 158 | 159 | void bsal_lbs_loop(void *p) 160 | { 161 | button_sem = rt_sem_create("button", 0, RT_IPC_FLAG_FIFO); 162 | 163 | rt_pin_mode(BUTTON_PIN, PIN_MODE_INPUT_PULLUP); 164 | rt_pin_attach_irq(BUTTON_PIN, PIN_IRQ_MODE_RISING_FALLING, button_irq, button_sem); 165 | rt_pin_irq_enable(BUTTON_PIN, PIN_IRQ_ENABLE); 166 | 167 | rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); 168 | rt_pin_write(LED_PIN, PIN_HIGH); 169 | 170 | uint8_t flag = 0; 171 | 172 | while (1) 173 | { 174 | rt_sem_take(button_sem, RT_WAITING_FOREVER); 175 | if (button_cccd_flag) 176 | { 177 | flag = !rt_pin_read(BUTTON_PIN); 178 | bsal_lbs_send_notify_button(p, bsal_app_conn_handle, flag); 179 | } 180 | } 181 | } 182 | 183 | int bsal_lbs_app(void) 184 | { 185 | void *bsal_test_app_task = RT_NULL; 186 | 187 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 188 | if (stack_ptr == NULL) 189 | { 190 | //print error; 191 | return 1; 192 | } 193 | //set iocapability 194 | 195 | bsal_stack_ptr = stack_ptr; 196 | //1. init stack 197 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 198 | // set device name 199 | char *device_name = "ble_rtt_lbs"; 200 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 201 | //2. bond type 202 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 203 | //set the bond flag: 204 | 205 | //3. service begin 206 | bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service 207 | 208 | //4. lbs init 209 | bsal_le_lbs_svr_init(stack_ptr, bsal_app_profile_callback, &button_cccd_flag); 210 | 211 | //5. srv_end 212 | bsal_stack_le_srv_end(stack_ptr); //end srv add 213 | 214 | //6. start stack 215 | bsal_stack_startup(stack_ptr); //start she 216 | 217 | bsal_test_app_task = rt_thread_create("lbs_task", bsal_lbs_loop, stack_ptr, 2 * 256, 5, 10); 218 | if (bsal_test_app_task != RT_NULL) 219 | { 220 | rt_thread_startup(bsal_test_app_task); 221 | } 222 | return 0; 223 | } 224 | MSH_CMD_EXPORT_ALIAS(bsal_lbs_app, bsal_lbs_app, "bluetoooth LED Button sample"); 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /samples/ble_nus_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2021, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2021-09-09 WaterFishJ the first version 9 | * 2021-09-22 WaterFishJ fix the send bug 10 | */ 11 | 12 | 13 | #include "bsal.h" 14 | #include 15 | #include 16 | #include "bsal_osif.h" 17 | #include "bsal_srv_uart.h" 18 | 19 | #define BSAL_STACK_NAME PKG_BSAL_STACK_NAME 20 | 21 | static void *bsal_stack_ptr = NULL; 22 | static uint16_t bsal_app_conn_handle; 23 | rt_uint8_t gap_conn_state = BSAL_GAP_CONN_STATE_CONNECTED; 24 | 25 | static void bsa_app_set_adv_data(void *stack_ptr) 26 | { 27 | uint8_t tmp_data[32] = {0} ; //must be zero 28 | bsal_le_adv_data_add_flag(tmp_data, BSAL_GAP_ADTYPE_FLAGS_LIMITED | BSAL_GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED); 29 | 30 | char *adv_name = (char *)bsal_get_device_name(stack_ptr); 31 | bsal_adv_data_add_name(tmp_data, strlen(adv_name), adv_name); 32 | //bsal_adv_data_add_uuid16(tmp_data, BSAL_GATT_SERVICE_BATTERY_SERVICE); 33 | bsal_set_le_adv_data_user(stack_ptr, tmp_data); 34 | } 35 | 36 | static void bsal_app_all_callback(void *stack_ptr, uint8_t cb_layer, uint16_t cb_sub_event, uint8_t value_length, void *value) 37 | { 38 | T_BSAL_GAP_MSG_DATA *bsal_gap_msg_data = (T_BSAL_GAP_MSG_DATA *)value; 39 | uint8_t bd_addr[6]; 40 | switch (cb_layer) 41 | { 42 | case BSAL_CB_LAYER_GAP: 43 | switch (cb_sub_event) 44 | { 45 | case BSAL_CB_STACK_READY: 46 | //get mac address 47 | 48 | bsal_osif_printf_info("============stack ready===========\r\n"); 49 | bsa_app_set_adv_data(stack_ptr); 50 | bsal_stack_start_adv(stack_ptr); 51 | break; 52 | case BSAL_CB_CONNECT_STATUS: 53 | bsal_osif_printf_info("============stack connect id %d===========\r\n", bsal_gap_msg_data->gap_conn_state_change.conn_id); 54 | if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_CONNECTED) 55 | { 56 | bsal_app_conn_handle = bsal_gap_msg_data->gap_conn_state_change.conn_id; 57 | } 58 | else if (bsal_gap_msg_data->gap_conn_state_change.new_state == BSAL_GAP_CONN_STATE_DISCONNECTED) 59 | { 60 | bsal_stack_start_adv(stack_ptr); 61 | } 62 | bsal_osif_printf_info("BSAL: conn_id %d old_state %d new_state %d, disc_cause 0x%x", 63 | 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); 64 | 65 | break; 66 | default: 67 | break; 68 | } 69 | 70 | if (cb_sub_event == BSAL_CB_STACK_READY) 71 | { 72 | //stack ready 73 | } 74 | 75 | break; 76 | case BSAL_CB_LAYER_GATT_PROFILE: 77 | switch (cb_sub_event) 78 | { 79 | //save the service start_handle 80 | //case uuid profile save start_handle 81 | //case SRV_CALLBACK66 82 | //save the identity 83 | } 84 | break; 85 | case BSAL_CB_LAYER_SM: 86 | break; 87 | case BSAL_CB_LAYER_COMMON: 88 | //connected save the connect id 89 | 90 | break; 91 | case BSAL_CB_LAYER_UNKNOWN: 92 | break; 93 | default: 94 | break; 95 | } 96 | 97 | } 98 | 99 | bool nus_is_uuid(bsal_uuid_any_t *s, bsal_uuid_any_t *u) 100 | { 101 | if (s->u_type == u->u_type) 102 | { 103 | switch (s->u_type) 104 | { 105 | case BSAL_UUID_TYPE_128BIT: 106 | for (rt_uint8_t i = 0; i < 16; i++) 107 | { 108 | if (s->u128.value[i] != u->u128.value[i]) return false; 109 | } 110 | return true; 111 | case BSAL_UUID_TYPE_16BIT: 112 | break; 113 | case BSAL_UUID_TYPE_32BIT: 114 | break; 115 | default: 116 | return false; 117 | } 118 | } 119 | else return false; 120 | } 121 | 122 | static void bsal_app_profile_callback(void *p) 123 | { 124 | bsal_callbak_data_t *bsal_param = (bsal_callbak_data_t *)p; 125 | 126 | if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_READ_CHAR_VALUE) 127 | { 128 | bsal_osif_printf_info("========callback read from %x====%x=======\r\n", bsal_param->off_handle, bsal_param->srv_uuid.u16.value); 129 | } 130 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) 131 | { 132 | uint16_t cccbits = bsal_param->value; 133 | 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); 134 | if (nus_is_uuid(&(bsal_param->srv_uuid), BSAL_UUID128_DECLARE(0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 135 | 0x93, 0xf3, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e)))//uart_uuid 136 | { 137 | if (cccbits & BSAL_GATT_CCC_NOTIFY) 138 | { 139 | 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); 140 | } 141 | else 142 | { 143 | 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); 144 | } 145 | } 146 | } 147 | else if (bsal_param->msg_type == BSAL_CALLBACK_TYPE_WRITE_CHAR_VALUE) 148 | { 149 | bsal_osif_printf_info("\r\n BSAL: THE DATA IS :%s\r\n", bsal_param->data); 150 | } 151 | } 152 | 153 | int bsal_nus_app(void) 154 | { 155 | void *stack_ptr = bsal_find_stack_ptr(BSAL_STACK_NAME); 156 | if (stack_ptr == NULL) 157 | { 158 | //print error; 159 | return 1; 160 | } 161 | //set iocapability 162 | 163 | 164 | bsal_stack_ptr = stack_ptr; 165 | //1. init stack 166 | bsal_stack_init(stack_ptr, bsal_app_all_callback); // init param not start stack 167 | // set device name 168 | char *device_name = "ble_rtt_uart"; 169 | bsal_set_device_name(stack_ptr, strlen(device_name), (uint8_t *)device_name); 170 | //2. bond type 171 | bsal_set_device_le_bond_type(stack_ptr, false, BSAL_NO_INPUT, BSAL_NO_OUTPUT, BSAL_GAP_AUTHEN_BIT_NO_BONDING, false); 172 | //set the bond flag: 173 | 174 | //3. service begin 175 | bsal_stack_le_srv_begin(stack_ptr, 1, bsal_app_profile_callback); //will add 1 service 176 | 177 | //4. uart init 178 | bsal_le_uart_svr_init(stack_ptr, bsal_app_profile_callback); 179 | 180 | //5. srv_end 181 | bsal_stack_le_srv_end(stack_ptr); //end srv add 182 | 183 | //6. start stack 184 | bsal_stack_startup(stack_ptr); //start she 185 | 186 | bsal_bleuart_init(stack_ptr, &bsal_app_conn_handle); 187 | 188 | return 0; 189 | } 190 | MSH_CMD_EXPORT_ALIAS(bsal_nus_app, bsal_nus_app, "bluetoooth uart sample"); 191 | 192 | 193 | 194 | 195 | 196 | 197 | --------------------------------------------------------------------------------