├── .gitignore ├── Doxyfile ├── LICENSE ├── Makefile ├── README.md ├── dfu ├── README.md ├── gl-efr32mg21f512-ble-ncp-v4_2_0.gbl └── gl-efr32mg21f768-ble-ncp-v4_2_0.gbl ├── files ├── etc │ ├── ble │ │ ├── gl-efr32mg21f768-ble-ncp-v4_2_0.gbl │ │ └── gl_gattdb_cfg.json │ ├── config │ │ └── ble │ └── uci-defaults │ │ └── 30-ble-model-config └── usr │ └── bin │ └── gl-ble-dfu ├── src ├── CMakeLists.txt ├── bledriver │ ├── silabs │ │ ├── silabs_bleapi.c │ │ ├── silabs_bleapi.h │ │ ├── silabs_evt.c │ │ ├── silabs_evt.h │ │ ├── silabs_msg.c │ │ ├── silabs_msg.h │ │ ├── sl_bgapi.h │ │ ├── sl_bt_api.h │ │ ├── sl_bt_api_compatibility.h │ │ ├── sl_bt_ncp_host_api.c │ │ ├── sl_bt_types.h │ │ ├── sl_bt_version.h │ │ ├── sl_status.h │ │ ├── sli_bt_api.h │ │ └── sli_bt_gattdb_def.h │ └── util │ │ ├── gl_common.c │ │ ├── gl_common.h │ │ ├── gl_hal.c │ │ ├── gl_hal.h │ │ ├── gl_methods.h │ │ ├── gl_uart.c │ │ └── gl_uart.h ├── components │ ├── dev_mgr │ │ ├── gl_dev_mgr.c │ │ └── gl_dev_mgr.h │ ├── evt_msg_queue │ │ ├── evt_queue.c │ │ └── evt_queue.h │ ├── log │ │ ├── gl_log.c │ │ └── gl_log.h │ ├── thread │ │ ├── gl_thread.c │ │ └── gl_thread.h │ └── timestamp │ │ ├── timestamp.c │ │ └── timestamp.h ├── example │ ├── bleAdvExtended │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── demo_bleAdvExtended.c │ │ └── docs │ │ │ └── DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png │ ├── bleAdvLegacy │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── demo_bleAdvLegacy.c │ │ └── docs │ │ │ ├── 1.jpg │ │ │ └── 2.jpg │ ├── bleAdvPeriodic │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── demo_bleAdvPeriodic.c │ │ └── docs │ │ │ └── DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png │ ├── bleClient │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── demo_bleClient.c │ ├── bleIbeacon │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── demo_bleIbeacon.c │ │ ├── ibeacon.c │ │ ├── ibeacon.h │ │ ├── run_mode.c │ │ ├── run_mode.h │ │ ├── ubus.c │ │ ├── ubus.h │ │ ├── util.c │ │ └── util.h │ ├── bleScanner │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── demo_bleScanner.c │ ├── bleService │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── demo_bleService.c │ ├── bleSynchronize │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── demo_bleSynchronize.c │ └── bletool │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ └── demo_bletool.c └── lib │ ├── CMakeLists.txt │ ├── gl_bleapi.c │ └── include │ ├── gl_bleapi.h │ ├── gl_errno.h │ └── gl_type.h └── version.mk /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | docs/html 3 | docs/latex -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | # Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | #################################################################### 16 | include $(TOPDIR)/rules.mk 17 | include version.mk 18 | 19 | PKG_NAME:=gl-ble-sdk 20 | PKG_VERSION:=$(strip $(call findrev)) 21 | PKG_RELEASE:=2 22 | 23 | TARGET_CFLAGS += -ggdb3 24 | 25 | 26 | include $(INCLUDE_DIR)/package.mk 27 | include $(INCLUDE_DIR)/cmake.mk 28 | 29 | define Package/libglble 30 | SECTION:=base 31 | CATEGORY:=gl-inet-ble 32 | TITLE:=GL inet BLE driver library 33 | DEPENDS:= +libuci +libpthread +lrzsz +@BUSYBOX_CUSTOM +@BUSYBOX_CONFIG_STTY 34 | endef 35 | 36 | define Package/gl-bleScanner 37 | SECTION:=base 38 | CATEGORY:=gl-inet-ble 39 | TITLE:=GL inet BLE Scanner 40 | DEPENDS:= +libjson-c +libglble 41 | endef 42 | 43 | define Package/gl-bleSynchronize 44 | SECTION:=base 45 | CATEGORY:=gl-inet-ble 46 | TITLE:=GL inet BLE Synchronize 47 | DEPENDS:= +libjson-c +libglble 48 | endef 49 | 50 | define Package/gl-bleAdvLegacy 51 | SECTION:=base 52 | CATEGORY:=gl-inet-ble 53 | TITLE:=GL inet BLE Legacy Advertising 54 | DEPENDS:= +libjson-c +libglble 55 | endef 56 | 57 | define Package/gl-bleAdvExtended 58 | SECTION:=base 59 | CATEGORY:=gl-inet-ble 60 | TITLE:=GL inet BLE Extended Advertising 61 | DEPENDS:= +libjson-c +libglble 62 | endef 63 | 64 | define Package/gl-bleAdvPeriodic 65 | SECTION:=base 66 | CATEGORY:=gl-inet-ble 67 | TITLE:=GL inet BLE Periodic Advertising 68 | DEPENDS:= +libjson-c +libglble 69 | endef 70 | 71 | define Package/gl-bleClient 72 | SECTION:=base 73 | CATEGORY:=gl-inet-ble 74 | TITLE:=GL inet BLE Client 75 | DEPENDS:= +libjson-c +libglble 76 | endef 77 | 78 | define Package/gl-bleService 79 | SECTION:=base 80 | CATEGORY:=gl-inet-ble 81 | TITLE:=GL inet BLE Service 82 | DEPENDS:= +libjson-c +libglble 83 | endef 84 | 85 | define Package/gl-bletool 86 | SECTION:=base 87 | CATEGORY:=gl-inet-ble 88 | TITLE:=GL inet BLE Debug Cmdline Tool 89 | DEPENDS:= +libjson-c +libreadline +libncurses +libglble 90 | endef 91 | 92 | define Package/gl-bleIbeacon 93 | SECTION:=base 94 | CATEGORY:=gl-inet-ble 95 | TITLE:=GL inet BLE Ibeacon 96 | DEPENDS:= +libjson-c +libglble +libubox +libubus +libblobmsg-json 97 | endef 98 | 99 | define Build/Prepare 100 | mkdir -p $(PKG_BUILD_DIR) 101 | $(CP) ./src/* $(PKG_BUILD_DIR)/ 102 | endef 103 | 104 | define Build/InstallDev 105 | $(INSTALL_DIR) $(1)/usr/include 106 | $(CP) $(PKG_BUILD_DIR)/lib/include/*.h $(1)/usr/include/ 107 | $(INSTALL_DIR) $(1)/usr/lib 108 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/lib/libglbleapi.* $(1)/usr/lib/ 109 | endef 110 | 111 | define Package/libglble/install 112 | $(INSTALL_DIR) $(1)/usr/include 113 | $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include 114 | $(INSTALL_DIR) $(1)/usr/lib/gl 115 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/gl 116 | $(LN) /usr/lib/gl/libglbleapi.so $(1)/usr/lib/ 117 | $(INSTALL_DIR) $(1)/etc/uci-defaults 118 | $(INSTALL_BIN) files/etc/uci-defaults/30-ble-model-config $(1)/etc/uci-defaults/30-ble-model-config 119 | $(INSTALL_DIR) $(1)/etc/config 120 | $(INSTALL_BIN) files/etc/config/ble $(1)/etc/config/ble 121 | 122 | $(INSTALL_DIR) $(1)/usr/bin 123 | $(INSTALL_BIN) files/usr/bin/* $(1)/usr/bin/ 124 | 125 | $(INSTALL_DIR) $(1)/etc/ble 126 | $(CP) files/etc/ble/* $(1)/etc/ble 127 | endef 128 | 129 | define Package/gl-bleScanner/install 130 | $(INSTALL_DIR) $(1)/usr/sbin 131 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleScanner $(1)/usr/sbin/ 132 | endef 133 | 134 | define Package/gl-bleSynchronize/install 135 | $(INSTALL_DIR) $(1)/usr/sbin 136 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleSynchronize $(1)/usr/sbin/ 137 | endef 138 | 139 | define Package/gl-bleAdvLegacy/install 140 | $(INSTALL_DIR) $(1)/usr/sbin 141 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleAdvLegacy $(1)/usr/sbin/ 142 | endef 143 | 144 | define Package/gl-bleAdvExtended/install 145 | $(INSTALL_DIR) $(1)/usr/sbin 146 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleAdvExtended $(1)/usr/sbin/ 147 | endef 148 | 149 | define Package/gl-bleAdvPeriodic/install 150 | $(INSTALL_DIR) $(1)/usr/sbin 151 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleAdvPeriodic $(1)/usr/sbin/ 152 | endef 153 | 154 | define Package/gl-bleClient/install 155 | $(INSTALL_DIR) $(1)/usr/sbin 156 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleClient $(1)/usr/sbin/ 157 | endef 158 | 159 | define Package/gl-bleService/install 160 | $(INSTALL_DIR) $(1)/usr/sbin 161 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleService $(1)/usr/sbin/ 162 | endef 163 | 164 | define Package/gl-bletool/install 165 | $(INSTALL_DIR) $(1)/usr/sbin 166 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bletool $(1)/usr/sbin/ 167 | endef 168 | 169 | define Package/gl-bleIbeacon/install 170 | $(INSTALL_DIR) $(1)/usr/sbin 171 | $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bleIbeacon $(1)/usr/sbin/ 172 | endef 173 | 174 | 175 | $(eval $(call BuildPackage,libglble)) 176 | $(eval $(call BuildPackage,gl-bleScanner)) 177 | $(eval $(call BuildPackage,gl-bleSynchronize)) 178 | $(eval $(call BuildPackage,gl-bleAdvLegacy)) 179 | $(eval $(call BuildPackage,gl-bleAdvExtended)) 180 | $(eval $(call BuildPackage,gl-bleAdvPeriodic)) 181 | $(eval $(call BuildPackage,gl-bleClient)) 182 | $(eval $(call BuildPackage,gl-bleService)) 183 | $(eval $(call BuildPackage,gl-bletool)) 184 | $(eval $(call BuildPackage,gl-bleIbeacon)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GL-Ble-SDK User Guide 2 | 3 | 4 | 5 | 6 | ## What’s GL-Ble-SDK 7 | 8 | GL-Ble-SDK is developed and provided by GL-iNet Technology as a part of the iot solution. SDK encapsulates the operation interface of bluetooth modules from different manufacturers and provides users with bluetooth operation functions after abstraction. Users don't need to care what Bluetooth module they are using, just call the **gl-ble-api** in their application to control Bluetooth. 9 | 10 | 11 | 12 | ## How to test easily 13 | 14 | bletool is a cmd line tool for debug gl-ble module which bases on gl-ble-api. You can use it for quick controning and managing ble. 15 | 16 | For information on how to use bletool, you can refer to the [Bletool User Guide](src/example/bletool/README.md). 17 | 18 | 19 | 20 | ## Build develop environment 21 | 22 | Before using the SDK, you need to install the Openwrt SDK environment. 23 | 24 | Please set up the environment according to the following project documents: 25 | 26 | https://github.com/gl-inet/sdk 27 | 28 | 29 | 30 | ## Download&Compile 31 | 32 | ```shell 33 | $ git clone https://github.com/gl-inet/gl-ble-sdk.git 34 | ``` 35 | 36 | Place your package in `openwrt-sdk///package/`, then run: 37 | 38 | ```shell 39 | $ cd sdk/// 40 | $ make package//compile V=s 41 | ``` 42 | 43 | For example, to compile the ble SDK for the S1300 44 | 45 | ```shell 46 | $ cd sdk/qsdk53/ipq806x/ 47 | $ make package/bletool/{clean,compile} V=s 48 | ``` 49 | 50 | If there is a problem with missing dependent libraries during compilation, follow these steps 51 | 52 | ```shell 53 | $ ./scripts/feeds update -f 54 | $ ./scripts/feeds install 55 | ``` 56 | 57 | 58 | 59 | ## Directory structure of gl-ble-sdk source code 60 | 61 | ``` 62 | gl-ble-sdk 63 | | 64 | |- Doxyfile 65 | |- LICENSE 66 | |- Makefile 67 | |- docs 68 | |- src 69 | | | 70 | | |- bledriver # ble module driver 71 | | |- components # sdk component 72 | | |- example # example folder 73 | | |- lib # gl-ble-api lib source code 74 | | |- CMakeLists.txt 75 | ``` 76 | 77 | 78 | 79 | ## Example introduce 80 | 81 | We provide a series of examples(src/example) to help users better understand and use the API. 82 | 83 | ``` 84 | bleAdvertiserLegacy --------------------> A Ble Legacy advertiser with configurable parameters 85 | bleAdvertiserExtended --------------------> A Ble Extended advertiser with configurable parameters 86 | bleAdvertiserPeriodic --------------------> A Ble Periodic advertiser with configurable parameters 87 | bleScanner --------------------> A Ble scanner that can configure scan parameters 88 | bleSynchronize --------------------> A Ble Synchronize that can configure scan parameters 89 | bleIbeacon --------------------> A Ble Ibeacon that can configure send or receive. 90 | bleService --------------------> A Ble server wait for connected 91 | bleClient --------------------> A Ble client with configurable parameters 92 | bletool --------------------> A tool that integrates all BLE API functions 93 | ``` 94 | 95 | We'll keep updating the example, so let us know if you have any good ideas :D 96 | 97 | **Note: The above example will check the BLE module firmware version, if the version of BLE module firmware is not v4.2.0, it will update. However, it may not be supported for previous devices. Please see [DFU DOCS](./dfu).** 98 | 99 | 100 | 101 | ## API References 102 | 103 | We will continue to update the online version of the API documentation. 104 | 105 | [C API References](https://dev.gl-inet.com/gl-ble-sdk-api/group__user) 106 | 107 | Users can also use doxygen to generate documents locally. 108 | 109 | 110 | 111 | ## Supported devices 112 | 113 | | device name | Details | 114 | | ----------- | ------------------------------------------------------------ | 115 | | GL-B2200 | [GL-B2200 / Velica - GL.iNet (gl-inet.com)](https://www.gl-inet.com/products/gl-b2200/) | 116 | | GL-S200 | [GL-S200 - GL.iNet (gl-inet.com)](https://www.gl-inet.com/products/gl-s200/) | 117 | 118 | We'll updating the Supported devices. 119 | -------------------------------------------------------------------------------- /dfu/README.md: -------------------------------------------------------------------------------- 1 | # BLE Module DFU 2 | 3 | ## 1. Build and compile 4 | 5 | - Before using the DFU tool, you need to install the Openwrt SDK environment. Please set up the environment according to the following project documents: https://github.com/gl-inet/sdk. 6 | 7 | - Secondly, you should clone the [gl-silabs-dfu](https://github.com/gl-inet/gl-silabs-dfu) repository into the package directory mentioned above. The version v1.3.1 is used when writing this document. 8 | 9 | - The following is a general compile process. 10 | 11 | ```shell 12 | # 1.Place your gl-silabs-dfu repository in sdk///package/, then run: 13 | cd sdk/// 14 | 15 | # 2.compile 16 | make package/gl-silabs-dfu/compile V=s 17 | ``` 18 | 19 | 20 | 21 | ## 2. Select device BLE firmware 22 | 23 | Currently, only supported for the GL-B2200 and GL-S200 to upgrade the BLE module firmware to v4.2.0. The following is the firmware corresponding to the device. 24 | 25 | | Device | BLE module firmware | 26 | | -------- | ------------------------------------------------------------ | 27 | | GL-B2200 | [gl-efr32mg21f512-ble-ncp-v4_2_0.gbl](./gl-efr32mg21f512-ble-ncp-v4_2_0.gbl) | 28 | | GL-S200 | [gl-efr32mg21f768-ble-ncp-v4_2_0.gbl](gl-efr32mg21f768-ble-ncp-v4_2_0.gbl) | 29 | 30 | 31 | 32 | ## 3. Upgrade 33 | 34 | **Warning:This upgrade is risky and may cause the BLE module of the device to fail to work properly. Please confirm this before upgrading.** 35 | 36 | 37 | 38 | - About GL-B2200, please use the bgaip soft mode to upgrade. 39 | 40 | ```shell 41 | root@GL-B2200:~# gl-silabs-dfu bgapi soft ./gl-efr32mg21f512-ble-ncp-v4_2_0.gbl /dev/ttyMSM1 42 -v 42 | sh: write error: Resource busy 43 | Get upgrade firmware size: 217248 44 | * System boot event! 45 | * Module firmware version: 2.12.3 46 | * Build number: 151 47 | process:[====================================================================================================>]99% *** DFU END! *** 48 | * System boot event! 49 | * Module firmware version: 4.2.0 50 | * Build number: 321 51 | Module reset finish, please check firmware version. 52 | ``` 53 | 54 | 55 | 56 | - About GL-S200, please use the xmodem mode to upgrade. 57 | 58 | ```shell 59 | root@GL-S200:~# gl-silabs-dfu xmodem ./gl-efr32mg21f768-ble-ncp-v4_2_0.gbl /dev/ttyCH343USB1 1 11 -v 60 | file size:216216 61 | start upload... 62 | process:[====================================================================================================>]100% 63 | upload ok. total size:216320 64 | reset chip now... 65 | dfu success! 66 | ``` 67 | -------------------------------------------------------------------------------- /dfu/gl-efr32mg21f512-ble-ncp-v4_2_0.gbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/dfu/gl-efr32mg21f512-ble-ncp-v4_2_0.gbl -------------------------------------------------------------------------------- /dfu/gl-efr32mg21f768-ble-ncp-v4_2_0.gbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/dfu/gl-efr32mg21f768-ble-ncp-v4_2_0.gbl -------------------------------------------------------------------------------- /files/etc/ble/gl-efr32mg21f768-ble-ncp-v4_2_0.gbl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/files/etc/ble/gl-efr32mg21f768-ble-ncp-v4_2_0.gbl -------------------------------------------------------------------------------- /files/etc/ble/gl_gattdb_cfg.json: -------------------------------------------------------------------------------- 1 | { 2 | "service": [ 3 | { 4 | "service_property": 0, 5 | "service_uuid_len": 2, 6 | "service_uuid": "180a", 7 | "characteristic": [ 8 | { 9 | "char_property": 34, 10 | "char_flag": 0, 11 | "char_uuid_len": 16, 12 | "char_uuid": "0D77CC114AC149F2BFA9CD96AC7A92F8", 13 | "char_value_type": 1, 14 | "char_maxlen": 5, 15 | "char_value_len": 5, 16 | "char_value": "342E322E30", 17 | "descriptor": [] 18 | } 19 | ] 20 | }, 21 | { 22 | "service_property": 1, 23 | "service_uuid_len": 2, 24 | "service_uuid": "1800", 25 | "characteristic": [ 26 | { 27 | "char_property": 2, 28 | "char_flag": 1, 29 | "char_uuid_len": 2, 30 | "char_uuid": "2A00", 31 | "char_value_type": 1, 32 | "char_maxlen": 6, 33 | "char_value_len": 6, 34 | "char_value": "474C5F424C45", 35 | "descriptor": [ 36 | { 37 | "despt_property": 1, 38 | "despt_uuid_len": 2, 39 | "despt_uuid": "2902", 40 | "despt_value_type": 1, 41 | "despt_maxlen": 2, 42 | "despt_value_len": 2, 43 | "despt_value": "3030" 44 | } 45 | ] 46 | }, 47 | { 48 | "char_property": 10, 49 | "char_flag": 1, 50 | "char_uuid_len": 2, 51 | "char_uuid": "2A23", 52 | "char_value_type": 1, 53 | "char_maxlen": 3, 54 | "char_value_len": 3, 55 | "char_value": "333231", 56 | "descriptor": [] 57 | } 58 | ] 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /files/etc/config/ble: -------------------------------------------------------------------------------- 1 | config service 'ble' 2 | option model 'GL' 3 | option uart_flowcontrol '0' 4 | option rst_trigger '1' 5 | option uart_baudrate '115200' 6 | option uart_fc '&uart-flow-control' 7 | option gpio_rst '255' 8 | option gpio_dfu '255' 9 | option uart_tty '/dev/null' 10 | -------------------------------------------------------------------------------- /files/etc/uci-defaults/30-ble-model-config: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | . /lib/functions.sh 4 | 5 | tty="" 6 | board=$(board_name) 7 | case "$board" in 8 | *x750*) 9 | uci set ble.ble.model="x750" 10 | uci set ble.ble.uart_flowcontrol="0" 11 | uci set ble.ble.rst_trigger="1" 12 | uci set ble.ble.uart_baudrate="115200" 13 | uci set ble.ble.uart_fc="&uart-flow-control" 14 | uci set ble.ble.gpio_rst="1" 15 | uci set ble.ble.gpio_dfu="255" 16 | uci set ble.ble.uart_tty='/dev/ttyS0' 17 | ;; 18 | *s1300*) 19 | uci set ble.ble.model="s1300" 20 | uci set ble.ble.uart_flowcontrol="0" 21 | uci set ble.ble.rst_trigger="1" 22 | uci set ble.ble.uart_baudrate="115200" 23 | uci set ble.ble.uart_fc="&uart-flow-control" 24 | uci set ble.ble.gpio_rst="48" 25 | uci set ble.ble.gpio_dfu="255" 26 | uci set ble.ble.uart_tty='/dev/ttyMSM1' 27 | ;; 28 | *xe300*) 29 | uci set ble.ble.model="xe300" 30 | uci set ble.ble.uart_flowcontrol="0" 31 | uci set ble.ble.rst_trigger="1" 32 | uci set ble.ble.uart_baudrate="115200" 33 | uci set ble.ble.uart_fc="&uart-flow-control" 34 | uci set ble.ble.gpio_rst="14" 35 | uci set ble.ble.gpio_dfu="255" 36 | uci set ble.ble.uart_tty='/dev/ttyS0' 37 | ;; 38 | *x300b*) 39 | uci set ble.ble.model="x300b" 40 | uci set ble.ble.uart_flowcontrol="0" 41 | uci set ble.ble.rst_trigger="1" 42 | uci set ble.ble.uart_baudrate="115200" 43 | uci set ble.ble.uart_fc="&uart-flow-control" 44 | uci set ble.ble.gpio_rst="16" 45 | uci set ble.ble.gpio_dfu="255" 46 | uci set ble.ble.uart_tty='/dev/ttyS0' 47 | ;; 48 | *ap1300*) 49 | uci set ble.ble.model="ap1300" 50 | uci set ble.ble.uart_flowcontrol="0" 51 | uci set ble.ble.rst_trigger="1" 52 | uci set ble.ble.uart_baudrate="115200" 53 | uci set ble.ble.uart_fc="&uart-flow-control" 54 | uci set ble.ble.gpio_rst="62" 55 | uci set ble.ble.gpio_dfu="255" 56 | uci set ble.ble.uart_tty='/dev/ttyUSB0' 57 | ;; 58 | *b2200*) 59 | uci set ble.ble.model="b2200" 60 | uci set ble.ble.uart_flowcontrol="0" 61 | uci set ble.ble.rst_trigger="1" 62 | uci set ble.ble.uart_baudrate="115200" 63 | uci set ble.ble.uart_fc="&uart-flow-control" 64 | uci set ble.ble.gpio_rst="42" 65 | uci set ble.ble.gpio_dfu="255" 66 | uci set ble.ble.uart_tty='/dev/ttyMSM1' 67 | ;; 68 | *s200*) 69 | uci set ble.ble.model="s200" 70 | uci set ble.ble.uart_flowcontrol="0" 71 | uci set ble.ble.rst_trigger="1" 72 | uci set ble.ble.uart_baudrate="115200" 73 | uci set ble.ble.uart_fc="&uart-flow-control" 74 | uci set ble.ble.gpio_rst="1" 75 | uci set ble.ble.gpio_dfu="11" 76 | uci set ble.ble.uart_tty='/dev/ttyCH343USB1' 77 | ;; 78 | *x3000*) 79 | uci set ble.ble.model="x3000" 80 | uci set ble.ble.uart_flowcontrol="0" 81 | uci set ble.ble.rst_trigger="1" 82 | uci set ble.ble.uart_baudrate="115200" 83 | uci set ble.ble.uart_fc="&uart-flow-control" 84 | uci set ble.ble.gpio_rst="26" 85 | uci set ble.ble.gpio_dfu="27" 86 | uci set ble.ble.uart_tty='/dev/ttyCH343USB0' 87 | ;; 88 | *) 89 | uci set ble.ble.model="GL" 90 | uci set ble.ble.uart_flowcontrol="0" 91 | uci set ble.ble.rst_trigger="1" 92 | tty=$(ls /dev/ttyACM* 2>/dev/null) 93 | [ -z "$tty" ] && tty=$(ls /dev/ttyUSB0 2>/dev/null) 94 | [ -n "$tty" ] && { 95 | uci set ble.ble.uart_tty="$tty" 96 | uci set ble.ble.uart_baudrate="115200" 97 | } 98 | ;; 99 | esac 100 | uci commit ble -------------------------------------------------------------------------------- /files/usr/bin/gl-ble-dfu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | EXEC_NAME=gl-ble-dfu 4 | 5 | device_name=$1 6 | uart_tty=$2 7 | gpio_rst=$3 8 | gpio_dfu=$4 9 | 10 | dfu_mode_exit() { 11 | echo 1 > /sys/class/gpio/gpio$gpio_dfu/value 12 | usleep 100000 13 | echo 0 > /sys/class/gpio/gpio$gpio_rst/value 14 | usleep 100000 15 | echo 1 > /sys/class/gpio/gpio$gpio_rst/value 16 | usleep 100000 17 | 18 | err_code=$1 19 | [ -n "$err_code" ] && { 20 | if [ $err_code != 0 ]; then 21 | exit 1 22 | else 23 | exit 0 24 | fi 25 | } 26 | } 27 | 28 | dfu_mode_enter() { 29 | echo 0 > /sys/class/gpio/gpio$gpio_rst/value 30 | usleep 100000 31 | echo 0 > /sys/class/gpio/gpio$gpio_dfu/value 32 | usleep 100000 33 | echo 1 > /sys/class/gpio/gpio$gpio_rst/value 34 | usleep 100000 35 | 36 | echo -n "\n" > $uart_tty 37 | usleep 100000 38 | echo 1 > $uart_tty 39 | } 40 | 41 | 42 | [ -z "$(which stty)" ] && { 43 | echo "stty not found, dfu failed." 44 | exit 1 45 | } 46 | 47 | [ ! -e "$uart_tty" ] && { 48 | echo "$uart_tty not found, dfu failed." 49 | exit 1 50 | } 51 | 52 | # Check whether the dfu_file is exist, 53 | # After completing a module upgrade, the file will be deleted. If it does not exist, it will exit normally. 54 | dfu_files=$(ls /etc/ble/*.gbl 2>/dev/null) 55 | [ ! -f "$dfu_files" ] && { 56 | echo "dfu file not found." 57 | exit 0 58 | } 59 | 60 | # Enter DFU mode 61 | echo "dfu start..." 62 | 63 | stty -F $uart_tty 115200 cs8 -parenb -cstopb -crtscts -echo raw 64 | 65 | dfu_mode_enter 66 | 67 | # Tranfer image 68 | err_code=$(timeout 60 sz -4 -u -X $dfu_files > $uart_tty < $uart_tty; echo $?) #This will unlink the file. 69 | # err_code=$(timeout 60 sz -4 -X $dfu_files > $uart_tty < $uart_tty; echo $?) 70 | if [ $err_code != 0 ]; then 71 | echo "dfu failed. err_code = $err_code" 72 | else 73 | echo "dfu success." 74 | fi 75 | 76 | # Exit DFU mode 77 | dfu_mode_exit $err_code 78 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.0 ) 2 | 3 | project(gl-ble-sdk 4 | VERSION 2.0.0 5 | LANGUAGES C ) 6 | 7 | add_definitions( -D_GNU_SOURCE ) 8 | # add_compile_options(-O -Wall -Werror --std=gnu99) 9 | add_compile_options(-O -Wall --std=gnu99) 10 | 11 | set(CMAKE_C_FLAGS_RELEASE "-O3") 12 | 13 | add_subdirectory(./lib build/lib) 14 | add_subdirectory(./example/bleScanner build/bleScanner) 15 | add_subdirectory(./example/bleSynchronize build/bleSynchronize) 16 | add_subdirectory(./example/bleAdvExtended build/bleAdvExtended) 17 | add_subdirectory(./example/bleAdvLegacy build/bleAdvLegacy) 18 | add_subdirectory(./example/bleAdvPeriodic build/bleAdvPeriodic) 19 | add_subdirectory(./example/bleClient build/bleClient) 20 | add_subdirectory(./example/bleService build/bleService) 21 | add_subdirectory(./example/bletool build/bletool) 22 | add_subdirectory(./example/bleIbeacon build/bleIbeacon) -------------------------------------------------------------------------------- /src/bledriver/silabs/silabs_bleapi.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef _SILABS_BLEAPI_H 21 | #define _SILABS_BLEAPI_H 22 | 23 | #include "gl_errno.h" 24 | 25 | GL_RET silabs_ble_enable(int); 26 | 27 | GL_RET silabs_ble_hard_reset(void); 28 | 29 | GL_RET silabs_ble_local_mac(BLE_MAC mac); 30 | 31 | GL_RET silabs_ble_start_discovery(uint8_t phys, uint16_t interval, uint16_t window, uint8_t type, uint8_t mode); 32 | 33 | GL_RET silabs_ble_stop_discovery(void); 34 | 35 | GL_RET silabs_ble_set_sync_parameters(uint16_t skip, uint16_t timeout); 36 | 37 | GL_RET silabs_ble_start_sync(BLE_MAC address, uint8_t address_type, uint8_t adv_sid, uint16_t *handle); 38 | 39 | GL_RET silabs_ble_stop_sync(uint16_t handle); 40 | 41 | GL_RET silabs_ble_create_adv_handle(uint8_t *handle); 42 | 43 | GL_RET silabs_ble_delete_adv_handle(uint8_t handle); 44 | 45 | GL_RET silabs_ble_start_legacy_adv(uint8_t handle, uint32_t interval_min, uint32_t interval_max, uint8_t discover, uint8_t connect); 46 | 47 | GL_RET silabs_ble_start_extended_adv(uint8_t handle, uint8_t primary_phy, uint8_t secondary_phy, 48 | uint32_t interval_min, uint32_t interval_max, uint8_t discover, uint8_t connect); 49 | 50 | GL_RET silabs_ble_start_periodic_adv(uint8_t handle, uint8_t primary_phy, uint8_t secondary_phy, uint16_t interval_min, uint16_t interval_max); 51 | 52 | GL_RET silabs_ble_stop_adv(uint8_t handle); 53 | 54 | GL_RET silabs_ble_set_legacy_adv_data(uint8_t handle, uint8_t flag, const char *data); 55 | 56 | GL_RET silabs_ble_set_extended_adv_data(uint8_t handle, const char *data); 57 | 58 | GL_RET silabs_ble_set_periodic_adv_data(uint8_t handle, const char *data); 59 | 60 | GL_RET silabs_ble_send_notify(BLE_MAC address, int char_handle, char *value); 61 | 62 | GL_RET silabs_ble_connect(BLE_MAC address, int address_type, int phy); 63 | 64 | GL_RET silabs_ble_disconnect(BLE_MAC address); 65 | 66 | GL_RET silabs_ble_get_rssi(BLE_MAC address, int32_t *rssi); 67 | 68 | GL_RET silabs_ble_get_service(gl_ble_service_list_t *service_list, BLE_MAC address); 69 | 70 | GL_RET silabs_ble_get_char(gl_ble_char_list_t *char_list, BLE_MAC address, int service_handle); 71 | 72 | GL_RET silabs_ble_set_power(int power, int *current_power); 73 | 74 | GL_RET silabs_ble_read_char(BLE_MAC address, int char_handle); 75 | 76 | GL_RET silabs_ble_write_char(BLE_MAC address, int char_handle, char *value, int res); 77 | 78 | GL_RET silabs_ble_set_notify(BLE_MAC address, int char_handle, int flag); 79 | 80 | GL_RET silabs_ble_set_gattdb(char *json_cfg_name); 81 | 82 | GL_RET silabs_ble_del_gattdb(void); 83 | 84 | GL_RET silabs_ble_set_identity_address(BLE_MAC address, int address_type); 85 | 86 | GL_RET silabs_ble_get_identity_address(BLE_MAC address, int *address_type); 87 | 88 | #endif -------------------------------------------------------------------------------- /src/bledriver/silabs/silabs_evt.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #ifndef _SILABS_EVT_H_ 18 | #define _SILABS_EVT_H_ 19 | 20 | #include "sli_bt_api.h" 21 | 22 | typedef struct{ 23 | long msgtype; 24 | struct sl_bt_packet evt; 25 | }silabs_msg_queue_t; 26 | 27 | typedef struct{ 28 | int evt_msgid; 29 | gl_ble_cbs* cbs; 30 | }watcher_param_t; 31 | 32 | 33 | 34 | void* silabs_watcher(void* arg); 35 | 36 | 37 | 38 | 39 | #endif -------------------------------------------------------------------------------- /src/bledriver/silabs/silabs_msg.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #ifndef _SILABS_MSG_H_ 18 | #define _SILABS_MSG_H_ 19 | 20 | #include "sli_bt_api.h" 21 | 22 | #ifndef SL_BT_API_QUEUE_LEN 23 | #define SL_BT_API_QUEUE_LEN 30 24 | #endif 25 | 26 | #define BGLIB_DEFINE() \ 27 | struct sl_bt_packet _sl_bt_cmd_msg; \ 28 | struct sl_bt_packet _sl_bt_rsp_msg; \ 29 | struct sl_bt_packet *sl_bt_cmd_msg = &_sl_bt_cmd_msg; \ 30 | struct sl_bt_packet *sl_bt_rsp_msg = &_sl_bt_rsp_msg; \ 31 | struct sl_bt_packet sl_bt_queue_buffer[SL_BT_API_QUEUE_LEN]; \ 32 | int sl_bt_queue_w = 0; \ 33 | int sl_bt_queue_r = 0; 34 | 35 | extern struct sl_bt_packet sl_bt_queue_buffer[SL_BT_API_QUEUE_LEN]; 36 | extern int sl_bt_queue_w; 37 | extern int sl_bt_queue_r; 38 | 39 | #define SPE_EVT_MAX 50 40 | extern struct sl_bt_packet special_evt[SPE_EVT_MAX]; 41 | extern int special_evt_num; 42 | 43 | int wait_rsp_evt(uint32_t evt_id, uint32_t timeout); 44 | 45 | typedef struct 46 | { 47 | int evt_msgid; 48 | } driver_param_t; 49 | 50 | void *silabs_driver(void *arg); 51 | 52 | void sl_bt_host_handle_command(); 53 | void sl_bt_host_handle_command_noresponse(); 54 | 55 | #endif -------------------------------------------------------------------------------- /src/bledriver/silabs/sl_bgapi.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef SL_BGAPI_H 21 | #define SL_BGAPI_H 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Macros to declare deprecated functions */ 30 | #if defined(__IAR_SYSTEMS_ICC__) 31 | #define SL_BGAPI_DEPRECATED _Pragma("deprecated") 32 | #elif defined(__GNUC__) 33 | #define SL_BGAPI_DEPRECATED __attribute__((deprecated)) 34 | #else 35 | #define SL_BGAPI_DEPRECATED 36 | #endif 37 | 38 | /* Compatibility */ 39 | #ifndef PACKSTRUCT 40 | /*Default packed configuration*/ 41 | #ifdef __GNUC__ 42 | #ifdef _WIN32 43 | #define PACKSTRUCT(decl) decl __attribute__((__packed__, gcc_struct)) 44 | #else 45 | #define PACKSTRUCT(decl) decl __attribute__((__packed__)) 46 | #endif 47 | #define ALIGNED __attribute__((aligned(0x4))) 48 | #elif __IAR_SYSTEMS_ICC__ 49 | 50 | #define PACKSTRUCT(decl) __packed decl 51 | 52 | #define ALIGNED 53 | #elif _MSC_VER /*msvc*/ 54 | 55 | #define PACKSTRUCT(decl) __pragma(pack(push, 1) ) decl __pragma(pack(pop) ) 56 | #define ALIGNED 57 | #else 58 | #define PACKSTRUCT(a) a PACKED 59 | #endif 60 | #endif 61 | 62 | /** 63 | * The maximum BGAPI command payload size. 64 | */ 65 | #ifndef SL_BGAPI_MAX_PAYLOAD_SIZE 66 | #define SL_BGAPI_MAX_PAYLOAD_SIZE 256 67 | #endif 68 | 69 | /***************************************************************************//** 70 | * @addtogroup sl_bgapi_types BGAPI Types 71 | * @brief Common types in BGAPI protocol 72 | * @{ 73 | */ 74 | 75 | #ifndef SL_BT_TYPE_UINT8ARRARY 76 | #define SL_BT_TYPE_UINT8ARRARY 77 | /** @brief Variable-length uint8_t array. Maximum length: 255 */ 78 | typedef struct { 79 | uint8_t len; /**< Number of bytes stored in @p data */ 80 | uint8_t data[]; /**< Data bytes*/ 81 | } uint8array; 82 | #endif 83 | 84 | #ifndef SL_BT_TYPE_BYTE_ARRARY 85 | #define SL_BT_TYPE_BYTE_ARRARY 86 | /** @brief Variable-length int8_t array. Maximum length: 65535 */ 87 | typedef struct { 88 | uint16_t len; /**< Number of bytes stored in @p data */ 89 | int8_t data[]; /**< Data bytes*/ 90 | } byte_array; 91 | #endif 92 | 93 | #ifndef SL_BT_TYPE_BDADDR 94 | #define SL_BT_TYPE_BDADDR 95 | /** @brief Bluetooth address */ 96 | typedef struct { 97 | uint8_t addr[6]; /**< @brief Bluetooth address in reverse byte order */ 98 | } bd_addr; 99 | #endif 100 | 101 | #ifndef SL_BT_TYPE_UUID128 102 | #define SL_BT_TYPE_UUID128 103 | /** @brief 128-bit UUID */ 104 | typedef struct { 105 | uint8_t data[16]; /**< 128-bit UUID */ 106 | } uuid_128; 107 | #endif 108 | 109 | #ifndef SL_BT_TYPE_AES_KEY128 110 | #define SL_BT_TYPE_AES_KEY128 111 | /** @brief 128-bit AES key */ 112 | typedef struct { 113 | uint8_t data[16]; /**< 128-bit AES key */ 114 | } aes_key_128; 115 | #endif 116 | 117 | #ifndef SL_BT_TYPE_UUID16 118 | #define SL_BT_TYPE_UUID16 119 | /** @brief 16-bit UUID */ 120 | typedef struct { 121 | uint8_t data[2]; /**< 16-bit UUID */ 122 | } sl_bt_uuid_16_t; 123 | #endif 124 | 125 | #ifndef SL_BT_TYPE_UUID64 126 | #define SL_BT_TYPE_UUID64 127 | /** @brief 64-bit UUID */ 128 | typedef struct { 129 | uint8_t data[8]; /**< 64-bit UUID */ 130 | } sl_bt_uuid_64_t; 131 | #endif 132 | 133 | /** @} */ // end addtogroup sl_bgapi_types 134 | /******************************************************************************/ 135 | 136 | /** @brief Internal function prototype for BGAPI command handlers */ 137 | typedef void (*sl_bgapi_handler)(const void*); 138 | 139 | typedef enum sl_bgapi_msg_types { 140 | sl_bgapi_msg_type_cmd = 0x00, 141 | sl_bgapi_msg_type_rsp = 0x00, 142 | sl_bgapi_msg_type_evt = 0x80 143 | } sl_bgapi_msg_types_t; 144 | 145 | enum sl_bgapi_dev_types { 146 | sl_bgapi_dev_type_bt = 0x20, 147 | sl_bgapi_dev_type_btmesh = 0x28, 148 | }; 149 | 150 | /***************************************************************************//** 151 | * @addtogroup sl_bgapi_types BGAPI Types 152 | * @brief Common types in BGAPI protocol 153 | * @{ 154 | */ 155 | 156 | /** 157 | * @brief The length of a BGAPI message header which is 4 bytes 158 | */ 159 | #define SL_BGAPI_MSG_HEADER_LEN (4) 160 | 161 | /** 162 | * @brief Get the identifier of a BGAPI message including device type, class ID, 163 | * message type and message ID. 164 | * 165 | * @param HDR The header of the message as a uint32_t integer 166 | */ 167 | #define SL_BGAPI_MSG_ID(HDR) ((HDR) & 0xffff00f8) 168 | 169 | /** 170 | * @brief Get the data payload length in a BGAPI message. 171 | * 172 | * @param HDR The header of the message as a uint32_t integer 173 | */ 174 | #define SL_BGAPI_MSG_LEN(HDR) ((((HDR) & 0x7) << 8) | (((HDR) & 0xff00) >> 8)) 175 | 176 | /** @} */ // end addtogroup sl_bgapi_types 177 | /******************************************************************************/ 178 | 179 | /** 180 | * @brief The bit indicating whether data of a BGAPI message is encrypted 181 | */ 182 | #define SL_BGAPI_BIT_ENCRYPTED (1 << 6) // Bit 183 | 184 | /** 185 | * @brief Check whether data of a BGAPI message is encrypted. 186 | * 187 | * @param HDR The BGAPI header of the message as a uint32_t integer 188 | */ 189 | #define SL_BGAPI_MSG_ENCRYPTED(HDR) ((HDR)&SL_BGAPI_BIT_ENCRYPTED) 190 | 191 | /** 192 | * Internal function for setting the command handler function. Used by API library. 193 | * 194 | * @param cmd_handler_delegate Pointer to command handler delegate function 195 | */ 196 | void sli_bgapi_set_cmd_handler_delegate(void (*cmd_handler_delegate)(uint32_t, 197 | sl_bgapi_handler, 198 | const void*)); 199 | 200 | #ifdef __cplusplus 201 | } 202 | #endif 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /src/bledriver/silabs/sl_bt_types.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | /* 21 | * "sl_bt_types.h" is deprecated and replaced by "sl_bt_api.h". We include 22 | * "sl_bt_api.h" here to maintain source code compatibility with files that only 23 | * include "sl_bt_types.h". 24 | */ 25 | #include "sl_bt_api.h" 26 | -------------------------------------------------------------------------------- /src/bledriver/silabs/sl_bt_version.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * @file 3 | * @brief Bluetooth stack version definition 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef SL_BT_VERSION_H 21 | #define SL_BT_VERSION_H 22 | 23 | #define BG_VERSION_MAJOR 4 24 | #define BG_VERSION_MINOR 2 25 | #define BG_VERSION_PATCH 0 26 | #define BG_VERSION_BUILD 321 27 | #define BG_VERSION_HASH {0x1b,0x0e,0x33,0xcd,0xe2,0xa3,0xa5,0x42,0x7a,0x20,0xe3,0x5f,0x8e,0x67,0xbc,0x0c,0x97,0x27,0x3c,0x87} 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/bledriver/silabs/sli_bt_gattdb_def.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef SLI_BT_GATT_DEF_H 21 | #define SLI_BT_GATT_DEF_H 22 | 23 | #include 24 | #include 25 | 26 | typedef struct { 27 | uint16_t len; //size of buffer 28 | uint8_t data[]; 29 | } sli_bt_gattdb_value_t; 30 | 31 | typedef struct { 32 | uint8_t properties; //Characteristic properties, same as in characteristic descriptor gatt_char_prop 33 | uint16_t max_len; //Maximum length of data in buffer 34 | uint16_t len; //current size of data in buffer 35 | uint8_t data[]; //size is max_len 36 | } sli_bt_gattdb_attribute_chrvalue_t; 37 | 38 | typedef struct { 39 | uint8_t flags; //client characteristic flags allowed 1-notification, 2-indication) 40 | uint8_t clientconfig_index; // index to client config. 41 | } sli_bt_gattdb_attribute_config_t; 42 | 43 | typedef struct { 44 | uint8_t properties; //Characteristic properties, same as in characteristic descriptor gatt_char_prop 45 | uint16_t char_uuid; // characteristic UUID handle 46 | } sli_bt_gattdb_attribute_characteristic_t; 47 | 48 | typedef struct { 49 | uint16_t start; //Included Service Attribute Handle 50 | uint16_t end; //End Group Handle 51 | } sli_bt_gattdb_attribute_service_include_t; 52 | 53 | typedef struct { 54 | uint16_t handle; 55 | uint16_t uuid; 56 | uint16_t permissions; //gatt_attribute_permission 57 | uint16_t caps; // Capability bit flags 58 | uint8_t datatype; //Just use uint8_t Do not use enum type, may cause compatibility troubles 59 | uint8_t state; 60 | union { 61 | const sli_bt_gattdb_value_t *constdata; //generic constant data 62 | sli_bt_gattdb_attribute_chrvalue_t *dynamicdata; //Modifiable data 63 | sli_bt_gattdb_attribute_config_t configdata; 64 | sli_bt_gattdb_attribute_characteristic_t characteristic; 65 | sli_bt_gattdb_attribute_service_include_t service_include; 66 | }; 67 | } sli_bt_gattdb_attribute_t; 68 | 69 | struct sli_bt_gattdb_s { 70 | const sli_bt_gattdb_attribute_t *attributes; 71 | uint16_t attribute_table_size; 72 | uint16_t attribute_num; 73 | const uint16_t *uuid16; 74 | uint16_t uuid16_table_size; 75 | uint16_t uuid16_num; 76 | const uint8_t *uuid128; 77 | uint16_t uuid128_table_size; 78 | uint16_t uuid128_num; 79 | uint8_t num_ccfg; 80 | uint16_t caps_mask; 81 | uint16_t enabled_caps; 82 | }; 83 | 84 | typedef struct sli_bt_gattdb_s sli_bt_gattdb_t; 85 | 86 | extern const sli_bt_gattdb_t *static_gattdb; 87 | 88 | /** 89 | * @addtogroup dynamic_gatt_config 90 | * 91 | * Dynamic GATT database configuration. 92 | */ 93 | 94 | /** 95 | * Flag indicating GATT caching should be enabled. When enabled, a Generic 96 | * Attribute Profile Service will be created in database if one doesn't exist. 97 | **/ 98 | #define SLI_BT_GATTDB_CONFIG_FLAG_ENABLE_GATT_CACHING (0x01) 99 | 100 | /** 101 | * Flag indicating the static database should be included if one exists. 102 | */ 103 | #define SLI_BT_GATTDB_CONFIG_FLAG_INCLUDE_STATIC_DB (0X02) 104 | 105 | typedef struct { 106 | uint32_t flags; 107 | } sli_bt_gattdb_config_t; 108 | 109 | /** @} (end addtogroup dynamic_gatt_config) */ 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /src/bledriver/util/gl_common.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "sl_bt_api.h" 24 | #include "gl_common.h" 25 | #include "gl_errno.h" 26 | 27 | 28 | int addr2str(BLE_MAC adr, char* str) { 29 | sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", adr[5], adr[4], 30 | adr[3], adr[2], adr[1], adr[0]); 31 | return 0; 32 | } 33 | 34 | int str2addr(char* str, BLE_MAC address) { 35 | int mac[6] = {0}; 36 | sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", &mac[5], &mac[4], &mac[3], 37 | &mac[2], &mac[1], &mac[0]); 38 | 39 | uint8_t i = 0; 40 | for(;i < 6; i++) 41 | { 42 | address[i] = mac[i]; 43 | } 44 | return 0; 45 | } 46 | 47 | int str2array(uint8_t* dst, const char* src, int len) { 48 | int i = 0; 49 | int tmp; 50 | while (i < len) { 51 | sscanf(src + i * 2, "%02x", &tmp); 52 | dst[i] = tmp; 53 | // printf("str2array dst[%d] = 0x%02x\n", i, dst[i]); 54 | i++; 55 | } 56 | return 0; 57 | } 58 | int hex2str(uint8_t* head, int len, char* value) { 59 | int i = 0; 60 | 61 | // FIXME: (Sometime kernel don't mask all uart print) When wifi network up/down, it will recv a big message 62 | // if(len >= 256/2) 63 | // { 64 | // strcpy(value,"00"); 65 | // // printf("recv a err msg! err len = %d\n",len); 66 | // return -1; 67 | // } 68 | 69 | while (i < len) { 70 | sprintf(value + i * 2, "%02x", head[i]); 71 | i++; 72 | } 73 | return 0; 74 | } 75 | 76 | void reverse_endian(uint8_t* header, uint8_t length) { 77 | uint8_t* tmp = (uint8_t*)malloc(length); 78 | memcpy(tmp, header, length); 79 | int i = length - 1; 80 | int j = 0; 81 | for (; i >= 0; i--, j++) { 82 | *(header + j) = *(tmp + i); 83 | } 84 | free(tmp); 85 | return; 86 | } 87 | 88 | sl_status_t ble_write_long_data(uint16_t len, uint8_t *adv_data) 89 | { 90 | sl_status_t status = SL_STATUS_FAIL; 91 | status = sl_bt_system_data_buffer_clear(); 92 | if (status != SL_STATUS_OK) 93 | { 94 | return GL_UNKNOW_ERR; 95 | } 96 | 97 | uint8_t i = 0; 98 | uint8_t remain = len % (SL_BGAPI_MAX_PAYLOAD_SIZE - 1); 99 | uint8_t write_count = len / (SL_BGAPI_MAX_PAYLOAD_SIZE - 1); 100 | for (; i < write_count; ++i) 101 | { 102 | status = sl_bt_system_data_buffer_write(SL_BGAPI_MAX_PAYLOAD_SIZE - 1, &adv_data[i * (SL_BGAPI_MAX_PAYLOAD_SIZE - 1)]); 103 | if (status != SL_STATUS_OK) 104 | { 105 | return GL_UNKNOW_ERR; 106 | } 107 | } 108 | status = sl_bt_system_data_buffer_write(remain, &adv_data[write_count * (SL_BGAPI_MAX_PAYLOAD_SIZE - 1)]); 109 | if (status != SL_STATUS_OK) 110 | { 111 | return GL_UNKNOW_ERR; 112 | } 113 | 114 | return GL_SUCCESS; 115 | } 116 | 117 | gl_ble_adv_type_t ble_get_adv_type(uint8_t adv_event_flag) 118 | { 119 | if((SL_BT_SCANNER_EVENT_FLAG_CONNECTABLE | SL_BT_SCANNER_EVENT_FLAG_SCANNABLE) == adv_event_flag) 120 | { 121 | return CONNECTABLE_SCANNABLE_UNDIRECTED; 122 | } 123 | else if(SL_BT_SCANNER_EVENT_FLAG_CONNECTABLE == adv_event_flag) 124 | { 125 | return CONNECTABLE_UNDIRECTED; 126 | } 127 | else if((SL_BT_SCANNER_EVENT_FLAG_CONNECTABLE | SL_BT_SCANNER_EVENT_FLAG_DIRECTED) == adv_event_flag) 128 | { 129 | return CONNECTABLE_DIRECTED; 130 | } 131 | else if(0 == adv_event_flag) 132 | { 133 | return NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; 134 | } 135 | else if(SL_BT_SCANNER_EVENT_FLAG_DIRECTED == adv_event_flag) 136 | { 137 | return NONCONNECTABLE_NONSCANNABLE_DIRECTED; 138 | } 139 | else if(SL_BT_SCANNER_EVENT_FLAG_SCANNABLE == adv_event_flag) 140 | { 141 | return SCANNABLE_UNDIRECTED; 142 | } 143 | else if((SL_BT_SCANNER_EVENT_FLAG_SCANNABLE | SL_BT_SCANNER_EVENT_FLAG_DIRECTED) == adv_event_flag) 144 | { 145 | return SCANNABLE_DIRECTED; 146 | } 147 | else if(SL_BT_SCANNER_EVENT_FLAG_SCAN_RESPONSE & adv_event_flag) 148 | { 149 | return SCSN_RSPONE; 150 | } 151 | return INVAILD_ADV_TYPE; 152 | } -------------------------------------------------------------------------------- /src/bledriver/util/gl_common.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #ifndef GL_COMMON_H 20 | #define GL_COMMON_H 21 | #include 22 | #include "gl_type.h" 23 | #include "sl_status.h" 24 | #include "sl_bt_version.h" 25 | 26 | /***********************************************************************************************//** 27 | * \brief The MAC address of uint8_t type convets to string. 28 | * \param[in] adr The MAC address of uint8_t type. 29 | * \param[out] str Buffer used for storing the mac address. 30 | * \return 0 means success, None-zero means failed. 31 | **************************************************************************************************/ 32 | int addr2str(BLE_MAC adr, char* str); 33 | 34 | /***********************************************************************************************//** 35 | * \brief The MAC address of string type convets to uint8_t type. 36 | * \param[in] adr The MAC address of string type. 37 | * \param[out] address Buffer used for storing the mac address. 38 | * \return 0 means success, None-zero means failed. 39 | **************************************************************************************************/ 40 | int str2addr(char* str, BLE_MAC address); 41 | 42 | /***********************************************************************************************//** 43 | * \brief The string convets to uint8_t array. 44 | * \param[in] src The string will be converted. 45 | * \param[out] dst The uint8_t array used for storing the result. 46 | * \return 0 means success, None-zero means failed. 47 | **************************************************************************************************/ 48 | int str2array(uint8_t* dst, const char* src, int len); 49 | 50 | /***********************************************************************************************//** 51 | * \brief Hexadecimal conversion to a string. 52 | * \param[in] head The hexadecimal will be converted. 53 | * \param[in] len The length of the hexadecimal. 54 | * \param[in] value Buffer used for storing the coverted result. 55 | * \return 0 means success, None-zero means failed. 56 | **************************************************************************************************/ 57 | int hex2str(uint8_t* head, int len, char* value); 58 | 59 | /***********************************************************************************************//** 60 | * \brief Reverse endian conversion 61 | * \param[in] header The value will be reversed. 62 | * \param[in] length The length of the value. 63 | **************************************************************************************************/ 64 | void reverse_endian(uint8_t* header, uint8_t length); 65 | 66 | /***********************************************************************************************//** 67 | * \brief Write long data in specify buffer. 68 | * \param[in] len The length of the value. 69 | * \param[in] adv_data The Data value to be written. 70 | **************************************************************************************************/ 71 | sl_status_t ble_write_long_data(uint16_t len, uint8_t *adv_data); 72 | 73 | /***********************************************************************************************//** 74 | * \brief get the adv packet type in scan event. 75 | * \param[in] adv_event_flag Event Type Flags of Advertisement ReportsScanner. 76 | **************************************************************************************************/ 77 | gl_ble_adv_type_t ble_get_adv_type(uint8_t adv_event_flag); 78 | 79 | #endif -------------------------------------------------------------------------------- /src/bledriver/util/gl_hal.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file hal.c 3 | * @brief Hardware interface adaptation 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "gl_uart.h" 25 | #include "gl_log.h" 26 | #include "gl_hal.h" 27 | #include "gl_errno.h" 28 | 29 | #define UCI_PACKAGE "ble" 30 | 31 | unsigned char ENDIAN; 32 | 33 | char rston[64] = {0}; 34 | char rstoff[64] = {0}; 35 | 36 | hw_cfg_t* ble_hw_cfg = NULL; 37 | static bool is_ble_rst_exist = false; 38 | 39 | static int check_endian(void); 40 | static int serial_init(void); 41 | static GL_RET get_model_hw_cfg(void); 42 | static GL_RET normal_check_rst_io(void); 43 | static GL_RET sdk_check_ver(void); 44 | 45 | struct uci_context* guci2_init(void); 46 | int guci2_free(struct uci_context* ctx); 47 | int guci2_get(struct uci_context* ctx, const char* section_or_key, char value[]); 48 | 49 | static int check_endian(void) 50 | { 51 | int x = 1; 52 | if(*((char *)&x) == 1) 53 | { 54 | ENDIAN = 0; 55 | log_debug("little endian\n"); 56 | }else{ 57 | ENDIAN = 1; 58 | log_debug("big endian\n"); 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | static GL_RET normal_check_rst_io(void) 65 | { 66 | if(!ble_hw_cfg) 67 | { 68 | log_err("HW cfg lost!\n"); 69 | return GL_UNKNOW_ERR; 70 | } 71 | 72 | if(access("/sys/class/gpio/ble_rst", F_OK) == 0) 73 | { 74 | is_ble_rst_exist = true; 75 | log_debug("Ble rst io exist.\n"); 76 | return GL_SUCCESS; 77 | } 78 | 79 | char io[32] = {0}; 80 | sprintf(io, "/sys/class/gpio/gpio%d", ble_hw_cfg->rst_gpio); 81 | log_debug("%s\n", io); 82 | 83 | char create_io[64] = {0}; 84 | sprintf(create_io, "((echo %d > /sys/class/gpio/export) 2>/dev/null)", ble_hw_cfg->rst_gpio); 85 | log_debug("%s\n", create_io); 86 | 87 | char create_io_direction[80] = {0}; 88 | sprintf(create_io_direction, "((echo out > /sys/class/gpio/gpio%d/direction) 2>/dev/null)", ble_hw_cfg->rst_gpio); 89 | log_debug("%s\n", create_io_direction); 90 | 91 | 92 | // create IO 93 | int i = 0; 94 | while((access(io, F_OK)) != 0) 95 | { 96 | log_debug("Ble rst io: %s not exist. Now trying create ... Time: %d\n", io, i+1); 97 | system(create_io); 98 | 99 | i++; 100 | usleep(300000); 101 | 102 | if(i > 5) 103 | { 104 | log_err("Creating ble RST IO failed!\n"); 105 | return GL_UNKNOW_ERR; 106 | } 107 | } 108 | 109 | // set IO direction 110 | system(create_io_direction); 111 | 112 | log_debug("Ble rst io: %s exist.\n", io); 113 | 114 | return GL_SUCCESS; 115 | } 116 | 117 | /* Check openwrt version 118 | SDK in official openwrt will have a special io base num. 119 | If "/sys/class/gpio/gpiochip412" exist, all io shoule add 412. 120 | If "/sys/class/gpio/gpiochip455" exist, all io shoule add 455. 121 | If "/sys/class/gpio/gpiochip512" exist, all io shoule add 512. 122 | */ 123 | #define SPECIAL_CHIP_IO412 "/sys/class/gpio/gpiochip412" 124 | #define SPECIAL_CHIP_IO455 "/sys/class/gpio/gpiochip455" 125 | #define SPECIAL_CHIP_IO512 "/sys/class/gpio/gpiochip512" 126 | static GL_RET sdk_check_ver(void) 127 | { 128 | if(!ble_hw_cfg) 129 | { 130 | log_err("HW cfg lost!\n"); 131 | return GL_UNKNOW_ERR; 132 | } 133 | 134 | if((access(SPECIAL_CHIP_IO412, F_OK)) != -1) 135 | { 136 | log_debug("SDK gpiochip412 exist.\n"); 137 | ble_hw_cfg->rst_gpio += 412; 138 | } 139 | else if((access(SPECIAL_CHIP_IO455, F_OK)) != -1) 140 | { 141 | log_debug("SDK gpiochip455 exist.\n"); 142 | ble_hw_cfg->rst_gpio += 455; 143 | } 144 | else if((access(SPECIAL_CHIP_IO512, F_OK)) != -1) 145 | { 146 | log_debug("SDK gpiochip512 exist.\n"); 147 | ble_hw_cfg->rst_gpio += 512; 148 | } 149 | 150 | return GL_SUCCESS; 151 | } 152 | 153 | static int serial_init(void) 154 | { 155 | if(!ble_hw_cfg) 156 | { 157 | log_err("HW cfg lost!\n"); 158 | return GL_UNKNOW_ERR; 159 | } 160 | 161 | if(is_ble_rst_exist) 162 | { 163 | if(ble_hw_cfg->rst_trigger == 1) 164 | { 165 | strcpy(rston, "((echo 1 > /sys/class/gpio/ble_rst/value) 2>/dev/null)"); 166 | strcpy(rstoff, "((echo 0 > /sys/class/gpio/ble_rst/value) 2>/dev/null)"); 167 | 168 | }else if(ble_hw_cfg->rst_trigger == 0){ 169 | strcpy(rston, "((echo 0 > /sys/class/gpio/ble_rst/value) 2>/dev/null)"); 170 | strcpy(rstoff, "((echo 1 > /sys/class/gpio/ble_rst/value) 2>/dev/null)"); 171 | 172 | }else{ 173 | log_err("hw rst trigger cfg error!\n"); 174 | return GL_UNKNOW_ERR; 175 | } 176 | } 177 | else 178 | { 179 | if(ble_hw_cfg->rst_trigger == 1) 180 | { 181 | sprintf(rston, "echo 1 > /sys/class/gpio/gpio%d/value", ble_hw_cfg->rst_gpio); 182 | sprintf(rstoff, "echo 0 > /sys/class/gpio/gpio%d/value", ble_hw_cfg->rst_gpio); 183 | 184 | }else if(ble_hw_cfg->rst_trigger == 0){ 185 | sprintf(rston, "echo 0 > /sys/class/gpio/gpio%d/value", ble_hw_cfg->rst_gpio); 186 | sprintf(rstoff, "echo 1 > /sys/class/gpio/gpio%d/value", ble_hw_cfg->rst_gpio); 187 | 188 | }else{ 189 | log_err("hw rst trigger cfg error!\n"); 190 | return GL_UNKNOW_ERR; 191 | } 192 | } 193 | 194 | return uartOpen((int8_t*)ble_hw_cfg->port, ble_hw_cfg->baudRate, ble_hw_cfg->flowcontrol, 100); 195 | } 196 | 197 | static GL_RET get_model_hw_cfg(void) 198 | { 199 | char uart_baudrate[16] = {0}; 200 | char flowcontrol[8] = {0}; 201 | char rst_trigger[8] = {0}; 202 | char gpio_rst[8] = {0}; 203 | char gpio_dfu[8] = {0}; 204 | char uart_tty[32] = {0}; 205 | 206 | struct uci_context* ctx = guci2_init(); 207 | if(!ctx) 208 | { 209 | log_err("open uci handle error\n"); 210 | return GL_UNKNOW_ERR; 211 | } 212 | 213 | if(guci2_get(ctx,"uart_baudrate",uart_baudrate) < 0) 214 | { 215 | log_err("Get hw uart_baudrate error!\n"); 216 | return GL_UNKNOW_ERR; 217 | }else{ 218 | log_debug("Get uart_baudrate: %s\n", uart_baudrate); 219 | } 220 | 221 | if(guci2_get(ctx,"uart_flowcontrol",flowcontrol) < 0) 222 | { 223 | log_err("Get hw flowcontrol error!\n"); 224 | return GL_UNKNOW_ERR; 225 | }else{ 226 | log_debug("Get flowcontrol: %s\n", flowcontrol); 227 | } 228 | 229 | if(guci2_get(ctx,"rst_trigger",rst_trigger) < 0) 230 | { 231 | log_err("Get hw rst_trigger error!\n"); 232 | return GL_UNKNOW_ERR; 233 | }else{ 234 | log_debug("Get rst_trigger: %s\n", rst_trigger); 235 | } 236 | 237 | if(guci2_get(ctx,"gpio_rst",gpio_rst) < 0) 238 | { 239 | log_err("Get hw gpio_rst error!\n"); 240 | return GL_UNKNOW_ERR; 241 | }else{ 242 | log_debug("Get gpio_rst: %s\n", gpio_rst); 243 | } 244 | 245 | if(guci2_get(ctx,"gpio_dfu",gpio_dfu) < 0) 246 | { 247 | log_err("Get hw gpio_dfu error!\n"); 248 | return GL_UNKNOW_ERR; 249 | }else{ 250 | log_debug("Get gpio_dfu: %s\n", gpio_dfu); 251 | } 252 | 253 | if(guci2_get(ctx,"uart_tty",uart_tty) < 0) 254 | { 255 | log_err("Get hw uart_tty error!\n"); 256 | return GL_UNKNOW_ERR; 257 | }else{ 258 | log_debug("Get uart_tty: %s\n", uart_tty); 259 | } 260 | 261 | guci2_free(ctx); 262 | 263 | ble_hw_cfg = malloc(sizeof(hw_cfg_t)); 264 | ble_hw_cfg->baudRate = atoi(uart_baudrate); 265 | ble_hw_cfg->flowcontrol = atoi(flowcontrol); 266 | ble_hw_cfg->rst_trigger = atoi(rst_trigger); 267 | ble_hw_cfg->rst_gpio = atoi(gpio_rst); 268 | ble_hw_cfg->dfu_gpio = atoi(gpio_dfu); 269 | memcpy(ble_hw_cfg->port, uart_tty, sizeof(uart_tty)); 270 | sdk_check_ver(); 271 | 272 | normal_check_rst_io(); 273 | 274 | return GL_SUCCESS; 275 | } 276 | 277 | int hal_init(void) 278 | { 279 | check_endian(); 280 | 281 | get_model_hw_cfg(); 282 | 283 | // Manual clean uart cache: fix tcflush() not work on some model 284 | // uartCacheClean(); 285 | 286 | int serialFd = serial_init(); 287 | if( serialFd < 0 ) 288 | { 289 | fprintf(stderr,"Hal initilized failed.\n"); 290 | return GL_UNKNOW_ERR; 291 | } 292 | 293 | return serialFd; 294 | } 295 | 296 | int hal_destroy(void) 297 | { 298 | return uartClose(); 299 | } 300 | 301 | 302 | struct uci_context* guci2_init(void) 303 | { 304 | 305 | struct uci_context* ctx = uci_alloc_context(); 306 | 307 | return ctx; 308 | } 309 | 310 | int guci2_free(struct uci_context* ctx) 311 | { 312 | uci_free_context(ctx); 313 | return 0; 314 | } 315 | 316 | int guci2_get(struct uci_context* ctx, const char* section_or_key, char out_value[]) 317 | { 318 | struct uci_package *pkg; 319 | struct uci_section *sec; 320 | const char *value = NULL; 321 | int ret = UCI_OK; 322 | 323 | if (uci_load(ctx, UCI_PACKAGE, &pkg)) { 324 | return -1; 325 | } 326 | 327 | sec = uci_lookup_section(ctx, pkg, UCI_PACKAGE); 328 | if (!sec) { 329 | uci_unload(ctx, pkg); 330 | return -1; 331 | } 332 | 333 | value = uci_lookup_option_string(ctx, sec, section_or_key); 334 | if (value) { 335 | strcpy(out_value, value); 336 | } else { 337 | fprintf(stderr, "Failed to get option value\n"); 338 | } 339 | 340 | uci_unload(ctx, pkg); 341 | return ret; 342 | } -------------------------------------------------------------------------------- /src/bledriver/util/gl_hal.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef GL_HAL_H 21 | #define GL_HAL_H 22 | 23 | 24 | extern char rston[]; 25 | extern char rstoff[]; 26 | 27 | typedef struct { 28 | char model[32]; 29 | char port[32]; 30 | uint32_t baudRate; 31 | uint32_t flowcontrol; 32 | uint8_t rst_trigger; 33 | uint16_t rst_gpio; 34 | uint16_t dfu_gpio; 35 | }hw_cfg_t; 36 | 37 | /*Initilize the hal*/ 38 | int hal_init(void); 39 | 40 | int hal_destroy(void); 41 | 42 | 43 | #endif -------------------------------------------------------------------------------- /src/bledriver/util/gl_methods.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | 20 | #ifndef GL_METHODS_H 21 | #define GL_METHODS_H 22 | 23 | #define SILABS_EFR32 24 | #ifdef SILABS_EFR32 25 | 26 | #include "silabs_bleapi.h" 27 | #include "silabs_msg.h" 28 | 29 | #define ble_driver silabs_driver 30 | #define ble_watcher silabs_watcher 31 | 32 | #define ble_enable silabs_ble_enable 33 | #define ble_hard_reset silabs_ble_hard_reset 34 | #define ble_local_mac silabs_ble_local_mac 35 | #define ble_set_power silabs_ble_set_power 36 | #define ble_start_discovery silabs_ble_start_discovery 37 | #define ble_stop_discovery silabs_ble_stop_discovery 38 | #define ble_set_sync_parameters silabs_ble_set_sync_parameters 39 | #define ble_start_sync silabs_ble_start_sync 40 | #define ble_stop_sync silabs_ble_stop_sync 41 | #define ble_create_adv_handle silabs_ble_create_adv_handle 42 | #define ble_delete_adv_handle silabs_ble_delete_adv_handle 43 | #define ble_start_legacy_adv silabs_ble_start_legacy_adv 44 | #define ble_start_extended_adv silabs_ble_start_extended_adv 45 | #define ble_start_periodic_adv silabs_ble_start_periodic_adv 46 | #define ble_stop_adv silabs_ble_stop_adv 47 | #define ble_set_legacy_adv_data silabs_ble_set_legacy_adv_data 48 | #define ble_set_extended_adv_data silabs_ble_set_extended_adv_data 49 | #define ble_set_periodic_adv_data silabs_ble_set_periodic_adv_data 50 | #define ble_send_notify silabs_ble_send_notify 51 | #define ble_connect silabs_ble_connect 52 | #define ble_disconnect silabs_ble_disconnect 53 | #define ble_get_rssi silabs_ble_get_rssi 54 | #define ble_get_service silabs_ble_get_service 55 | #define ble_get_char silabs_ble_get_char 56 | #define ble_read_char silabs_ble_read_char 57 | #define ble_write_char silabs_ble_write_char 58 | #define ble_set_notify silabs_ble_set_notify 59 | #define ble_set_gattdb silabs_ble_set_gattdb 60 | // #define ble_del_gattdb silabs_ble_del_gattdb 61 | #define ble_set_identity_address silabs_ble_set_identity_address 62 | #define ble_get_identity_address silabs_ble_get_identity_address 63 | 64 | #endif 65 | 66 | #ifdef TLK_8251 67 | #endif 68 | 69 | 70 | #endif -------------------------------------------------------------------------------- /src/bledriver/util/gl_uart.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file 3 | * @brief 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #ifndef GL_UART_H 20 | #define GL_UART_H 21 | 22 | #include 23 | /***********************************************************************************************//** 24 | * \brief Open the serial port. 25 | * \param[in] port Serial port to use. 26 | * \param[in] baudRate Baud rate to use. 27 | * \param[in] rtsCts Enable/disable hardware flow control. 28 | * \param[in] timeout Constant used to calculate the total time-out period for read operations, in 29 | * milliseconds. 30 | * \return 0 on success, -1 on failure. 31 | **************************************************************************************************/ 32 | int32_t uartOpen(int8_t* port, uint32_t baudRate, uint32_t rtsCts, int32_t timeout); 33 | 34 | /***********************************************************************************************//** 35 | * \brief Close the serial port. 36 | * \return 0 on success, -1 on failure. 37 | **************************************************************************************************/ 38 | int32_t uartClose(void); 39 | 40 | /***********************************************************************************************//** 41 | * \brief Blocking read data from serial port. The function will block until the desired amount 42 | * has been read or an error occurs. 43 | * \note In order to use this function the serial port has to be configured blocking. This can be 44 | * done by calling uartOpen() with 'timeout = 0'. 45 | * \param[in] dataLength The amount of bytes to read. 46 | * \param[out] data Buffer used for storing the data. 47 | * \return The amount of bytes read or -1 on failure. 48 | **************************************************************************************************/ 49 | int32_t uartRx(uint32_t dataLength, uint8_t* data); 50 | 51 | /***********************************************************************************************//** 52 | * \brief Non-blocking read from serial port. 53 | * \note A truly non-blocking operation is possible only if uartOpen() is called with timeout 54 | * parameter set to 0. 55 | * \param[in] dataLength The amount of bytes to read. 56 | * \param[out] data Buffer used for storing the data. 57 | * \return The amount of bytes read, 0 if configured serial blocking time interval elapses or -1 58 | * on failure. 59 | **************************************************************************************************/ 60 | int32_t uartRxNonBlocking(uint32_t dataLength, uint8_t* data); 61 | 62 | /***********************************************************************************************//** 63 | * \brief Return the number of bytes in the input buffer. 64 | * \return The number of bytes in the input buffer or -1 on failure. 65 | **************************************************************************************************/ 66 | int32_t uartRxPeek(void); 67 | 68 | /***********************************************************************************************//** 69 | * \brief Write data to serial port. The function will block until 70 | * the desired amount has been written or an error occurs. 71 | * \param[in] dataLength The amount of bytes to write. 72 | * \param[in] data Buffer used for storing the data. 73 | * \return The amount of bytes written or -1 on failure. 74 | **************************************************************************************************/ 75 | int32_t uartTx(uint32_t dataLength, uint8_t* data); 76 | 77 | 78 | int32_t uartCacheClean(void); 79 | 80 | int32_t setRtsStu(char stu); 81 | int32_t setDtrStu(char stu); 82 | 83 | int32_t getDsrStu(void); 84 | int32_t getCtsStu(void); 85 | 86 | #endif -------------------------------------------------------------------------------- /src/components/dev_mgr/gl_dev_mgr.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _GL_DEV_MGR_H_ 17 | #define _GL_DEV_MGR_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define MAC_STR_LEN 18 24 | 25 | typedef struct _silabs_dev_desc_t 26 | { 27 | char dev_addr[MAC_STR_LEN]; 28 | uint16_t connection; 29 | } ble_dev_desc_t; 30 | 31 | typedef struct 32 | { 33 | ble_dev_desc_t ble_dev_desc; 34 | uint32_t timestamp; 35 | struct list_head linked_list; 36 | } ble_dev_mgr_node_t; 37 | 38 | typedef struct 39 | { 40 | void* dev_list_mutex; 41 | struct list_head dev_list; 42 | } ble_dev_mgr_ctx_t; 43 | 44 | void ble_dev_mgr_print(void); 45 | 46 | int ble_dev_mgr_init(void); 47 | 48 | int ble_dev_mgr_del_all(void); 49 | 50 | int ble_dev_mgr_add(char *dev_addr, uint16_t connection); 51 | 52 | int ble_dev_mgr_del(uint16_t connection); 53 | 54 | int ble_dev_mgr_update(uint16_t connection); 55 | 56 | uint16_t ble_dev_mgr_get_connection(char *dev_addr, int* connection); 57 | 58 | uint16_t ble_dev_mgr_get_address(uint16_t connection, char *mac); 59 | 60 | int ble_dev_mgr_get_list_size(void); 61 | 62 | int ble_dev_mgr_destroy(void); 63 | 64 | #endif // !_GL_DEV_MGR_H_ 65 | -------------------------------------------------------------------------------- /src/components/evt_msg_queue/evt_queue.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/components/evt_msg_queue/evt_queue.c -------------------------------------------------------------------------------- /src/components/evt_msg_queue/evt_queue.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/components/evt_msg_queue/evt_queue.h -------------------------------------------------------------------------------- /src/components/log/gl_log.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #include "gl_log.h" 18 | #include 19 | #include 20 | #include 21 | 22 | #ifdef SYSLOG 23 | #include 24 | #endif 25 | 26 | /* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */ 27 | // char* lvl_color[] = { 28 | // "[0m", "[1;31m", "[1;33m", "[1;32m", "[1;34m" 29 | // }; 30 | log_name_t lvl_names[] = { 31 | { "emerg", LOG_EMERG_LEVEL }, 32 | { "alert", LOG_ALERT_LEVEL }, 33 | { "crit", LOG_CRIT_LEVEL }, 34 | { "err", LOG_ERROR_LEVEL }, 35 | { "warning", LOG_WARN_LEVEL }, 36 | { "notice", LOG_NOTICE_LEVEL }, 37 | { "info", LOG_INFO_LEVEL }, 38 | { "debug", LOG_DEBUG_LEVEL }, 39 | { NULL, -1 } 40 | }; 41 | 42 | log_color_t lvl_color[] = { 43 | { "[0m", LOG_EMERG_LEVEL }, 44 | { "[0m", LOG_ALERT_LEVEL }, 45 | { "[0m", LOG_CRIT_LEVEL }, 46 | { "[1;31m", LOG_ERROR_LEVEL }, 47 | { "[1;33m", LOG_WARN_LEVEL }, 48 | { "[0m", LOG_NOTICE_LEVEL }, 49 | { "[1;32m", LOG_INFO_LEVEL }, 50 | { "[1;34m", LOG_DEBUG_LEVEL }, 51 | { NULL, -1 } 52 | }; 53 | 54 | #if defined(ENABLE_DEBUG) 55 | log_level_t g_log_level = LOG_DEBUG_LEVEL; 56 | #else 57 | log_level_t g_log_level = LOG_INFO_LEVEL; 58 | #endif 59 | 60 | static const char* _get_filename(const char* p) 61 | { 62 | #ifdef WIN32 63 | char ch = '\\'; 64 | #else 65 | char ch = '/'; 66 | #endif 67 | const char* q = strrchr(p, ch); 68 | if (q == NULL) { 69 | q = p; 70 | } else { 71 | q++; 72 | } 73 | return q; 74 | } 75 | 76 | void IOT_SetLogLevel(log_level_t level) 77 | { 78 | g_log_level = level; 79 | } 80 | 81 | log_level_t IOT_GetLogLevel(void) 82 | { 83 | return g_log_level; 84 | } 85 | 86 | void IOT_LogPrintf(const char* module, const char* file, const char* func, const int line, const int level, const char* fmt, ...) 87 | { 88 | if (level > g_log_level) { 89 | return; 90 | } 91 | 92 | /* format log content */ 93 | const char* file_name = _get_filename(file); 94 | 95 | char sg_text_buf[MAX_LOG_MSG_LEN + 1]; 96 | char* tmp_buf = sg_text_buf; 97 | char* o = tmp_buf; 98 | memset(tmp_buf, 0, sizeof(sg_text_buf)); 99 | 100 | if (NULL != module) { 101 | o += snprintf(o, sizeof(sg_text_buf), "%s|%s|%s|%s(%d): ", lvl_names[level].c_name, module, file_name, func, line); 102 | } else { 103 | o += snprintf(o, sizeof(sg_text_buf), "%s|%s|%s(%d): ", lvl_names[level].c_name, file_name, func, line); 104 | } 105 | 106 | va_list ap; 107 | va_start(ap, fmt); 108 | o += vsnprintf(o, MAX_LOG_MSG_LEN - 2 - strlen(tmp_buf), fmt, ap); 109 | va_end(ap); 110 | 111 | strcat(tmp_buf, "\r\n"); 112 | #ifndef SYSLOG 113 | printf("%s%s", "\033", lvl_color[level].c_color); 114 | #endif 115 | 116 | if (level <= g_log_level) { 117 | #ifdef SYSLOG 118 | syslog(level, "%s", tmp_buf); 119 | #else 120 | /* default log handler: print to console */ 121 | printf("%s", tmp_buf); 122 | #endif 123 | } 124 | 125 | #ifndef SYSLOG 126 | printf("%s", "\033[0m"); 127 | #endif 128 | 129 | return; 130 | } 131 | 132 | #define LITE_HEXDUMP_DRAWLINE(start_mark, len, end_mark) \ 133 | do { \ 134 | int i; \ 135 | \ 136 | printf("%s", start_mark); \ 137 | for (i = 0; i < len; ++i) { \ 138 | printf("-"); \ 139 | } \ 140 | printf("%s", end_mark); \ 141 | printf("\r\n"); \ 142 | \ 143 | } while (0) 144 | 145 | #define HEXDUMP_SEP_LINE "+" \ 146 | "-----------------------" \ 147 | "-----------------------" \ 148 | "-----------------------" 149 | void utils_log_hexdump(const char* title, const void* buff, const int len) 150 | { 151 | int i, j, written; 152 | unsigned char ascii[20] = { 0 }; 153 | char header[64] = { 0 }; 154 | unsigned char* buf = (unsigned char*)buff; 155 | 156 | snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len); 157 | 158 | LITE_HEXDUMP_DRAWLINE("+", strlen(header) - 4, "+"); 159 | printf("%s", header); 160 | printf("%s\r\n", HEXDUMP_SEP_LINE); 161 | 162 | written = 0; 163 | for (i = 0; i < len; ++i) { 164 | if (i % 16 == 0) { 165 | printf("| %08X: ", (unsigned int)(i + (long)buff)); 166 | written += 8; 167 | } 168 | 169 | printf("%02X", buf[i]); 170 | written += 2; 171 | 172 | if (i % 2 == 1) { 173 | printf(" "); 174 | written += 1; 175 | } 176 | snprintf((char*)ascii + i % 16, (1 + 1), "%c", ((buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.')); 177 | 178 | if (((i + 1) % 16 == 0) || (i == len - 1)) { 179 | for (j = 0; j < 48 - written; ++j) { 180 | printf(" "); 181 | } 182 | 183 | printf(" %s", ascii); 184 | printf("\r\n"); 185 | 186 | written = 0; 187 | memset(ascii, 0, sizeof(ascii)); 188 | } 189 | } 190 | printf("%s\r\n", HEXDUMP_SEP_LINE); 191 | 192 | return ; 193 | } 194 | -------------------------------------------------------------------------------- /src/components/log/gl_log.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #ifndef _GL_LOG_H_ 18 | #define _GL_LOG_H_ 19 | 20 | #if defined(__cplusplus) 21 | extern "C" { 22 | #endif 23 | 24 | #include 25 | 26 | #define MAX_LOG_MSG_LEN 512 27 | 28 | #define LOG_DIS "DIS" 29 | #define LOG_ERR "ERR" 30 | #define LOG_WRN "WRN" 31 | #define LOG_INF "INF" 32 | #define LOG_DBG "DBG" 33 | 34 | typedef enum { 35 | LOG_EMERG_LEVEL = 0, 36 | LOG_ALERT_LEVEL = 1, 37 | LOG_CRIT_LEVEL = 2, 38 | LOG_ERROR_LEVEL = 3, 39 | LOG_WARN_LEVEL = 4, 40 | LOG_NOTICE_LEVEL = 5, 41 | LOG_INFO_LEVEL = 6, 42 | LOG_DEBUG_LEVEL = 7 43 | } log_level_t; 44 | 45 | typedef struct { 46 | char* c_name; 47 | int c_val; 48 | } log_name_t; 49 | 50 | typedef struct { 51 | char* c_color; 52 | int c_val; 53 | } log_color_t; 54 | 55 | void IOT_SetLogLevel(log_level_t level); 56 | log_level_t IOT_GetLogLevel(void); 57 | 58 | void IOT_LogPrintf(const char* module, const char* file, const char* func, const int line, const int level, const char* fmt, ...); 59 | void utils_log_hexdump(const char* title, const void* buff, const int len); 60 | 61 | // 全局日志输出宏 62 | #if 1 63 | #define log_debug(fmt, ...) IOT_LogPrintf(NULL, __FILE__, __FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, fmt, ##__VA_ARGS__) 64 | #define log_info(fmt, ...) IOT_LogPrintf(NULL, __FILE__, __FUNCTION__, __LINE__, LOG_INFO_LEVEL, fmt, ##__VA_ARGS__) 65 | #define log_warning(fmt, ...) IOT_LogPrintf(NULL, __FILE__, __FUNCTION__, __LINE__, LOG_WARN_LEVEL, fmt, ##__VA_ARGS__) 66 | #define log_err(fmt, ...) IOT_LogPrintf(NULL, __FILE__, __FUNCTION__, __LINE__, LOG_ERROR_LEVEL, fmt, ##__VA_ARGS__) 67 | 68 | // #define log_debug(fmt, ...) printf(fmt, ##__VA_ARGS__);printf("\n"); 69 | // #define log_info(fmt, ...) printf(fmt, ##__VA_ARGS__);printf("\n"); 70 | // #define log_warning(fmt, ...) printf(fmt, ##__VA_ARGS__);printf("\n"); 71 | // #define log_err(fmt, ...) printf(fmt, ##__VA_ARGS__);printf("\n"); 72 | 73 | #else 74 | #define log_debug(fmt, ...) \ 75 | do { \ 76 | ; \ 77 | } while (0) 78 | #define log_info(fmt, ...) \ 79 | do { \ 80 | ; \ 81 | } while (0) 82 | #define log_warning(fmt, ...) \ 83 | do { \ 84 | ; \ 85 | } while (0) 86 | #define log_err(fmt, ...) \ 87 | do { \ 88 | ; \ 89 | } while (0) 90 | #endif 91 | 92 | // 基于模块级别的日志输出宏 93 | #if 1 94 | #define mlog_debug(module, fmt, ...) IOT_LogPrintf(module, __FILE__, __FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, fmt, ##__VA_ARGS__) 95 | #define mlog_info(module, fmt, ...) IOT_LogPrintf(module, __FILE__, __FUNCTION__, __LINE__, LOG_INFO_LEVEL, fmt, ##__VA_ARGS__) 96 | #define mlog_warning(module, fmt, ...) IOT_LogPrintf(module, __FILE__, __FUNCTION__, __LINE__, LOG_WARN_LEVEL, fmt, ##__VA_ARGS__) 97 | #define mlog_err(module, fmt, ...) IOT_LogPrintf(module, __FILE__, __FUNCTION__, __LINE__, LOG_ERROR_LEVEL, fmt, ##__VA_ARGS__) 98 | #else 99 | #define mlog_debug(fmt, ...) \ 100 | do { \ 101 | ; \ 102 | } while (0) 103 | #define mlog_info(fmt, ...) \ 104 | do { \ 105 | ; \ 106 | } while (0) 107 | #define mlog_warning(fmt, ...) \ 108 | do { \ 109 | ; \ 110 | } while (0) 111 | #define mlog_err(fmt, ...) \ 112 | do { \ 113 | ; \ 114 | } while (0) 115 | #endif 116 | 117 | // 16进制打印 118 | #define log_hexdump(buf, len) utils_log_hexdump(#buf, (const void*)buf, (const int)len) 119 | 120 | #if defined(__cplusplus) 121 | } 122 | #endif 123 | 124 | #endif /* _INFRA_LOG_H_ */ 125 | -------------------------------------------------------------------------------- /src/components/thread/gl_thread.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "gl_thread.h" 40 | #include "gl_log.h" 41 | 42 | static thread_ctx_t g_thread_ctx = { 0 }; 43 | 44 | static void HAL_MutexLock(void *mutex); 45 | static void HAL_MutexUnlock(void *mutex); 46 | static int HAL_MutexTryLock(void *mutex); 47 | 48 | 49 | thread_ctx_t* _thread_get_ctx(void) 50 | { 51 | return &g_thread_ctx; 52 | } 53 | 54 | void _thread_ctx_mutex_lock(void) 55 | { 56 | // log_debug("_thread_ctx_mutex_lock\n"); 57 | thread_ctx_t* ctx = _thread_get_ctx(); 58 | if (ctx->mutex) { 59 | HAL_MutexLock(ctx->mutex); 60 | }else{ 61 | log_err("mutex lock NULL"); 62 | } 63 | } 64 | 65 | int _thread_ctx_mutex_try_lock(void) 66 | { 67 | // log_debug("_thread_ctx_mutex_try_lock\n"); 68 | 69 | thread_ctx_t* ctx = _thread_get_ctx(); 70 | if (ctx->mutex) { 71 | return HAL_MutexTryLock(ctx->mutex); 72 | }else{ 73 | log_err("mutex try lock NULL"); 74 | } 75 | 76 | return -1; 77 | } 78 | 79 | void _thread_ctx_mutex_unlock(void) 80 | { 81 | // log_debug("_thread_ctx_mutex_unlock\n"); 82 | 83 | thread_ctx_t* ctx = _thread_get_ctx(); 84 | if (ctx->mutex) { 85 | HAL_MutexUnlock(ctx->mutex); 86 | }else{ 87 | log_err("mutex unlock NULL"); 88 | } 89 | } 90 | 91 | void *HAL_MutexCreate(void) 92 | { 93 | int err_num; 94 | pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); 95 | if (NULL == mutex) { 96 | return NULL; 97 | } 98 | 99 | if (0 != (err_num = pthread_mutex_init(mutex, NULL))) { 100 | log_err("create mutex failed\n"); 101 | free(mutex); 102 | return NULL; 103 | } 104 | 105 | return mutex; 106 | } 107 | 108 | void HAL_MutexDestroy(void *mutex) 109 | { 110 | int err_num; 111 | 112 | if (!mutex) { 113 | printf("mutex want to destroy is NULL!\n"); 114 | return; 115 | } 116 | if (0 != (err_num = pthread_mutex_destroy((pthread_mutex_t *)mutex))) { 117 | log_err("destroy mutex failed\n"); 118 | } 119 | 120 | free(mutex); 121 | } 122 | 123 | static void HAL_MutexLock(void *mutex) 124 | { 125 | int err_num; 126 | if (0 != (err_num = pthread_mutex_lock((pthread_mutex_t *)mutex))) { 127 | log_err("lock mutex failed: - '%s' (%d)\n", strerror(err_num), err_num); 128 | } 129 | } 130 | 131 | static int HAL_MutexTryLock(void *mutex) 132 | { 133 | return pthread_mutex_trylock((pthread_mutex_t *)mutex); 134 | } 135 | 136 | static void HAL_MutexUnlock(void *mutex) 137 | { 138 | int err_num; 139 | if (0 != (err_num = pthread_mutex_unlock((pthread_mutex_t *)mutex))) { 140 | log_err("unlock mutex failed - '%s' (%d)\n", strerror(err_num), err_num); 141 | } 142 | } 143 | 144 | int HAL_ThreadCreate( 145 | void **thread_handle, 146 | void *(*work_routine)(void *), 147 | void *arg, 148 | hal_os_thread_param_t *hal_os_thread_param, 149 | int *stack_used) 150 | { 151 | int ret = -1; 152 | 153 | if (stack_used) { 154 | *stack_used = 0; 155 | } 156 | 157 | ret = pthread_create((pthread_t *)thread_handle, NULL, work_routine, arg); 158 | 159 | return ret; 160 | } 161 | 162 | void HAL_ThreadDetach(void *thread_handle) 163 | { 164 | pthread_detach((pthread_t)thread_handle); 165 | } 166 | 167 | void HAL_ThreadDelete(void *thread_handle) 168 | { 169 | if (NULL == thread_handle) { 170 | // pthread_exit(0); 171 | } else { 172 | /*main thread delete child thread*/ 173 | pthread_cancel((pthread_t)thread_handle); 174 | pthread_join((pthread_t)thread_handle, 0); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/components/thread/gl_thread.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _GL_THREAD_H_ 17 | #define _GL_THREAD_H_ 18 | 19 | typedef struct { 20 | void* g_dispatch_thread; 21 | void* mutex; 22 | } thread_ctx_t; 23 | 24 | 25 | thread_ctx_t* _thread_get_ctx(void); 26 | 27 | void *HAL_MutexCreate(void); 28 | 29 | void HAL_MutexDestroy(void *mutex); 30 | 31 | void _thread_ctx_mutex_lock(void); 32 | 33 | int _thread_ctx_mutex_try_lock(void); 34 | 35 | void _thread_ctx_mutex_unlock(void); 36 | 37 | 38 | 39 | 40 | typedef enum { 41 | os_thread_priority_idle = -3, /* priority: idle (lowest) */ 42 | os_thread_priority_low = -2, /* priority: low */ 43 | os_thread_priority_belowNormal = -1, /* priority: below normal */ 44 | os_thread_priority_normal = 0, /* priority: normal (default) */ 45 | os_thread_priority_aboveNormal = 1, /* priority: above normal */ 46 | os_thread_priority_high = 2, /* priority: high */ 47 | os_thread_priority_realtime = 3, /* priority: realtime (highest) */ 48 | os_thread_priority_error = 0x84, /* system cannot determine priority or thread has illegal priority */ 49 | } hal_os_thread_priority_t; 50 | 51 | typedef struct _hal_os_thread { 52 | hal_os_thread_priority_t priority; /*initial thread priority */ 53 | void *stack_addr; /* thread stack address malloced by caller, use system stack by . */ 54 | int stack_size; /* stack size requirements in bytes; 0 is default stack size */ 55 | int detach_state; /* 0: not detached state; otherwise: detached state. */ 56 | char *name; /* thread name. */ 57 | } hal_os_thread_param_t; 58 | 59 | int HAL_ThreadCreate(void **thread_handle,void *(*work_routine)(void *), \ 60 | void *arg,hal_os_thread_param_t *hal_os_thread_param, \ 61 | int *stack_used); 62 | 63 | void HAL_ThreadDetach(void *thread_handle); 64 | 65 | void HAL_ThreadDelete(void *thread_handle); 66 | 67 | 68 | 69 | 70 | 71 | #endif -------------------------------------------------------------------------------- /src/components/timestamp/timestamp.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "timestamp.h" 22 | 23 | uint32_t utils_get_timestamp(void) 24 | { 25 | struct timeval tv; 26 | gettimeofday(&tv, NULL); 27 | 28 | return tv.tv_usec; 29 | } -------------------------------------------------------------------------------- /src/components/timestamp/timestamp.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | 17 | #ifndef _TIMESTAMP_H_ 18 | #define _TIMESTAMP_H_ 19 | 20 | #include 21 | 22 | uint32_t utils_get_timestamp(void); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | #endif -------------------------------------------------------------------------------- /src/example/bleAdvExtended/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleAdvExtended" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleAdvExtended/demo_bleAdvExtended.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleAdvExtended.c 3 | * @brief Enable BLE Extended broadcast sending function 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gl_errno.h" 29 | #include "gl_type.h" 30 | #include "gl_bleapi.h" 31 | 32 | static void sigal_hander(int sig); 33 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 34 | 35 | #define MAC2STR(a) (a)[5], (a)[4], (a)[3], (a)[2], (a)[1], (a)[0] 36 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 37 | 38 | static bool module_work = false; 39 | static uint8_t handle = 0xff; 40 | 41 | 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | signal(SIGTERM, sigal_hander); 46 | signal(SIGINT, sigal_hander); 47 | signal(SIGQUIT, sigal_hander); 48 | 49 | // init msg callback 50 | gl_ble_cbs ble_cb; 51 | memset(&ble_cb, 0, sizeof(gl_ble_cbs)); 52 | 53 | ble_cb.ble_gap_event = NULL; 54 | ble_cb.ble_gatt_event = NULL; 55 | ble_cb.ble_module_event = ble_module_cb; 56 | 57 | // init adv param 58 | uint8_t primary_phy = 1; 59 | uint8_t secondary_phy = 1; 60 | uint32_t interval_min = 160; 61 | uint32_t interval_max = 320; 62 | uint8_t discover = 2; 63 | uint8_t connect = 4; 64 | //init adv data param 65 | const char *data = NULL; 66 | 67 | json_object *file_o = NULL; 68 | 69 | // get scanner param 70 | if ((argc != 1) && (argc != 2)) 71 | { 72 | goto exit; 73 | } 74 | 75 | if (argc == 2) 76 | { 77 | file_o = json_object_from_file(argv[1]); 78 | if(file_o == NULL) 79 | { 80 | goto exit; 81 | } 82 | 83 | json_object *primary_phy_o = json_object_object_get(file_o, "primary_phy"); 84 | if(primary_phy_o == NULL) 85 | { 86 | goto exit; 87 | } 88 | primary_phy = json_object_get_int(primary_phy_o); 89 | 90 | json_object *secondary_phy_o = json_object_object_get(file_o, "secondary_phy"); 91 | if(secondary_phy_o == NULL) 92 | { 93 | goto exit; 94 | } 95 | secondary_phy = json_object_get_int(secondary_phy_o); 96 | 97 | json_object *interval_min_o = json_object_object_get(file_o, "interval_min"); 98 | if(interval_min_o == NULL) 99 | { 100 | goto exit; 101 | } 102 | interval_min = json_object_get_int(interval_min_o); 103 | 104 | json_object *interval_max_o = json_object_object_get(file_o, "interval_max"); 105 | if(interval_max_o == NULL) 106 | { 107 | goto exit; 108 | } 109 | interval_max = json_object_get_int(interval_max_o); 110 | 111 | json_object *discover_o = json_object_object_get(file_o, "discover"); 112 | if(discover_o == NULL) 113 | { 114 | goto exit; 115 | } 116 | discover = json_object_get_int(discover_o); 117 | 118 | json_object *connect_o = json_object_object_get(file_o, "connect"); 119 | if(connect_o == NULL) 120 | { 121 | goto exit; 122 | } 123 | connect = json_object_get_int(connect_o); 124 | 125 | json_object *extended_adv_data_o = json_object_object_get(file_o, "extended_adv_data"); 126 | if(extended_adv_data_o != NULL) 127 | { 128 | data = json_object_get_string(extended_adv_data_o); 129 | } 130 | 131 | json_object_put(file_o); 132 | } 133 | 134 | 135 | // init ble module 136 | GL_RET ret; 137 | ret = gl_ble_init(); 138 | if (GL_SUCCESS != ret) 139 | { 140 | printf("gl_ble_init failed: %d\n", ret); 141 | exit(-1); 142 | } 143 | 144 | ret = gl_ble_subscribe(&ble_cb); 145 | if (GL_SUCCESS != ret) 146 | { 147 | printf("gl_ble_subscribe failed: %d\n", ret); 148 | exit(-1); 149 | } 150 | 151 | // ble module check, will auto update firmware if module firmware not work. 152 | // after update firmware if not work, will exit the program. 153 | ret = gl_ble_check_module(&ble_cb, false); 154 | if(ret != GL_SUCCESS) 155 | { 156 | printf("The ble module firmware not work.\n"); 157 | exit(-1); 158 | } 159 | 160 | // wait for module reset 161 | while (!module_work) 162 | { 163 | usleep(100000); 164 | } 165 | 166 | // create adv handle 167 | ret = gl_ble_create_adv_handle(&handle); 168 | if (GL_SUCCESS != ret) 169 | { 170 | printf("gl_ble_create_adv_handle failed: %d\n", ret); 171 | exit(-1); 172 | } 173 | 174 | // set advertising data 175 | if (data) 176 | { 177 | ret = gl_ble_set_extended_adv_data(handle, data); 178 | if (GL_SUCCESS != ret) 179 | { 180 | printf("gl_ble_set_extended_adv_data failed: %d\n", ret); 181 | exit(-1); 182 | } 183 | } 184 | 185 | // start advertising 186 | ret = gl_ble_start_extended_adv(handle, primary_phy, secondary_phy, interval_min, interval_max, discover, connect); 187 | if (GL_SUCCESS != ret) 188 | { 189 | printf("gl_ble_start_extended_adv failed: %d\n", ret); 190 | exit(-1); 191 | } 192 | 193 | //get ble mac 194 | uint8_t mac_buf[6]; 195 | ret = gl_ble_get_mac(mac_buf); 196 | if (GL_SUCCESS != ret) 197 | { 198 | printf("gl_ble_get_mac failed: %d\n", ret); 199 | exit(-1); 200 | } 201 | printf("Broadcasting data, the mac of the current device is > " MACSTR "\n", MAC2STR(mac_buf)); 202 | 203 | while (1) 204 | { 205 | sleep(1000); 206 | } 207 | 208 | return 0; 209 | 210 | exit: 211 | if(file_o != NULL) 212 | { 213 | json_object_put(file_o); 214 | } 215 | printf("param err!"); 216 | return GL_ERR_PARAM; 217 | } 218 | 219 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 220 | { 221 | switch (event) 222 | { 223 | case MODULE_BLE_SYSTEM_BOOT_EVT: 224 | { 225 | 226 | json_object *o = NULL; 227 | o = json_object_new_object(); 228 | json_object_object_add(o, "type", json_object_new_string("module_start")); 229 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 230 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 231 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 232 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 233 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 234 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 235 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 236 | const char *temp = json_object_to_json_string(o); 237 | printf("MODULE_CB_MSG >> %s\n", temp); 238 | 239 | json_object_put(o); 240 | 241 | module_work = true; 242 | 243 | break; 244 | } 245 | default: 246 | break; 247 | } 248 | 249 | return 0; 250 | } 251 | 252 | static void sigal_hander(int sig) 253 | { 254 | printf("\bleAdvertiserExtended exit!\n"); 255 | 256 | gl_ble_stop_adv(handle); 257 | gl_ble_delete_adv_handle(handle); 258 | gl_ble_unsubscribe(); 259 | gl_ble_destroy(); 260 | 261 | exit(0); 262 | } 263 | -------------------------------------------------------------------------------- /src/example/bleAdvExtended/docs/DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/example/bleAdvExtended/docs/DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png -------------------------------------------------------------------------------- /src/example/bleAdvLegacy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleAdvLegacy" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleAdvLegacy/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleAdvLegacy 2 | 3 | Demonstrate how to Legacy broadcast 4 | 5 | This is a demonstration of the user using gl-ble-api to send out a Legacy broadcast. 6 | 7 | 8 | 9 | ## Compile 10 | 11 | Make sure you have the compile option enabled before compiling the project. 12 | 13 | ``` 14 | make menuconfig 15 | -> gl-inet-ble 16 | -> libglble...................................... GL inet BLE driver library 17 | -> gl-bleAdvLegacy........................... GL inet BLE Legacy Advertising 18 | 19 | ``` 20 | 21 | 22 | 23 | ## Using the example 24 | 25 | You can use SCP or other means to upload example ipk to the device. 26 | 27 | 28 | 29 | ### install 30 | 31 | ```shell 32 | opkg install libglble_2.0.0_mipsel_24kc.ipk 33 | opkg install gl-bleAdvLegacy_2.0.0_mipsel_24kc.ipk 34 | ``` 35 | 36 | 37 | 38 | ### Using 39 | 40 | ```shell 41 | bleAdvLegacy [json_file_path] 42 | -> json_file_path : The path of configuration parameter json file. 43 | ``` 44 | 45 | **json file parameter(“-” means you must set this parameter, "/" means optional parameter.)** 46 | 47 | | | key | value_type | descriptiion | 48 | | ---- | --------------- | ---------- | ------------------------------------------------------------ | 49 | | - | interval_min | int | Minimum Legacy advertising interval.Value in units of 0.625 ms
Range: 0x20 to 0xFFFFFF, Time range: 20 ms to 10485.759375 s | 50 | | - | interval_max | int | Maximum Legacy advertising interval. Value in units of 0.625 ms
Range: 0x20 to 0xFFFFFF, Time range: 20 ms to 10485.759375 s | 51 | | - | discover | int | Define the discoverable mode.
0: Not discoverable
1: Discoverable by both limited and general discovery procedures
2: Discoverable by the general discovery procedure
3: Send legacy advertising and/or scan response data defined by the user.
The limited/general discoverable flags are defined by the user. | 52 | | - | connect | int | Define the Legacy Advertising connectable mode.
0: Undirected non-connectable and non-scannable legacy advertising
2: Undirected connectable and scannable legacy advertising
3: Undirected scannable and non-connectable legacy advertising | 53 | | / | legacy_adv_data | string | Customized non-targeted advertising data. Must be hexadecimal ASCII. Like “020106”.
The maximum size is 31 bytes. | 54 | | / | legacy_rsp_data | string | Customized non-targeted scan respone data. Must be hexadecimal ASCII. Like “020106”.
The maximum size is 31 bytes. | 55 | 56 | 57 | 58 | ### demonstrate 59 | 60 | **note** 61 | 62 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 63 | 64 | ```shell 65 | root@OpenWrt:~# bleAdvLegacy ./legacy_adv.json 66 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 67 | The ble module firmware version is not 4_2_0, please switch it. 68 | ``` 69 | 70 | 71 | 72 | - customize parameters 73 | 74 | ```shell 75 | #1. Create the json file and write the parameter 76 | root@OpenWrt:~# vim legacy_adv.json 77 | ``` 78 | 79 | ```shell 80 | #2. The template of json file 81 | { 82 | "interval_min": 160, 83 | "interval_max": 320, 84 | "discover": 3, 85 | "connect": 3, 86 | "legacy_adv_data": "0201060709474c5f424c45", 87 | "legacy_rsp_data": "05ff74657374" 88 | } 89 | ``` 90 | 91 | ```shell 92 | #3. Run the example 93 | root@OpenWrt:~# bleAdvLegacy ./legacy_adv.json 94 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 95 | Broadcasting data, the mac of the current device is > 94:de:b8:f1:35:1a 96 | ``` 97 | 98 | You can use example [bleScanner](../bleScanner/README.md) to specify address scan it. 99 | 100 | ```shell 101 | root@OpenWrt:~# bleScanner 1 16 16 1 2 94:de:b8:f1:35:1a 102 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 103 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "event_flags": 2, "bonding": 255, "data": "0201060709474c5f424c45" } 104 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -12, "event_flags": 2, "bonding": 255, "data": "0201060709474c5f424c45" } 105 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 8, "bonding": 255, "data": "05ff74657374" } 106 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "event_flags": 2, "bonding": 255, "data": "0201060709474c5f424c45" } 107 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -9, "event_flags": 2, "bonding": 255, "data": "0201060709474c5f424c45" } 108 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 2, "bonding": 255, "data": "0201060709474c5f424c45" } 109 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -9, "event_flags": 8, "bonding": 255, "data": "05ff74657374" } 110 | ``` 111 | 112 | - default parameters 113 | 114 | The default parameters is [interval_min:160] [interval_max:320] [discover:2] [connect:2] [data0:NULL] [data1:NULL]. 115 | 116 | ```shell 117 | root@OpenWrt:~# bleAdvLegacy 118 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 119 | Broadcasting data, the mac of the current device is > 94:de:b8:f1:35:1a 120 | ``` 121 | 122 | You can use example [bleScanner](../bleScanner/README.md) to specify address scan it. 123 | 124 | ```shell 125 | root@OpenWrt:~# bleScanner 94:de:b8:f1:35:1a 126 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 127 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "event_flags": 3, "bonding": 255, "data": "0201060f0953696c616273204578616d706c65" } 128 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 3, "bonding": 255, "data": "0201060f0953696c616273204578616d706c65" } 129 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 3, "bonding": 255, "data": "0201060f0953696c616273204578616d706c65" } 130 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 3, "bonding": 255, "data": "0201060f0953696c616273204578616d706c65" } 131 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -11, "event_flags": 3, "bonding": 255, "data": "0201060f0953696c616273204578616d706c65" } 132 | 133 | ``` 134 | 135 | 136 | 137 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 138 | -------------------------------------------------------------------------------- /src/example/bleAdvLegacy/demo_bleAdvLegacy.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleAdvLegacy.c 3 | * @brief Enable BLE Legacy broadcast sending function 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gl_errno.h" 29 | #include "gl_type.h" 30 | #include "gl_bleapi.h" 31 | 32 | static void sigal_hander(int sig); 33 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 34 | 35 | #define MAC2STR(a) (a)[5], (a)[4], (a)[3], (a)[2], (a)[1], (a)[0] 36 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 37 | 38 | static bool module_work = false; 39 | static uint8_t handle = 0xff; 40 | 41 | 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | signal(SIGTERM, sigal_hander); 46 | signal(SIGINT, sigal_hander); 47 | signal(SIGQUIT, sigal_hander); 48 | 49 | // init msg callback 50 | gl_ble_cbs ble_cb; 51 | memset(&ble_cb, 0, sizeof(gl_ble_cbs)); 52 | 53 | ble_cb.ble_gap_event = NULL; 54 | ble_cb.ble_gatt_event = NULL; 55 | ble_cb.ble_module_event = ble_module_cb; 56 | 57 | // init adv param 58 | uint32_t interval_min = 160; 59 | uint32_t interval_max = 320; 60 | uint8_t discover = 2; 61 | uint8_t connect = 2; 62 | 63 | //init adv data param 64 | const char *data0 = NULL; 65 | const char *data1 = NULL; 66 | 67 | json_object *file_o = NULL; 68 | 69 | if ((argc != 1) && (argc != 2)) 70 | { 71 | goto exit; 72 | } 73 | 74 | if (argc == 2) 75 | { 76 | file_o = json_object_from_file(argv[1]); 77 | if(file_o == NULL) 78 | { 79 | goto exit; 80 | } 81 | 82 | json_object *interval_min_o = json_object_object_get(file_o, "interval_min"); 83 | if(interval_min_o == NULL) 84 | { 85 | goto exit; 86 | } 87 | interval_min = json_object_get_int(interval_min_o); 88 | 89 | json_object *interval_max_o = json_object_object_get(file_o, "interval_max"); 90 | if(interval_max_o == NULL) 91 | { 92 | goto exit; 93 | } 94 | interval_max = json_object_get_int(interval_max_o); 95 | 96 | json_object *discover_o = json_object_object_get(file_o, "discover"); 97 | if(discover_o == NULL) 98 | { 99 | goto exit; 100 | } 101 | discover = json_object_get_int(discover_o); 102 | 103 | json_object *connect_o = json_object_object_get(file_o, "connect"); 104 | if(connect_o == NULL) 105 | { 106 | goto exit; 107 | } 108 | connect = json_object_get_int(connect_o); 109 | 110 | json_object *legacy_adv_data_o = json_object_object_get(file_o, "legacy_adv_data"); 111 | if(legacy_adv_data_o != NULL) 112 | { 113 | data0 = json_object_get_string(legacy_adv_data_o); 114 | } 115 | 116 | json_object *legacy_rsp_data_o = json_object_object_get(file_o, "legacy_rsp_data"); 117 | if(legacy_rsp_data_o != NULL) 118 | { 119 | data1 = json_object_get_string(legacy_rsp_data_o); 120 | } 121 | 122 | json_object_put(file_o); 123 | } 124 | 125 | 126 | // init ble module 127 | GL_RET ret; 128 | ret = gl_ble_init(); 129 | if (GL_SUCCESS != ret) 130 | { 131 | printf("gl_ble_init failed: %d\n", ret); 132 | exit(-1); 133 | } 134 | 135 | ret = gl_ble_subscribe(&ble_cb); 136 | if (GL_SUCCESS != ret) 137 | { 138 | printf("gl_ble_subscribe failed: %d\n", ret); 139 | exit(-1); 140 | } 141 | 142 | // ble module check, will auto update firmware if module firmware not work. 143 | // after update firmware if not work, will exit the program. 144 | ret = gl_ble_check_module(&ble_cb, false); 145 | if(ret != GL_SUCCESS) 146 | { 147 | printf("The ble module firmware not work.\n"); 148 | exit(-1); 149 | } 150 | 151 | // wait for module reset 152 | while (!module_work) 153 | { 154 | usleep(100000); 155 | } 156 | 157 | // create adv handle 158 | ret = gl_ble_create_adv_handle(&handle); 159 | if (GL_SUCCESS != ret) 160 | { 161 | printf("gl_ble_create_adv_handle failed: %d\n", ret); 162 | exit(-1); 163 | } 164 | 165 | // set advertising data 166 | if (data0) 167 | { 168 | ret = gl_ble_set_legacy_adv_data(handle, 0, data0); 169 | if (GL_SUCCESS != ret) 170 | { 171 | printf("gl_ble_set_legacy_adv_data failed: %d\n", ret); 172 | exit(-1); 173 | } 174 | } 175 | if (data1) 176 | { 177 | ret = gl_ble_set_legacy_adv_data(handle, 1, data1); 178 | if (GL_SUCCESS != ret) 179 | { 180 | printf("gl_ble_set_legacy_adv_data failed: %d\n", ret); 181 | exit(-1); 182 | } 183 | } 184 | 185 | // start advertising 186 | ret = gl_ble_start_legacy_adv(handle, interval_min, interval_max, discover, connect); 187 | if (GL_SUCCESS != ret) 188 | { 189 | printf("gl_ble_start_legacy_adv failed: %d\n", ret); 190 | exit(-1); 191 | } 192 | 193 | //get ble mac 194 | uint8_t mac_buf[6]; 195 | ret = gl_ble_get_mac(mac_buf); 196 | if (GL_SUCCESS != ret) 197 | { 198 | printf("gl_ble_get_mac failed: %d\n", ret); 199 | exit(-1); 200 | } 201 | printf("Broadcasting data, the mac of the current device is > " MACSTR "\n", MAC2STR(mac_buf)); 202 | 203 | while (1) 204 | { 205 | sleep(1000); 206 | } 207 | 208 | return 0; 209 | 210 | exit: 211 | if(file_o != NULL) 212 | { 213 | json_object_put(file_o); 214 | } 215 | printf("param err!"); 216 | return GL_ERR_PARAM; 217 | } 218 | 219 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 220 | { 221 | switch (event) 222 | { 223 | case MODULE_BLE_SYSTEM_BOOT_EVT: 224 | { 225 | json_object *o = NULL; 226 | o = json_object_new_object(); 227 | json_object_object_add(o, "type", json_object_new_string("module_start")); 228 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 229 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 230 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 231 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 232 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 233 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 234 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 235 | const char *temp = json_object_to_json_string(o); 236 | printf("MODULE_CB_MSG >> %s\n", temp); 237 | 238 | json_object_put(o); 239 | 240 | module_work = true; 241 | 242 | break; 243 | } 244 | default: 245 | break; 246 | } 247 | 248 | return 0; 249 | } 250 | 251 | static void sigal_hander(int sig) 252 | { 253 | printf("\bleAdvertiserLegacy exit!\n"); 254 | 255 | gl_ble_stop_adv(handle); 256 | gl_ble_delete_adv_handle(handle); 257 | gl_ble_unsubscribe(); 258 | gl_ble_destroy(); 259 | 260 | exit(0); 261 | } 262 | -------------------------------------------------------------------------------- /src/example/bleAdvLegacy/docs/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/example/bleAdvLegacy/docs/1.jpg -------------------------------------------------------------------------------- /src/example/bleAdvLegacy/docs/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/example/bleAdvLegacy/docs/2.jpg -------------------------------------------------------------------------------- /src/example/bleAdvPeriodic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleAdvPeriodic" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleAdvPeriodic/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleAdvPeriodic 2 | 3 | Demonstrate how to Periodic broadcast 4 | 5 | This is a demonstration of the user using gl-ble-api to send out a Periodic broadcast. 6 | 7 | 8 | 9 | ## Compile 10 | 11 | Make sure you have the compile option enabled before compiling the project. 12 | 13 | ``` 14 | make menuconfig 15 | -> gl-inet-ble 16 | -> libglble...................................... GL inet BLE driver library 17 | -> gl-bleAdvPeriodic....................... GL inet BLE Periodic Advertising 18 | ``` 19 | 20 | 21 | 22 | ## Using the example 23 | 24 | You can use SCP or other means to upload example ipk to the device. 25 | 26 | 27 | 28 | ### install 29 | 30 | ```shell 31 | opkg install libglble_2.0.0_mipsel_24kc.ipk 32 | opkg install gl-bleAdvPeriodic_2.0.0_mipsel_24kc.ipk 33 | ``` 34 | 35 | 36 | 37 | ### Using 38 | 39 | **note** 40 | 41 | > Bluetooth 5.0 introduces 40 RF channels are defined in the 2.4GHz ISM band. These RF channels are allocated into three LE physical channels: advertising, periodic, and data. These RF channels are divided into 3 RF channels(37,38,39), known as the "**primary advertising channel**", used for initial advertising and all legacy advertising activities, and 37 RF channels(0~36), known as the "**secondary advertising channel**", used for the majority of the communications involved. The periodic physical channel uses the same RF channels as the secondary advertising channel over the advertising physical channel. 42 | > 43 | > The mandatory symbol rate is 1 megasymbol per second (Msym/s), where 1 symbol represents 1 bit therefore supporting a bit rate of 1 megabit per second (Mb/s), which is referred to as the **LE 1M PHY**. The 1 Msym/s symbol rate may optionally support error correction coding, which is referred to as the **LE Coded PHY**. This may use either of two coding schemes: S=2, where 2 symbols represent 1 bit therefore supporting a bit rate of 500 kb/s, and S=8, where 8 symbols represent 1 bit therefore supporting a bit rate of 125 kb/s. An optional symbol rate of 2 Msym/s may be supported, with a bit rate of 2 Mb/s, which is referred to as the LE 2M PHY. The 2 Msym/s symbol rate supports uncoded data only. LE 1M and LE 2M are collectively referred to as the **LE Uncoded PHYs**. 44 | > 45 | > 2M PHY ensures **higher data throughput**. A new long range PHY (LE Coded PHY) with 125kbps and 500kbps coding which **gives range gains of 1.5-2x with improved sensitivity of 4 to 6dB**. The LE Coded PHY uses 1Mbit PHY but payload is coded at 125kbps or 500kbps. It also adds Forward Error Correction and Pattern Mapper. 46 | 47 | ```shell 48 | bleAdvPeriodic [json_file_path] 49 | -> json_file_path : The path of configuration parameter json file. 50 | ``` 51 | 52 | **json file parameter(“-” means you must set this parameter, "/" means optional parameter.)** 53 | 54 | | | key | value_type | descriptiion | 55 | | ---- | ----------------- | ---------- | ------------------------------------------------------------ | 56 | | - | primary_phy | int | The PHY on which the advertising packets are transmitted on the primary advertising channel.
(1M PHY must be used when Legacy Advertising, Legacy Advertising ignore this parameter)
1: LE 1M PHY 4: LE Coded PHY | 57 | | - | secondary_phy | int | The PHY on which the advertising packets are transmitted on the secondary advertising channel.
(1M PHY must be used when Legacy Advertising, Legacy Advertising ignore this parameter)
1: LE 1M PHY 2: LE 2M PHY 4: LE Coded PHY | 58 | | - | interval_min | int | Minimum periodic advertising interval. Value in units of 1.25 ms
Range: 0x06 to 0xFFFF, Time range: 7.5 ms to 81.92 s | 59 | | - | interval_max | int | Maximum periodic advertising interval. Value in units of 1.25 ms
Range: 0x06 to 0xFFFF, Time range: 7.5 ms to 81.92 s | 60 | | / | periodic_adv_data | string | Customized non-targeted advertising data. Must be hexadecimal ASCII. Like “020106”.
The maximum size is 1024 bytes. | 61 | 62 | The Periodic advertising interval you set should be smaller than synchronize timeout. If not, it will breaks the established synchronization. 63 | 64 | 65 | 66 | #### demonstrate 67 | 68 | **note** 69 | 70 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 71 | 72 | ```shell 73 | root@OpenWrt:~# bleAdvPeriodic ./periodic_adv.json 74 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 75 | The ble module firmware version is not 4_2_0, please switch it. 76 | ``` 77 | 78 | 79 | 80 | - customize parameters 81 | 82 | ```shell 83 | #1. Create the json file and write the parameter 84 | root@OpenWrt:~# vim periodic_adv.json 85 | ``` 86 | 87 | ```shell 88 | #2. The template of json file 89 | { 90 | "primary_phy": 1, 91 | "secondary_phy": 1, 92 | "interval_min": 80, 93 | "interval_max": 160, 94 | "periodic_adv_data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" 95 | } 96 | ``` 97 | 98 | ```shell 99 | #3. Run the example 100 | root@OpenWrt:~# bleAdvPeriodic ./periodic_adv.json 101 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 102 | Broadcasting data, the mac of the current device is > 94:de:b8:f1:35:1a 103 | ``` 104 | 105 | You can use example [bleSynchronize](../bleSynchronize/README.md) to Synchronize it. 106 | 107 | ```shell 108 | root@OpenWrt:~# bleSynchronize 109 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 110 | GAP_CB_MSG >> { "type": "periodic_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "adv_sid": 0, "periodic_interval": 120 } 111 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 112 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -11, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 113 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 114 | ``` 115 | 116 | - default parameters 117 | 118 | The default parameters is [primary_phy:1] [secondary_phy:1] [interval_min:80] [interval_max:160] [data:NULL]. 119 | 120 | ```shell 121 | root@OpenWrt:~# bleAdvPeriodic 122 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 123 | Broadcasting data, the mac of the current device is > 94:de:b8:f1:35:1a 124 | ``` 125 | 126 | You can use example [bleSynchronize](../bleSynchronize/README.md) to Synchronize it. 127 | 128 | ```shell 129 | root@OpenWrt:~# bleSynchronize 130 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 131 | GAP_CB_MSG >> { "type": "periodic_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "adv_sid": 0, "periodic_interval": 120 } 132 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "" } 133 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "" } 134 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "" } 135 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "" } 136 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -11, "data": "" } 137 | ``` 138 | 139 | 140 | 141 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 142 | 143 | -------------------------------------------------------------------------------- /src/example/bleAdvPeriodic/demo_bleAdvPeriodic.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleAdvPeriodic.c 3 | * @brief Enable BLE Periodic broadcast sending function 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gl_errno.h" 29 | #include "gl_type.h" 30 | #include "gl_bleapi.h" 31 | 32 | static void sigal_hander(int sig); 33 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 34 | 35 | #define MAC2STR(a) (a)[5], (a)[4], (a)[3], (a)[2], (a)[1], (a)[0] 36 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 37 | 38 | static bool module_work = false; 39 | static uint8_t handle = 0xff; 40 | 41 | 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | signal(SIGTERM, sigal_hander); 46 | signal(SIGINT, sigal_hander); 47 | signal(SIGQUIT, sigal_hander); 48 | 49 | // init msg callback 50 | gl_ble_cbs ble_cb; 51 | memset(&ble_cb, 0, sizeof(gl_ble_cbs)); 52 | 53 | ble_cb.ble_gap_event = NULL; 54 | ble_cb.ble_gatt_event = NULL; 55 | ble_cb.ble_module_event = ble_module_cb; 56 | 57 | // init adv param 58 | uint8_t primary_phy = 1; 59 | uint8_t secondary_phy = 1; 60 | uint16_t interval_min = 80; 61 | uint16_t interval_max = 160; 62 | //init adv data param 63 | const char *data = NULL; 64 | 65 | json_object *file_o = NULL; 66 | 67 | if ((argc != 1) && (argc != 2)) 68 | { 69 | goto exit; 70 | } 71 | 72 | if (argc == 2) 73 | { 74 | file_o = json_object_from_file(argv[1]); 75 | if(file_o == NULL) 76 | { 77 | goto exit; 78 | } 79 | 80 | json_object *primary_phy_o = json_object_object_get(file_o, "primary_phy"); 81 | if(primary_phy_o == NULL) 82 | { 83 | goto exit; 84 | } 85 | primary_phy = json_object_get_int(primary_phy_o); 86 | 87 | json_object *secondary_phy_o = json_object_object_get(file_o, "secondary_phy"); 88 | if(secondary_phy_o == NULL) 89 | { 90 | goto exit; 91 | } 92 | secondary_phy = json_object_get_int(secondary_phy_o); 93 | 94 | json_object *interval_min_o = json_object_object_get(file_o, "interval_min"); 95 | if(interval_min_o == NULL) 96 | { 97 | goto exit; 98 | } 99 | interval_min = json_object_get_int(interval_min_o); 100 | 101 | json_object *interval_max_o = json_object_object_get(file_o, "interval_max"); 102 | if(interval_max_o == NULL) 103 | { 104 | goto exit; 105 | } 106 | interval_max = json_object_get_int(interval_max_o); 107 | 108 | json_object *periodic_adv_data_o = json_object_object_get(file_o, "periodic_adv_data"); 109 | if(periodic_adv_data_o != NULL) 110 | { 111 | data = json_object_get_string(periodic_adv_data_o); 112 | } 113 | 114 | json_object_put(file_o); 115 | } 116 | 117 | // init ble module 118 | GL_RET ret; 119 | ret = gl_ble_init(); 120 | if (GL_SUCCESS != ret) 121 | { 122 | printf("gl_ble_init failed: %d\n", ret); 123 | exit(-1); 124 | } 125 | 126 | ret = gl_ble_subscribe(&ble_cb); 127 | if (GL_SUCCESS != ret) 128 | { 129 | printf("gl_ble_subscribe failed: %d\n", ret); 130 | exit(-1); 131 | } 132 | 133 | // ble module check, will auto update firmware if module firmware not work. 134 | // after update firmware if not work, will exit the program. 135 | ret = gl_ble_check_module(&ble_cb, false); 136 | if(ret != GL_SUCCESS) 137 | { 138 | printf("The ble module firmware not work.\n"); 139 | exit(-1); 140 | } 141 | 142 | // wait for module reset 143 | while (!module_work) 144 | { 145 | usleep(100000); 146 | } 147 | 148 | // create adv handle 149 | ret = gl_ble_create_adv_handle(&handle); 150 | if (GL_SUCCESS != ret) 151 | { 152 | printf("gl_ble_create_adv_handle failed: %d\n", ret); 153 | exit(-1); 154 | } 155 | 156 | // set advertising data 157 | if (data) 158 | { 159 | ret = gl_ble_set_periodic_adv_data(handle, data); 160 | if (GL_SUCCESS != ret) 161 | { 162 | printf("gl_ble_set_periodic_adv_data failed: %d\n", ret); 163 | exit(-1); 164 | } 165 | } 166 | 167 | // start advertising 168 | ret = gl_ble_start_periodic_adv(handle, primary_phy, secondary_phy, interval_min, interval_max); 169 | if (GL_SUCCESS != ret) 170 | { 171 | printf("gl_ble_start_periodic_adv failed: %d\n", ret); 172 | exit(-1); 173 | } 174 | 175 | //get ble mac 176 | uint8_t mac_buf[6]; 177 | ret = gl_ble_get_mac(mac_buf); 178 | if (GL_SUCCESS != ret) 179 | { 180 | printf("gl_ble_get_mac failed: %d\n", ret); 181 | exit(-1); 182 | } 183 | printf("Broadcasting data, the mac of the current device is > " MACSTR "\n", MAC2STR(mac_buf)); 184 | 185 | while (1) 186 | { 187 | sleep(1000); 188 | } 189 | 190 | return 0; 191 | 192 | exit: 193 | if(file_o != NULL) 194 | { 195 | json_object_put(file_o); 196 | } 197 | printf("param err!"); 198 | return GL_ERR_PARAM; 199 | } 200 | 201 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 202 | { 203 | switch (event) 204 | { 205 | case MODULE_BLE_SYSTEM_BOOT_EVT: 206 | { 207 | 208 | json_object *o = NULL; 209 | o = json_object_new_object(); 210 | json_object_object_add(o, "type", json_object_new_string("module_start")); 211 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 212 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 213 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 214 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 215 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 216 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 217 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 218 | const char *temp = json_object_to_json_string(o); 219 | printf("MODULE_CB_MSG >> %s\n", temp); 220 | 221 | json_object_put(o); 222 | 223 | module_work = true; 224 | 225 | break; 226 | } 227 | default: 228 | break; 229 | } 230 | 231 | return 0; 232 | } 233 | 234 | static void sigal_hander(int sig) 235 | { 236 | printf("\bleAdvertiserPeriodic exit!\n"); 237 | 238 | gl_ble_stop_adv(handle); 239 | gl_ble_delete_adv_handle(handle); 240 | gl_ble_unsubscribe(); 241 | gl_ble_destroy(); 242 | 243 | exit(0); 244 | } 245 | -------------------------------------------------------------------------------- /src/example/bleAdvPeriodic/docs/DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gl-inet/gl-ble-sdk/158350e81e10df0ca823dfaefb7c8f951d373ec1/src/example/bleAdvPeriodic/docs/DA47BC2C-B7A3-44b7-9CC7-8FD3EAC2F89A.png -------------------------------------------------------------------------------- /src/example/bleClient/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleClient" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleClient/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleClient 2 | 3 | This example is used to connect to the BLE server and send data (it needs to be used with [bleService](../bleService/README.md)) 4 | 5 | This is a demonstration of the user using gl-ble-api to send out a ble broadcast and get the result. 6 | 7 | 8 | 9 | ## Compile 10 | 11 | Make sure you have the compile option enabled before compiling the project. 12 | 13 | ``` 14 | make menuconfig 15 | -> gl-inet-ble 16 | -> libglble...................................... GL inet BLE driver library 17 | -> gl-bleClient.......................................... GL inet BLE Client 18 | ``` 19 | 20 | 21 | 22 | ## Using the example 23 | 24 | You can use SCP or other means to upload example ipk to the device. 25 | 26 | 27 | 28 | ### install 29 | 30 | ```shell 31 | opkg install libglble_2.0.0_mipsel_24kc.ipk 32 | opkg install gl-bleClient_2.0.0_mipsel_24kc.ipk 33 | ``` 34 | 35 | 36 | 37 | ### Using 38 | 39 | **note** 40 | 41 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 42 | 43 | ```shell 44 | root@OpenWrt:~# bleClient 94:de:b8:f1:35:1a 45 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 46 | The ble module firmware version is not 4_2_0, please switch it. 47 | ``` 48 | 49 | 50 | 51 | **format** 52 | 53 | ```shell 54 | bleClient [address:"88:88:88:88:88:88"] 55 | -> address: The MAC of the device to be connected (lower-case) 56 | ``` 57 | 58 | ```shell 59 | root@OpenWrt:~# bleClient 94:de:b8:f1:35:1a 60 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 61 | GAP_CB_MSG >> { "type": "connect_open", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "connect_role": 1, "bonding": 255, "advertiser": 255 } 62 | GAP_CB_MSG >> { "type": "connect_update", "mac": "94:de:b8:f1:35:1a", "interval": 22, "latency": 0, "timeout": 100, "security_mode": 0, "txsize": 27 } 63 | GAP_CB_MSG >> { "type": "connect_update", "mac": "94:de:b8:f1:35:1a", "interval": 22, "latency": 0, "timeout": 100, "security_mode": 0, "txsize": 251 } 64 | { "service_list": [ { "service_handle": 65544, "service_uuid": "1801" }, { "service_handle": 589837, "service_uuid": "1800" }, { "service_handle": 983039, "service_uuid": "180a" } ] } 65 | { "characteristic_list": [ { "characteristic_handle": 3, "properties": 32, "characteristic_uuid": "2a05" }, { "characteristic_handle": 6, "properties": 2, "characteristic_uuid": "2b2a" }, { "characteristic_handle": 8, "properties": 10, "characteristic_uuid": "2b29" } ] } 66 | { "characteristic_list": [ { "characteristic_handle": 11, "properties": 10, "characteristic_uuid": "2a00" }, { "characteristic_handle": 13, "properties": 2, "characteristic_uuid": "2a01" } ] } 67 | { "characteristic_list": [ { "characteristic_handle": 16, "properties": 2, "characteristic_uuid": "2a29" }, { "characteristic_handle": 18, "properties": 2, "characteristic_uuid": "2a23" } ] } 68 | Data from the server : Hello Client . 69 | ``` 70 | 71 | 72 | 73 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. -------------------------------------------------------------------------------- /src/example/bleIbeacon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleIbeacon" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | add_executable( ${EXEC_NAME} ${SOURCES} ) 10 | 11 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 12 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ubox ubus blobmsg_json) 13 | 14 | 15 | install( 16 | TARGETS ${EXEC_NAME} 17 | RUNTIME DESTINATION bin 18 | ) -------------------------------------------------------------------------------- /src/example/bleIbeacon/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleIBeacon 2 | 3 | This Demo is used to send or receive ibeacon packets. There are two run modes, foreground mode and background mode. 4 | 5 | Foreground mode: 6 | 7 | It interacts through the command line. You can use it to send or receive ibeacon packet simply. 8 | 9 | Background mode: 10 | 11 | If you want to add ibeacon functionality to your code, here is a ubus interface to facilitate your implementation. 12 | 13 | 14 | 15 | ## Compile 16 | 17 | Make sure you have the compile option enabled before compiling the project. 18 | 19 | ``` 20 | make menuconfig 21 | -> gl-inet-ble 22 | -> libglble...................................... GL inet BLE driver library 23 | -> gl-bleIbeacon........................................ GL inet BLE Ibeacon 24 | ``` 25 | 26 | 27 | 28 | ## Using the example 29 | 30 | You can use SCP or other means to upload example ipk to the device. 31 | 32 | 33 | 34 | ### install 35 | 36 | ```shell 37 | opkg install libglble_2.0.0_mips_24kc.ipk 38 | opkg install gl-bleIbeacon_2.0.0_mips_24kc.ipk 39 | ``` 40 | 41 | 42 | 43 | ### Using 44 | 45 | **note** 46 | 47 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 48 | 49 | ```shell 50 | root@OpenWrt:~# bleIbeacon 51 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 52 | The ble module firmware version is not 4_2_0, please switch it. 53 | ``` 54 | 55 | 56 | 57 | #### Foreground mode 58 | 59 | ##### send 60 | 61 | ```shell 62 | bleIbeacon send [rsp_type] [proximity_uuid] [major] [minor] [measured_power] [measured_power] [tx_power] 63 | 64 | -> rsp_type: Whether to send a scan response packet. 65 | rsp_close: no send scan response packet 66 | rsp_open: send scan response packet 67 | -> proximity_uuid: 16 bytes. Application developers should define a UUID specific to their app and deployment use case. 68 | Must not be set to all 0s. 69 | -> major: 2 bytes. Further specifies a specific iBeacon and use case. For example, this could define a sub-region within a larger region defined by the UUID. 70 | -> minor: 2 bytes. Allows further subdivision of region or use case, specified by the application developer. 71 | -> measured_power: 1 bytes. Apple devices use the Measured Power value of a Proximity Beacon to help with ranging accuracy. 72 | -> tx_power: This item is optional, leave it blank and leave it unset. Set the global power level(0.1 dBm steps). 73 | ``` 74 | 75 | ###### demonstrate 76 | 77 | ```shell 78 | #unset tx_power 79 | root@OpenWrt:~# bleIbeacon send rsp_close 11112222333344445555777766668888 0001 0002 50 80 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 81 | 82 | foreground mode 83 | data: 0201061aff004c1502111122223333444455557777666688880001000250 84 | Broadcasting ibeacon data, the mac of the current device is > 94:de:b8:f1:35:1a 85 | ``` 86 | 87 | ```shell 88 | #set tx_power 89 | root@OpenWrt:~# bleIbeacon send rsp_close 11112222333344445555777766668888 0001 0002 50 50 90 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 91 | 92 | foreground mode 93 | data: 0201061aff004c1502111122223333444455557777666688880001000250 94 | { "code": 0, "current_power": 51 } 95 | Broadcasting ibeacon data, the mac of the current device is > 94:de:b8:f1:35:1a 96 | ``` 97 | 98 | ##### recieve 99 | 100 | ```shell 101 | bleIbeacon recieve [scan_type:passive_scan] 102 | -> rsp_type: Scan type. 103 | passive_scan: Passive scanning 104 | active_scan: Active scanning 105 | ``` 106 | 107 | ###### demonstrate 108 | 109 | ```shell 110 | root@OpenWrt:~# bleIbeacon recieve passive_scan 111 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 112 | 113 | foreground mode 114 | passive scan 115 | { "type": "Beacon", "mac": "ac:23:3f:5e:03:1d", "address_type": 0, "rssi": -69, "packet_type": 0, "bonding": 255, "proximity_uuid": "fda50693a4e24fb1afcfc6eb07647825", "major": "2711", "minor": "2711", "measured_power": -59 } 116 | { "type": "Beacon", "mac": "d8:96:e0:8b:7d:f2", "address_type": 0, "rssi": -52, "packet_type": 0, "bonding": 255, "proximity_uuid": "17320508075688772935274463415059", "major": "0001", "minor": "0001", "measured_power": -59 } 117 | { "type": "Beacon", "mac": "d8:96:e0:8b:7e:02", "address_type": 0, "rssi": -55, "packet_type": 0, "bonding": 255, "proximity_uuid": "17320508075688772935274463415059", "major": "0001", "minor": "0001", "measured_power": -59 } 118 | { "type": "Beacon", "mac": "d8:96:e0:8b:7d:e9", "address_type": 0, "rssi": -79, "packet_type": 0, "bonding": 255, "proximity_uuid": "17320508075688772935274463415059", "major": "0001", "minor": "0001", "measured_power": -59 } 119 | { "type": "Beacon", "mac": "ac:23:3f:5e:03:1d", "address_type": 0, "rssi": -73, "packet_type": 0, "bonding": 255, "proximity_uuid": "fda50693a4e24fb1afcfc6eb07647825", "major": "2711", "minor": "2711", "measured_power": -59 } 120 | ``` 121 | 122 | 123 | 124 | 125 | 126 | #### Background mode 127 | 128 | Firstly, Run the bleIbeacon program without parameters. 129 | 130 | ```shell 131 | root@OpenWrt:~# bleIbeacon 132 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 133 | 134 | background mode 135 | 136 | ``` 137 | 138 | And then, you can check the ubus invoke obj(ibeacon) like this. 139 | 140 | ```shell 141 | root@OpenWrt:~# ubus -v list ibeacon 142 | 'ibeacon' @5d6b5db6 143 | "recieve":{"scan_type":"String","stop_scan":"String"} 144 | "send":{"rsp_type":"String","uuid":"String","major":"String","minor":"String","measured_power":"String","tx_power":"String","stop_send":"String"} 145 | ``` 146 | 147 | 148 | 149 | ##### send 150 | 151 | ``` 152 | "send":{"rsp_type":"String","uuid":"String","major":"String","minor":"String","measured_power":"String","tx_power":"String","stop_send":"String"} 153 | 154 | -> rsp_type: Whether to send a scan response packet. 155 | rsp_close: no send scan response packet 156 | rsp_open: send scan response packet 157 | -> uuid: 16 bytes. Application developers should define a UUID specific to their app and deployment use case. 158 | Must not be set to all 0s. 159 | -> major: 2 bytes. Further specifies a specific iBeacon and use case. For example, this could define a sub-region within a larger region defined by the UUID. 160 | -> minor: 2 bytes. Allows further subdivision of region or use case, specified by the application developer. 161 | -> measured_power: 1 bytes. Apple devices use the Measured Power value of a Proximity Beacon to help with ranging accuracy. 162 | -> tx_power: This item is optional, leave it blank and leave it unset. Set the global power level(0.1 dBm steps). 163 | -> stop_send: It is use for stop to send ibeacon packet. 164 | true: stop to send ibeacon packet 165 | ``` 166 | 167 | ###### demonstrate 168 | 169 | ```shell 170 | #unset tx_power 171 | root@OpenWrt:~# ubus call ibeacon send '{"rsp_type":"rsp_close","uuid":"12345678123456781234567812345678","major":"0003","minor":"0005","measured_power":"50"}' 172 | { 173 | "code": 0 174 | } 175 | ``` 176 | 177 | ```shell 178 | #set tx_power 179 | root@OpenWrt:~# ubus call ibeacon send '{"rsp_type":"rsp_close","uuid":"12345678123456781234567812345678","major":"0003","minor":"0005","measured_power":"50","tx_power":"50"}' 180 | { 181 | "current_power": 51, 182 | "code": 0 183 | } 184 | ``` 185 | 186 | ```shell 187 | #stop send 188 | root@OpenWrt:~# ubus call ibeacon send '{"stop_send":"true"}' 189 | { 190 | "code": 0 191 | } 192 | ``` 193 | 194 | 195 | 196 | ##### recieve 197 | 198 | ``` 199 | "recieve":{"scan_type":"String","stop_scan":"String"} 200 | 201 | -> rsp_type: Scan type. 202 | passive_scan: Passive scanning 203 | active_scan: Active scanning 204 | -> stop_scan: It is use for stop to recieve ibeacon packet. 205 | true: stop to recieve ibeacon packet 206 | ``` 207 | 208 | ###### demonstrate 209 | 210 | ```shell 211 | # Set and start scan 212 | root@OpenWrt:~# ubus call ibeacon recieve '{"scan_type": "passive_scan"}' 213 | { 214 | "code": 0 215 | } 216 | 217 | # And then Receive reported ibeacon data through event ibeacon_data 218 | root@OpenWrt:~# ubus listen ibeacon_data 219 | { "ibeacon_data": {"type":"Beacon","mac":"d8:96:e0:8b:7d:f2","address_type":0,"rssi":-64,"event_flags":3,"bonding":255,"proximity_uuid":"17320508075688772935274463415059","major":"0001","minor":"4ad0","measured_power":-59} } 220 | { "ibeacon_data": {"type":"Beacon","mac":"72:64:21:10:00:d8","address_type":1,"rssi":-66,"event_flags":3,"bonding":255,"proximity_uuid":"fda50693a4e24fb1afcfc6eb07647825","major":"0001","minor":"0002","measured_power":-40} } 221 | { "ibeacon_data": {"type":"Beacon","mac":"d8:96:e0:8b:76:fd","address_type":0,"rssi":-64,"event_flags":3,"bonding":255,"proximity_uuid":"17320508075688772935274463415059","major":"0001","minor":"43db","measured_power":-59} } 222 | ``` 223 | 224 | 225 | 226 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 227 | 228 | -------------------------------------------------------------------------------- /src/example/bleIbeacon/demo_bleIbeacon.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleIbeacon.c 3 | * @brief Enable BLE broadcast or discovery ibeacon packet 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "gl_errno.h" 34 | #include "gl_type.h" 35 | #include "gl_bleapi.h" 36 | #include "ibeacon.h" 37 | #include "ubus.h" 38 | #include "run_mode.h" 39 | 40 | bool ibeacon_module_work = false; 41 | 42 | ibeacon_ringArray_t *ibeacon_array; 43 | uint8_t adv_handle = 0xff; 44 | 45 | static pthread_t tid_ble; 46 | static void *ble_start(void *arg); 47 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data); 48 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 49 | static void sigal_ibeacon_hander(int sig); 50 | static int mode = -1; 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | int ret = -1; 55 | 56 | ret = pthread_create(&tid_ble, NULL, ble_start, NULL); 57 | if (ret) { 58 | fprintf(stderr, "ubus_pthread_create: %s\n", strerror(ret)); 59 | return -1; 60 | } 61 | 62 | mode = mode_check(argc); 63 | 64 | signal(SIGTERM, sigal_ibeacon_hander); 65 | signal(SIGINT, sigal_ibeacon_hander); 66 | signal(SIGQUIT, sigal_ibeacon_hander); 67 | if(mode == BACKGROUNG_MODE) 68 | { 69 | ret = background(); 70 | if(ret != GL_SUCCESS) 71 | { 72 | printf("background mode open failed\n"); 73 | exit(-1); 74 | } 75 | } 76 | else if(mode == FOREGROUND_MODE) 77 | { 78 | ret = foreground_param_check(argc, argv); 79 | if(ret != GL_SUCCESS) 80 | { 81 | exit(-1); 82 | } 83 | ret = foreground(argv); 84 | if(ret != GL_SUCCESS) 85 | { 86 | printf("foreground mode open failed\n"); 87 | exit(-1); 88 | } 89 | } 90 | 91 | } 92 | 93 | static void *ble_start(void *arg) 94 | { 95 | GL_RET ret = -1; 96 | ibeacon_array = calloc(1, sizeof(ibeacon_ringArray_t)); 97 | 98 | // init msg callback 99 | gl_ble_cbs ble_ibeacon_cb; 100 | memset(&ble_ibeacon_cb, 0, sizeof(gl_ble_cbs)); 101 | 102 | ble_ibeacon_cb.ble_gap_event = ble_gap_cb; 103 | ble_ibeacon_cb.ble_gatt_event = NULL; 104 | ble_ibeacon_cb.ble_module_event = ble_module_cb; 105 | 106 | // init ble module 107 | ret = gl_ble_init(); 108 | if (GL_SUCCESS != ret) 109 | { 110 | printf("gl_ble_init failed: %d\n", ret); 111 | exit(-1); 112 | } 113 | 114 | ret = gl_ble_subscribe(&ble_ibeacon_cb); 115 | if (GL_SUCCESS != ret) 116 | { 117 | printf("gl_ble_subscribe failed: %d\n", ret); 118 | exit(-1); 119 | } 120 | 121 | // ble module check, will auto update firmware if module firmware not work. 122 | // after update firmware if not work, will exit the program. 123 | ret = gl_ble_check_module(&ble_ibeacon_cb, false); 124 | if(ret != GL_SUCCESS) 125 | { 126 | printf("The ble module firmware not work.\n"); 127 | exit(-1); 128 | } 129 | 130 | // wait for module reset 131 | while (!ibeacon_module_work) 132 | { 133 | usleep(100000); 134 | } 135 | 136 | pthread_join(tid_ble, NULL); 137 | return NULL; 138 | } 139 | 140 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data) 141 | { 142 | 143 | switch (event) 144 | { 145 | case GAP_BLE_LEGACY_SCAN_RESULT_EVT: 146 | { 147 | ibeacon_data_collect(data); 148 | break; 149 | } 150 | default: 151 | break; 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 158 | { 159 | switch (event) 160 | { 161 | case MODULE_BLE_SYSTEM_BOOT_EVT: 162 | { 163 | 164 | json_object *o = NULL; 165 | o = json_object_new_object(); 166 | json_object_object_add(o, "type", json_object_new_string("module_start")); 167 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 168 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 169 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 170 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 171 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 172 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 173 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 174 | const char *temp = json_object_to_json_string(o); 175 | printf("MODULE_CB_MSG >> %s\n", temp); 176 | 177 | json_object_put(o); 178 | 179 | ibeacon_module_work = true; 180 | 181 | break; 182 | } 183 | default: 184 | break; 185 | } 186 | 187 | return 0; 188 | } 189 | 190 | static void sigal_ibeacon_hander(int sig) 191 | { 192 | printf("\nbleIbeacon exit!\n"); 193 | if(mode == FOREGROUND_MODE) 194 | { 195 | goto exit_foreground; 196 | } 197 | else if(mode == BACKGROUNG_MODE) 198 | { 199 | goto exit_background; 200 | } 201 | else 202 | { 203 | exit(0); 204 | } 205 | 206 | exit_background: 207 | 208 | pthread_cancel(ubus_tid); 209 | pthread_join(ubus_tid, NULL); 210 | if (_ctx_event) 211 | ubus_free(_ctx_event); 212 | 213 | if (_ctx_invoke) 214 | ubus_free(_ctx_invoke); 215 | 216 | uloop_done(); 217 | 218 | exit_foreground: 219 | 220 | gl_ble_stop_adv(adv_handle); 221 | gl_ble_stop_discovery(); 222 | gl_ble_destroy(); 223 | pthread_cancel(tid_ble); 224 | 225 | free(ibeacon_array); 226 | exit(0); 227 | } -------------------------------------------------------------------------------- /src/example/bleIbeacon/ibeacon.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "ibeacon.h" 32 | #include "util.h" 33 | 34 | extern ibeacon_ringArray_t *ibeacon_array; 35 | 36 | ble_ibeacon_head_t ibeacon_common_head = { 37 | .flags = {0x02, 0x01, 0x06}, 38 | .length = 0x1A, 39 | .type = 0xFF, 40 | .company_id = 0x4C00, 41 | .beacon_type = 0x0215 42 | }; 43 | 44 | bool is_ibeacon_packet(uint8_t *adv_data, uint8_t adv_data_len) 45 | { 46 | bool result = false; 47 | 48 | if ((adv_data != NULL) && (adv_data_len == 0x1E)){ 49 | if (!memcmp(adv_data, (uint8_t*)&ibeacon_common_head, IBEACON_HEADER_SIZE)){ 50 | result = true; 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | 57 | void ibeacon_data_collect(gl_ble_gap_data_t *data) 58 | { 59 | if(!is_ibeacon_packet(data->legacy_scan_rst.ble_adv, data->legacy_scan_rst.ble_adv_len)) 60 | { 61 | return; 62 | } 63 | 64 | memcpy(&ibeacon_array->data[ibeacon_array->w_count], data, sizeof(gl_ble_gap_data_t)); 65 | ibeacon_array->w_count = (ibeacon_array->w_count + 1) % MAX_DATA_NUM; 66 | 67 | } 68 | 69 | char *get_ibeacon_vendor_field(char *data, uint8_t field, char *buf) 70 | { 71 | switch (field) 72 | { 73 | case PROXIMITY_UUID: 74 | 75 | memcpy(buf, &data[IBEACON_HEADER_SIZE*2], PROXIMITY_UUID_SIZE*2); 76 | break; 77 | 78 | case MAJOR: 79 | 80 | memcpy(buf, &data[IBEACON_HEADER_SIZE*2 + PROXIMITY_UUID_SIZE*2], MAJOR_SIZE*2); 81 | break; 82 | 83 | case MINOR: 84 | 85 | memcpy(buf, &data[IBEACON_HEADER_SIZE*2 + PROXIMITY_UUID_SIZE*2 + MAJOR_SIZE*2], MINOR_SIZE*2); 86 | break; 87 | 88 | case MEASURED_POWER: 89 | 90 | memcpy(buf, &data[IBEACON_HEADER_SIZE*2 + PROXIMITY_UUID_SIZE*2 + MAJOR_SIZE*2 + MINOR_SIZE*2], MEASURED_POWER_SIZE*2); 91 | break; 92 | 93 | default: 94 | break; 95 | } 96 | 97 | return buf; 98 | } 99 | 100 | json_object *get_ibeacon_vendor(void) 101 | { 102 | char address[BLE_MAC_LEN] = {0}; 103 | char ble_adv[MAX_LEGACY_ADV_DATA_LEN * 2 + 1] = {0}; 104 | char proximity_uuid[PROXIMITY_UUID_SIZE*2 + 1] = {0}; 105 | char major[MAJOR_SIZE*2 + 1] = {0}; 106 | char minor[MINOR_SIZE*2 + 1] = {0}; 107 | char measured_power[MEASURED_POWER_SIZE*2 + 1] = {0}; 108 | uint8_t power = 0; 109 | 110 | if(ibeacon_array->r_count != ibeacon_array->w_count) 111 | { 112 | addr2str(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.address, address); 113 | hex2str(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.ble_adv, ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.ble_adv_len, ble_adv); 114 | 115 | get_ibeacon_vendor_field(ble_adv, PROXIMITY_UUID, proximity_uuid); 116 | get_ibeacon_vendor_field(ble_adv, MAJOR, major); 117 | get_ibeacon_vendor_field(ble_adv, MINOR, minor); 118 | get_ibeacon_vendor_field(ble_adv, MEASURED_POWER, measured_power); 119 | 120 | str2array(&power, measured_power, strlen(measured_power) / 2); 121 | 122 | // json format 123 | json_object *o = NULL; 124 | o = json_object_new_object(); 125 | json_object_object_add(o, "type", json_object_new_string("Beacon")); 126 | json_object_object_add(o, "mac", json_object_new_string(address)); 127 | json_object_object_add(o, "address_type", json_object_new_int(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.ble_addr_type)); 128 | json_object_object_add(o, "rssi", json_object_new_int(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.rssi)); 129 | json_object_object_add(o, "event_flags", json_object_new_int(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.event_flags)); 130 | json_object_object_add(o, "bonding", json_object_new_int(ibeacon_array->data[ibeacon_array->r_count].legacy_scan_rst.bonding)); 131 | 132 | json_object_object_add(o, "proximity_uuid", json_object_new_string(proximity_uuid)); 133 | json_object_object_add(o, "major", json_object_new_string(major)); 134 | json_object_object_add(o, "minor", json_object_new_string(minor)); 135 | json_object_object_add(o, "measured_power", json_object_new_int((int8_t)power)); 136 | 137 | ibeacon_array->r_count = (ibeacon_array->r_count + 1) % MAX_DATA_NUM; 138 | 139 | return o; 140 | } 141 | else 142 | { 143 | usleep(500000); 144 | } 145 | return NULL; 146 | } -------------------------------------------------------------------------------- /src/example/bleIbeacon/ibeacon.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _IBEACON_H 17 | #define _IBEACON_H 18 | 19 | #include 20 | #include "gl_errno.h" 21 | #include "gl_type.h" 22 | #include "gl_bleapi.h" 23 | /** 24 | * @brief Ibeacon type 25 | * 26 | */ 27 | #define IBEACON_RECIEVER "recieve" 28 | #define IBEACON_SENDER "send" 29 | #define IBEACON_ACTIVE_SCAN "active_scan" 30 | #define IBEACON_PASSIVE_SCAN "passive_scan" 31 | #define IBEACON_SCAN_RSP_OPEN "rsp_open" 32 | #define IBEACON_SCAN_RSP_CLOSE "rsp_close" 33 | 34 | #define IBEACON_SEND_HEADER "0201061aff004c1502" 35 | #define IBEACON_RECIEVE_HEADER "0201061aff4c000215" 36 | 37 | #define IBEACON_PACKET_SIZE 30 38 | #define IBEACON_HEADER_SIZE 9 39 | #define PROXIMITY_UUID_SIZE 16 40 | #define MAJOR_SIZE 2 41 | #define MINOR_SIZE 2 42 | #define MEASURED_POWER_SIZE 1 43 | 44 | #define MAX_DATA_NUM 1024 45 | 46 | /** 47 | * @brief adv/scan parm 48 | * 49 | */ 50 | /* common */ 51 | #define PHYS 1 52 | /* adv */ 53 | #define INTERVAL_MIN 32 54 | #define INTERVAL_MAX 64 55 | /* scan */ 56 | #define INTERVAL 80 57 | #define WINDOW 48 58 | #define SCAN_TYPE 0 59 | #define MODE 1 60 | 61 | /** 62 | * @brief ibeacon payload. 63 | */ 64 | typedef struct { 65 | uint8_t flags[3]; 66 | uint8_t length; 67 | uint8_t type; 68 | uint16_t company_id; 69 | uint16_t beacon_type; 70 | }__attribute__((packed)) ble_ibeacon_head_t; 71 | 72 | typedef struct { 73 | uint8_t proximity_uuid[16]; 74 | uint8_t major[2]; 75 | uint8_t minor[2]; 76 | int8_t measured_power; 77 | }__attribute__((packed)) ble_ibeacon_vendor_t; 78 | 79 | 80 | typedef struct { 81 | ble_ibeacon_head_t ibeacon_head; 82 | ble_ibeacon_vendor_t ibeacon_vendor; 83 | }__attribute__((packed)) ble_ibeacon_t; 84 | 85 | typedef struct 86 | { 87 | uint16_t w_count; 88 | uint16_t r_count; 89 | gl_ble_gap_data_t data[MAX_DATA_NUM]; 90 | }ibeacon_ringArray_t; 91 | 92 | typedef enum 93 | { 94 | PROXIMITY_UUID, 95 | MAJOR, 96 | MINOR, 97 | MEASURED_POWER 98 | }ibeacon_vendor_field_e; 99 | 100 | extern ble_ibeacon_head_t ibeacon_common_head; 101 | 102 | bool is_ibeacon_packet(uint8_t *adv_data, uint8_t adv_data_len); 103 | 104 | void ibeacon_data_collect(gl_ble_gap_data_t *data); 105 | 106 | char *get_ibeacon_vendor_field(char *data, uint8_t field, char *buf); 107 | 108 | json_object *get_ibeacon_vendor(void); 109 | 110 | #endif -------------------------------------------------------------------------------- /src/example/bleIbeacon/run_mode.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "gl_errno.h" 26 | #include "gl_type.h" 27 | #include "gl_bleapi.h" 28 | #include "ibeacon.h" 29 | #include "ubus.h" 30 | #include "run_mode.h" 31 | #include "util.h" 32 | 33 | static uint8_t scan_type = 0; 34 | static int scan_respone = 0; 35 | static int tx_power = -1; 36 | extern uint8_t adv_handle; 37 | 38 | int mode_check(int argc) 39 | { 40 | if(argc == 1) 41 | { 42 | printf("\nbackground mode\n"); 43 | return BACKGROUNG_MODE; 44 | } 45 | else 46 | { 47 | printf("\nforeground mode\n"); 48 | return FOREGROUND_MODE; 49 | } 50 | return -1; 51 | } 52 | 53 | int foreground_param_check(int argc, char *argv[]) 54 | { 55 | if(!strcmp(argv[1], IBEACON_RECIEVER)) 56 | { 57 | if (argc != 3) 58 | { 59 | printf("param err!\n"); 60 | return GL_ERR_PARAM; 61 | } 62 | // passive/active scan check 63 | if(!strcmp(argv[2], IBEACON_PASSIVE_SCAN)) 64 | { 65 | scan_type = 0; 66 | printf("passive scan\n"); 67 | } 68 | else if(!strcmp(argv[2], IBEACON_ACTIVE_SCAN)) 69 | { 70 | scan_type = 1; 71 | printf("active scan\n"); 72 | } 73 | else 74 | { 75 | printf("param err!\n"); 76 | return GL_ERR_PARAM; 77 | } 78 | } 79 | else if(!strcmp(argv[1], IBEACON_SENDER)) 80 | { 81 | if ((argc != 7) && (argc != 8)) 82 | { 83 | printf("param err!\n"); 84 | return GL_ERR_PARAM; 85 | } 86 | //ibeacon payload: uuid、major、minor、Measured Power 87 | if ((strlen(argv[3]) != 32) || (strlen(argv[4]) != 4) || 88 | (strlen(argv[5]) != 4) || (strlen(argv[6]) != 2)) 89 | { 90 | printf("ibeacon payload param err!\n"); 91 | return GL_ERR_PARAM; 92 | } 93 | //scan_respone 94 | if(argc == 7) 95 | { 96 | if(!strcmp(argv[2], IBEACON_SCAN_RSP_CLOSE)) 97 | { 98 | scan_respone = 0; 99 | } 100 | else if(!strcmp(argv[2], IBEACON_SCAN_RSP_OPEN)) 101 | { 102 | scan_respone = 1; 103 | } 104 | else 105 | { 106 | printf("scan respon param err!\n"); 107 | return GL_ERR_PARAM; 108 | } 109 | } 110 | //tx power 111 | if(argc == 8) 112 | { 113 | tx_power = atoi(argv[7]); 114 | } 115 | } 116 | else 117 | { 118 | printf("param err!\n"); 119 | return GL_ERR_PARAM; 120 | } 121 | return GL_SUCCESS; 122 | } 123 | 124 | int foreground(char *argv[]) 125 | { 126 | int ret = -1; 127 | if(!strcmp(argv[1], IBEACON_RECIEVER)) 128 | { 129 | ret = foreground_ibeacon_reciever(); 130 | } 131 | else if(!strcmp(argv[1], IBEACON_SENDER)) 132 | { 133 | ret = foreground_ibeacon_sender(argv); 134 | } 135 | return ret; 136 | } 137 | 138 | int foreground_ibeacon_reciever(void) 139 | { 140 | GL_RET ret = -1; 141 | json_object *o = NULL; 142 | const char *temp = NULL; 143 | 144 | // start scan 145 | ret = gl_ble_start_discovery(PHYS, INTERVAL, WINDOW, scan_type, MODE); 146 | if (ret != GL_SUCCESS) 147 | { 148 | printf("Start ble discovery error!! Err code: %d\n", ret); 149 | return GL_UNKNOW_ERR; 150 | } 151 | 152 | while(1) 153 | { 154 | o = get_ibeacon_vendor(); 155 | if(o == NULL) 156 | { 157 | continue; 158 | } 159 | temp = json_object_to_json_string(o); 160 | printf("%s\n", temp); 161 | 162 | json_object_put(o); 163 | o = NULL; 164 | } 165 | return GL_SUCCESS; 166 | } 167 | 168 | int foreground_ibeacon_sender(char *argv[]) 169 | { 170 | GL_RET ret = -1; 171 | int current_p = -1; 172 | char ibeacon_packet_snd[IBEACON_PACKET_SIZE*2 + 1] = {0}; 173 | sprintf(ibeacon_packet_snd, "%s%s%s%s%s", IBEACON_SEND_HEADER, argv[3], argv[4], argv[5], argv[6]); 174 | printf("data: %s\n", ibeacon_packet_snd); 175 | 176 | // init adv param 177 | uint32_t interval_min = 32; 178 | uint32_t interval_max = 64; 179 | uint8_t discover = 3; 180 | uint8_t connect = 3; 181 | 182 | //tx power 183 | if(tx_power != -1) 184 | { 185 | ret = gl_ble_set_power(tx_power, ¤t_p); 186 | json_object* o = NULL; 187 | o = json_object_new_object(); 188 | json_object_object_add(o, "code", json_object_new_int(ret)); 189 | if(ret == GL_SUCCESS) 190 | { 191 | json_object_object_add(o, "current_power", json_object_new_int(current_p)); 192 | } 193 | const char *temp = json_object_to_json_string(o); 194 | printf("%s\n",temp); 195 | 196 | json_object_put(o); 197 | 198 | tx_power = -1; 199 | } 200 | 201 | // create adv adv_handle 202 | ret = gl_ble_create_adv_handle(&adv_handle); 203 | if (GL_SUCCESS != ret) 204 | { 205 | printf("gl_ble_create_adv_handle failed: %d\n", ret); 206 | exit(-1); 207 | } 208 | 209 | const char *data = ibeacon_packet_snd; 210 | ret = gl_ble_set_legacy_adv_data(adv_handle, 0, data); 211 | if (GL_SUCCESS != ret) 212 | { 213 | printf("gl_ble_set_legacy_adv_data failed: %d\n", ret); 214 | return GL_UNKNOW_ERR; 215 | } 216 | if(scan_respone == 1) 217 | { 218 | ret = gl_ble_set_legacy_adv_data(adv_handle, 1, data); 219 | if (GL_SUCCESS != ret) 220 | { 221 | printf("gl_ble_set_legacy_adv_data failed: %d\n", ret); 222 | return GL_UNKNOW_ERR; 223 | } 224 | } 225 | 226 | // start advertising 227 | ret = gl_ble_start_legacy_adv(adv_handle, interval_min, interval_max, discover, connect); 228 | if (GL_SUCCESS != ret) 229 | { 230 | printf("gl_ble_start_legacy_adv failed: %d\n", ret); 231 | return GL_UNKNOW_ERR; 232 | } 233 | 234 | //get ble mac 235 | uint8_t mac_buf[6]; 236 | ret = gl_ble_get_mac(mac_buf); 237 | if (GL_SUCCESS != ret) 238 | { 239 | printf("gl_ble_get_mac failed: %d\n", ret); 240 | return GL_UNKNOW_ERR; 241 | } 242 | printf("Broadcasting ibeacon data, the mac of the current device is > " MACSTR "\n", MAC2STR(mac_buf)); 243 | 244 | while(1) 245 | { 246 | sleep(1000); 247 | } 248 | 249 | return GL_SUCCESS; 250 | } 251 | 252 | int background(void) 253 | { 254 | return ubus_start(); 255 | } -------------------------------------------------------------------------------- /src/example/bleIbeacon/run_mode.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _RUN_MODE_H 17 | #define _RUN_MODE_H 18 | 19 | typedef enum{ 20 | BACKGROUNG_MODE, 21 | FOREGROUND_MODE 22 | }mode_e; 23 | 24 | int mode_check(int argc); 25 | 26 | int foreground_param_check(int argc, char *argv[]); 27 | 28 | int foreground(char *argv[]); 29 | 30 | int foreground_ibeacon_reciever(void); 31 | 32 | int foreground_ibeacon_sender(char *argv[]); 33 | 34 | int background(void); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/example/bleIbeacon/ubus.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _UBUS_H 17 | #define _UBUS_H 18 | 19 | extern struct ubus_context *_ctx_invoke; 20 | extern struct ubus_context *_ctx_event; 21 | extern pthread_t ubus_tid; 22 | 23 | int ubus_start(void); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/example/bleIbeacon/util.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "util.h" 23 | 24 | int ENDIAN; 25 | 26 | #define MAC2STR(a) (a)[5], (a)[4], (a)[3], (a)[2], (a)[1], (a)[0] 27 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 28 | 29 | int addr2str(BLE_MAC adr, char* str) 30 | { 31 | sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", adr[5], adr[4], 32 | adr[3], adr[2], adr[1], adr[0]); 33 | return 0; 34 | } 35 | 36 | int str2array(uint8_t* dst, char* src, int len) 37 | { 38 | int i = 0; 39 | int tmp; 40 | while (i < len) { 41 | sscanf(src + i * 2, "%02x", &tmp); 42 | dst[i] = tmp; 43 | // printf("str2array dst[%d] = 0x%02x\n", i, dst[i]); 44 | i++; 45 | } 46 | return 0; 47 | } 48 | 49 | int hex2str(uint8_t* head, int len, char* value) { 50 | int i = 0; 51 | 52 | // FIXME: (Sometime kernel don't mask all uart print) When wifi network up/down, it will recv a big message 53 | if(len >= 256/2) 54 | { 55 | strcpy(value,"00"); 56 | // printf("recv a err msg! err len = %d\n",len); 57 | return -1; 58 | } 59 | 60 | while (i < len) { 61 | sprintf(value + i * 2, "%02x", head[i]); 62 | i++; 63 | } 64 | return 0; 65 | } -------------------------------------------------------------------------------- /src/example/bleIbeacon/util.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _UTIL_H 17 | #define _UTIL_H 18 | 19 | #include "gl_type.h" 20 | 21 | #define MAC2STR(a) (a)[5], (a)[4], (a)[3], (a)[2], (a)[1], (a)[0] 22 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 23 | 24 | int addr2str(BLE_MAC adr, char* str); 25 | 26 | int str2array(uint8_t* dst, char* src, int len); 27 | 28 | int hex2str(uint8_t* head, int len, char* value); 29 | 30 | 31 | #endif -------------------------------------------------------------------------------- /src/example/bleScanner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleScanner" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleScanner/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleScanner 2 | 3 | Demo of scanning the surrounding ble broadcast and output it in JSON format. 4 | 5 | This is the demo for user to use gl-ble-api to scanning ble broadcast and get results. 6 | 7 | You can collaborate with [bleAdvertiserLegacy](../bleAdvertiserLegacy/README.md) and [bleAdvertiserExtended](../bleAdvertiserExtended/README.md). 8 | 9 | 10 | 11 | ## Compile 12 | 13 | Make sure you have the compile option enabled before compiling the project. 14 | 15 | ``` 16 | make menuconfig 17 | -> gl-inet-ble 18 | -> libglble...................................... GL inet BLE driver library 19 | -> gl-bleScanner........................................ GL inet BLE Scanner 20 | ``` 21 | 22 | 23 | 24 | ## Using the example 25 | 26 | You can use SCP or other means to upload example ipk to the device. 27 | 28 | 29 | 30 | ### install 31 | 32 | ```shell 33 | opkg install libglble_2.0.0_mipsel_24kc.ipk 34 | opkg install gl-bleScanner_2.0.0_mipsel_24kc.ipk 35 | ``` 36 | 37 | 38 | 39 | ### Using 40 | 41 | ```shell 42 | bleScanner [phys] [interval] [window] [type] [mode] [address] 43 | 44 | -> phys: The PHY on which the advertising packets are transmitted on. 45 | 1: LE 1M PHY, 4: LE Coded PHY, 5: Simultaneous LE 1M and Coded PHY alternatively 46 | -> interval: Scan interval. Time = Value x 0.625 ms. 47 | Range: 0x0004 to 0xFFFF, Time Range: 2.5 ms to 40.96 s. 48 | -> window: Scan window. Time = Value x 0.625 ms. 49 | Range: 0x0004 to 0xFFFF, Time Range: 2.5 ms to 40.96 s. 50 | -> type: Scan type. 51 | 0: Passive scanning, 1: Active scanning. 52 | -> mode: Bluetooth discovery Mode. 53 | 0: Discover only limited discoverable devices 54 | 1: Discover limited and generic discoverable devices 55 | 2: Discover all devices 56 | -> address: (optional)Scans the broadcast packet for the specified MAC address. Like “11:22:33:44:55:66”. 57 | ``` 58 | 59 | 60 | 61 | ### demonstrate 62 | 63 | **note** 64 | 65 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 66 | 67 | ```shell 68 | root@OpenWrt:~# bleScanner 69 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 70 | The ble module firmware version is not 4_2_0, please switch it. 71 | ``` 72 | 73 | 74 | 75 | - customize parameters 76 | 77 | ```shell 78 | # Not specify MAC address 79 | root@OpenWrt:~# bleScanner 1 16 16 0 2 80 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 81 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "6e:8c:cc:0f:a7:fa", "address_type": 1, "rssi": -70, "event_flags": 3, 82 | "bonding": 255, "data": "0201061aff4c000c0e0895232231d3e902f72f3870ce4e1005491c23b634" } 83 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "e7:43:07:1e:e8:cb", "address_type": 1, "rssi": -57, "event_flags": 0, "bonding": 255, "data": "07ff4c0012020001" } 84 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "72:64:21:10:00:ba", "address_type": 1, "rssi": -63, "event_flags": 3, "bonding": 255, "data": "0201061aff4c000215fda50693a4e24fb1afcfc6eb0764782500010002d8" } 85 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "6e:be:a6:f7:0a:a7", "address_type": 1, "rssi": -82, "event_flags": 3, "bonding": 255, "data": "02011a020a070bff4c0010061f1978d89a28" } 86 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "03:b9:77:cc:9c:47", "address_type": 1, "rssi": -67, "event_flags": 0, "bonding": 255, "data": "1eff060001092002b911fbc40564078c43aba56dc86d7f5107f6f63e0541e2" } 87 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "69:df:be:90:44:9c", "address_type": 1, "rssi": -68, "event_flags": 3, "bonding": 255, "data": "02010217ff8f03271110184122343266621526080857010304830b0303aafd" } 88 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "47:8d:5d:77:bd:66", "address_type": 1, "rssi": -60, "event_flags": 3, "bonding": 255, "data": "02011a020a080bff4c001006281a734eb5da" } 89 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "c2:0a:0c:41:21:74", "address_type": 1, "rssi": -79, "event_flags": 0, "bonding": 255, "data": "07ff4c0012020001" } 90 | ``` 91 | 92 | ```shell 93 | # Specify MAC address 94 | root@OpenWrt:~# bleScanner 1 160 160 0 2 72:64:21:10:00:ba 95 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 96 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "72:64:21:10:00:ba", "address_type": 1, "rssi": -72, "event_flags": 3, "bonding": 255, "data": "0201061aff4c000215fda50693a4e24fb1afcfc6eb0764782500010002d8" } 97 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "72:64:21:10:00:ba", "address_type": 1, "rssi": -64, "event_flags": 3, "bonding": 255, "data": "0201061aff4c000215fda50693a4e24fb1afcfc6eb0764782500010002d8" } 98 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "72:64:21:10:00:ba", "address_type": 1, "rssi": -74, "event_flags": 3, "bonding": 255, "data": "0201061aff4c000215fda50693a4e24fb1afcfc6eb0764782500010002d8" } 99 | ``` 100 | 101 | - default parameters 102 | 103 | The default parameters is [phys:1] [interval:16] [window:16] [type:0] [mode:2] [address:NULL] 104 | 105 | ```shell 106 | # Not specify MAC address 107 | root@OpenWrt:~# bleScanner 108 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 109 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "7f:15:94:0d:43:54", "address_type": 1, "rssi": -64, "event_flags": 3, "bonding": 255, "data": "02011a020a0c0aff4c0010050018dca06a" } 110 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "e0:9c:ed:25:42:fa", "address_type": 1, "rssi": -75, "event_flags": 0, "bonding": 255, "data": "07ff4c0012020000" } 111 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "2e:fb:c6:26:2d:c6", "address_type": 1, "rssi": -80, "event_flags": 0, "bonding": 255, "data": "1eff0600010920020b5f21cacaee774827990d1adfbcb8f04d3827ac123b94" } 112 | GAP_CB_MSG >> { "type": "extended_adv_result", "mac": "94:de:b8:f1:23:f4", "address_type": 0, "rssi": -25, "event_flags": 0, "bonding": 255, "data": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" } 113 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "2e:ae:02:4d:ec:2c", "address_type": 1, "rssi": -60, "event_flags": 0, "bonding": 255, "data": "1eff060001092002f4073ed89f586b7389b2bbe6958ea24135dc9c732a6390" } 114 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "67:a6:af:05:f9:a0", "address_type": 1, "rssi": -60, "event_flags": 3, "bonding": 255, "data": "02011a020a070aff4c0010055f1c67f376" } 115 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "22:46:6d:9e:00:ca", "address_type": 1, "rssi": -64, "event_flags": 0, "bonding": 255, "data": "02011a0bff4c0009060369c0a82669" } 116 | GAP_CB_MSG >> { "type": "legacy_adv_result", "mac": "61:40:61:ae:65:e3", "address_type": 1, "rssi": -75, "event_flags": 3, "bonding": 255, "data": "02011a020a030aff4c0010054b1cfcda09" } 117 | ``` 118 | 119 | ```shell 120 | # Specify MAC address 121 | root@OpenWrt:~# bleScanner 94:de:b8:ee:4a:70 122 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 123 | GAP_CB_MSG >> { "type": "extended_adv_result", "mac": "94:de:b8:ee:4a:70", "address_type": 0, "rssi": -11, "event_flags": 0, "bonding": 255, "data": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" } 124 | GAP_CB_MSG >> { "type": "extended_adv_result", "mac": "94:de:b8:ee:4a:70", "address_type": 0, "rssi": -10, "event_flags": 0, "bonding": 255, "data": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" } 125 | GAP_CB_MSG >> { "type": "extended_adv_result", "mac": "94:de:b8:ee:4a:70", "address_type": 0, "rssi": -11, "event_flags": 0, "bonding": 255, "data": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" } 126 | ``` 127 | 128 | 129 | 130 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 131 | -------------------------------------------------------------------------------- /src/example/bleScanner/demo_bleScanner.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleScanner.c 3 | * @brief Start the BLE discovery and subscribe the BLE event 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gl_errno.h" 29 | #include "gl_type.h" 30 | #include "gl_bleapi.h" 31 | 32 | static void sigal_hander(int sig); 33 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data); 34 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 35 | static int addr2str(BLE_MAC adr, char *str); 36 | static int str2addr(char* str, BLE_MAC address); 37 | static int hex2str(uint8_t* head, int len, char* value); 38 | 39 | static bool module_work = false; 40 | static BLE_MAC mac_filter = {0}; 41 | static bool mac_filter_flag = false; 42 | 43 | 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | signal(SIGTERM, sigal_hander); 48 | signal(SIGINT, sigal_hander); 49 | signal(SIGQUIT, sigal_hander); 50 | 51 | // init msg callback 52 | gl_ble_cbs ble_cb; 53 | memset(&ble_cb, 0, sizeof(gl_ble_cbs)); 54 | 55 | ble_cb.ble_gap_event = ble_gap_cb; 56 | ble_cb.ble_gatt_event = NULL; 57 | ble_cb.ble_module_event = ble_module_cb; 58 | 59 | uint8_t phys = 1; 60 | uint16_t interval = 16, window = 16; 61 | uint8_t type = 0, mode = 2; 62 | char *address = NULL; 63 | // get scanner param 64 | if ((argc != 1) && (argc != 2) && (argc != 6) && (argc != 7)) 65 | { 66 | printf("param err!"); 67 | return GL_ERR_PARAM; 68 | } 69 | 70 | if (argc == 2) 71 | { 72 | address = argv[1]; 73 | if (strlen(address) != (BLE_MAC_LEN - 1)) 74 | { 75 | printf("param err!"); 76 | return GL_ERR_PARAM; 77 | } 78 | 79 | str2addr(address, mac_filter); 80 | mac_filter_flag = true; 81 | } 82 | 83 | if (argc >= 6) 84 | { 85 | phys = atoi(argv[1]); 86 | interval = atoi(argv[2]); 87 | window = atoi(argv[3]); 88 | type = atoi(argv[4]); 89 | mode = atoi(argv[5]); 90 | } 91 | 92 | if (argc == 7) 93 | { 94 | address = argv[6]; 95 | if (strlen(address) != (BLE_MAC_LEN - 1)) 96 | { 97 | printf("param err!"); 98 | return GL_ERR_PARAM; 99 | } 100 | 101 | str2addr(address, mac_filter); 102 | mac_filter_flag = true; 103 | } 104 | 105 | // init ble module 106 | GL_RET ret; 107 | ret = gl_ble_init(); 108 | if (GL_SUCCESS != ret) 109 | { 110 | printf("gl_ble_init failed: %d\n", ret); 111 | exit(-1); 112 | } 113 | 114 | ret = gl_ble_subscribe(&ble_cb); 115 | if (GL_SUCCESS != ret) 116 | { 117 | printf("gl_ble_subscribe failed: %d\n", ret); 118 | exit(-1); 119 | } 120 | 121 | // ble module check, will auto update firmware if module firmware not work. 122 | // after update firmware if not work, will exit the program. 123 | ret = gl_ble_check_module(&ble_cb, false); 124 | if(ret != GL_SUCCESS) 125 | { 126 | printf("The ble module firmware not work.\n"); 127 | exit(-1); 128 | } 129 | 130 | // wait for module reset 131 | while (!module_work) 132 | { 133 | usleep(100000); 134 | } 135 | 136 | // start scan 137 | ret = gl_ble_start_discovery(phys, interval, window, type, mode); 138 | if (ret != GL_SUCCESS) 139 | { 140 | printf("Start ble discovery error!! Err code: %d\n", ret); 141 | exit(-1); 142 | } 143 | 144 | while (1) 145 | { 146 | sleep(1000); 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | static int addr2str(BLE_MAC adr, char *str) 153 | { 154 | sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", adr[5], adr[4], 155 | adr[3], adr[2], adr[1], adr[0]); 156 | return 0; 157 | } 158 | 159 | static int str2addr(char* str, BLE_MAC address) 160 | { 161 | int mac[6] = {0}; 162 | sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", &mac[5], &mac[4], &mac[3], 163 | &mac[2], &mac[1], &mac[0]); 164 | 165 | uint8_t i = 0; 166 | for(;i < 6; i++) 167 | { 168 | address[i] = mac[i]; 169 | } 170 | return 0; 171 | } 172 | 173 | static int hex2str(uint8_t* head, int len, char* value) 174 | { 175 | int i = 0; 176 | 177 | // FIXME: (Sometime kernel don't mask all uart print) When wifi network up/down, it will recv a big message 178 | // if(len >= 256/2) 179 | // { 180 | // strcpy(value,"00"); 181 | // // printf("recv a err msg! err len = %d\n",len); 182 | // return -1; 183 | // } 184 | 185 | while (i < len) { 186 | sprintf(value + i * 2, "%02x", head[i]); 187 | i++; 188 | } 189 | return 0; 190 | } 191 | 192 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data) 193 | { 194 | char address[BLE_MAC_LEN] = {0}; 195 | char ble_adv[MAX_ADV_DATA_LEN * 2 + 1] = {0}; 196 | switch (event) 197 | { 198 | case GAP_BLE_LEGACY_SCAN_RESULT_EVT: 199 | { 200 | if(mac_filter_flag) 201 | { 202 | if(0 != memcmp(data->legacy_scan_rst.address, mac_filter, 6)) 203 | { 204 | break; 205 | } 206 | } 207 | addr2str(data->legacy_scan_rst.address, address); 208 | hex2str(data->legacy_scan_rst.ble_adv, data->legacy_scan_rst.ble_adv_len, ble_adv); 209 | 210 | // json format 211 | json_object* o = NULL; 212 | o = json_object_new_object(); 213 | 214 | json_object_object_add(o, "type", json_object_new_string("legacy_adv_result")); 215 | json_object_object_add(o, "mac", json_object_new_string(address)); 216 | json_object_object_add(o, "address_type", json_object_new_int(data->legacy_scan_rst.ble_addr_type)); 217 | json_object_object_add(o, "rssi", json_object_new_int(data->legacy_scan_rst.rssi)); 218 | json_object_object_add(o, "event_flags", json_object_new_int(data->legacy_scan_rst.event_flags)); 219 | json_object_object_add(o, "bonding", json_object_new_int(data->legacy_scan_rst.bonding)); 220 | json_object_object_add(o, "data", json_object_new_string(ble_adv)); 221 | const char *temp = json_object_to_json_string(o); 222 | printf("GAP_CB_MSG >> %s\n",temp); 223 | 224 | json_object_put(o); 225 | break; 226 | } 227 | 228 | case GAP_BLE_EXTENDED_SCAN_RESULT_EVT: 229 | { 230 | if(mac_filter_flag) 231 | { 232 | if(0 != memcmp(data->legacy_scan_rst.address, mac_filter, 6)) 233 | { 234 | break; 235 | } 236 | } 237 | 238 | addr2str(data->extended_scan_rst.address, address); 239 | 240 | // json format 241 | json_object* o = NULL; 242 | o = json_object_new_object(); 243 | 244 | hex2str(data->extended_scan_rst.ble_adv, data->extended_scan_rst.ble_adv_len, ble_adv); 245 | json_object_object_add(o, "type", json_object_new_string("extended_adv_result")); 246 | json_object_object_add(o, "mac", json_object_new_string(address)); 247 | json_object_object_add(o, "address_type", json_object_new_int(data->extended_scan_rst.ble_addr_type)); 248 | json_object_object_add(o, "rssi", json_object_new_int(data->extended_scan_rst.rssi)); 249 | json_object_object_add(o, "tx_power", json_object_new_int(data->extended_scan_rst.tx_power)); 250 | json_object_object_add(o, "event_flags", json_object_new_int(data->extended_scan_rst.event_flags)); 251 | json_object_object_add(o, "adv_sid", json_object_new_int(data->extended_scan_rst.adv_sid)); 252 | json_object_object_add(o, "periodic_interval", json_object_new_int(data->extended_scan_rst.periodic_interval)); 253 | json_object_object_add(o, "bonding", json_object_new_int(data->extended_scan_rst.bonding)); 254 | json_object_object_add(o, "data", json_object_new_string(ble_adv)); 255 | const char *temp = json_object_to_json_string(o); 256 | printf("GAP_CB_MSG >> %s\n",temp); 257 | 258 | json_object_put(o); 259 | 260 | break; 261 | } 262 | 263 | default: 264 | break; 265 | } 266 | 267 | return 0; 268 | } 269 | 270 | 271 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 272 | { 273 | switch (event) 274 | { 275 | case MODULE_BLE_SYSTEM_BOOT_EVT: 276 | { 277 | json_object *o = NULL; 278 | o = json_object_new_object(); 279 | json_object_object_add(o, "type", json_object_new_string("module_start")); 280 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 281 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 282 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 283 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 284 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 285 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 286 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 287 | const char *temp = json_object_to_json_string(o); 288 | printf("MODULE_CB_MSG >> %s\n", temp); 289 | 290 | json_object_put(o); 291 | 292 | module_work = true; 293 | 294 | break; 295 | } 296 | default: 297 | break; 298 | } 299 | 300 | return 0; 301 | } 302 | 303 | static void sigal_hander(int sig) 304 | { 305 | printf("\nbleScanner exit!\n"); 306 | 307 | gl_ble_stop_discovery(); 308 | gl_ble_unsubscribe(); 309 | gl_ble_destroy(); 310 | 311 | exit(0); 312 | } 313 | -------------------------------------------------------------------------------- /src/example/bleService/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleService" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleService/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleService 2 | 3 | This example is used to initiate a connectable BLE server (need to cooperate with [bleClient](../bleClient/README.md)) 4 | 5 | This is a demonstration of the user using gl-ble-api to start the ble broadcast server and get the results. 6 | 7 | 8 | 9 | ## Compile 10 | 11 | Make sure you have the compile option enabled before compiling the project. 12 | 13 | ``` 14 | make menuconfig 15 | -> gl-inet-ble 16 | -> libglble...................................... GL inet BLE driver library 17 | -> gl-bleService........................................ GL inet BLE Service 18 | ``` 19 | 20 | 21 | 22 | ## Using the example 23 | 24 | You can use SCP or other means to upload example ipk to the device. 25 | 26 | 27 | 28 | ### install 29 | 30 | ```shell 31 | opkg install libglble_2.0.0_mipsel_24kc.ipk 32 | opkg install gl-bleService_2.0.0_mipsel_24kc.ipk 33 | ``` 34 | 35 | 36 | 37 | ### Using 38 | 39 | **note** 40 | 41 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 42 | 43 | ```shell 44 | root@OpenWrt:~# bleService 45 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 46 | The ble module firmware version is not 4_2_0, please switch it. 47 | ``` 48 | 49 | 50 | 51 | **format** 52 | 53 | ```shell 54 | bleService 55 | ``` 56 | 57 | There are no configured parameters for this example. 58 | 59 | 60 | 61 | **Before being connected** 62 | 63 | ```shell 64 | root@OpenWrt:~# bleService 65 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 66 | Waiting to connect, the mac of the current device is > 94:de:b8:f1:35:1a 67 | ``` 68 | 69 | **After being connected** 70 | 71 | ```shell 72 | root@OpenWrt:~# bleService 73 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 74 | Waiting to connect, the mac of the current device is > 94:de:b8:f1:35:1a 75 | GAP_CB_MSG >> { "type": "connect_open", "mac": "94:de:b8:ee:4a:70", "address_type": 0, "connect_role": 0, "bonding": 255, "advertiser": 0 } 76 | GAP_CB_MSG >> { "type": "connect_update", "mac": "94:de:b8:ee:4a:70", "interval": 22, "latency": 0, "timeout": 100, "security_mode": 0, "txsize": 27 } 77 | GAP_CB_MSG >> { "type": "connect_update", "mac": "94:de:b8:ee:4a:70", "interval": 22, "latency": 0, "timeout": 100, "security_mode": 0, "txsize": 251 } 78 | Data from the client : Hello server . 79 | ``` 80 | 81 | 82 | 83 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 84 | 85 | -------------------------------------------------------------------------------- /src/example/bleSynchronize/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bleSynchronize" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | 9 | 10 | add_executable( ${EXEC_NAME} ${SOURCES} ) 11 | 12 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 13 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi ) 14 | 15 | 16 | install( 17 | TARGETS ${EXEC_NAME} 18 | RUNTIME DESTINATION bin 19 | ) 20 | -------------------------------------------------------------------------------- /src/example/bleSynchronize/README.md: -------------------------------------------------------------------------------- 1 | # GL-BLE-SDK bleSynchronize 2 | 3 | Demo of Synchronizing the surrounding ble periodic broadcast and output it in JSON format. 4 | 5 | This is the demo for user to use gl-ble-api to Synchronizing periodic broadcast and get results. 6 | 7 | You can collaborate with [bleAdvertiserPeriodic](../bleAdvertiserPeriodic/README.md). 8 | 9 | 10 | 11 | ## Compile 12 | 13 | Make sure you have the compile option enabled before compiling the project. 14 | 15 | ``` 16 | make menuconfig 17 | -> gl-inet-ble 18 | -> libglble...................................... GL inet BLE driver library 19 | -> gl-bleSynchronize................................ GL inet BLE Synchronize 20 | ``` 21 | 22 | 23 | 24 | ## Using the example 25 | 26 | You can use SCP or other means to upload example ipk to the device. 27 | 28 | You can use example [bleAdvertiserPeriodic](../bleAdvertiserPeriodic/README.md) to Advertising a Periodic packet first. 29 | 30 | 31 | 32 | ### install 33 | 34 | ```shell 35 | opkg install libglble_2.0.0_mipsel_24kc.ipk 36 | opkg install gl-bleSynchronize_2.0.0_mips_24kc.ipk 37 | ``` 38 | 39 | 40 | 41 | ### Using 42 | 43 | ```shell 44 | bleSynchronize [skip] [timeout] [address] [address_type] [adv_sid] 45 | -> skip: The maximum number of periodic advertising packets that can be skipped after a successful receive. 46 | Range: 0x0000 to 0x01F3. 47 | -> timeout: The maximum permitted time between successful receives.If this time is exceeded, synchronization is lost. 48 | Unit: 10 ms. Range: 0x0A to 0x4000, Time Range: 100 ms to 163.84 s. 49 | -> address: Address of the device to synchronize to. Like “11:22:33:44:55:66”. 50 | -> address_type: Address type of the device to connect to. 51 | 0: Public address. 52 | 1: Random address. 53 | -> adv_sid: Advertising set identifiers. 54 | The adv_sid of a periodic advertising packet can be obtained by GAP_BLE_EXTENDED_SCAN_RESULT_EVT whether periodic_interval exists. Periodic_interval equal 0 indicates no periodic advertising packet. 55 | ``` 56 | 57 | **Note:** **It will automationaly start ble scan on the simultaneous LE 1M and Coded PHY alternatively.** The synchronize timeout you set should bigger than Periodic advertising interval. If not, it will breaks the established synchronization. 58 | 59 | 60 | 61 | ### demonstrate 62 | 63 | **note** 64 | 65 | This example will detect whether the ble module firmware version is 4_2_0. If it is not, it will upgrade to the corresponding firmware version. However, the previous devices does not support this automatic upgrade method, which needs to be upgraded in other ways. 66 | 67 | ```shell 68 | root@OpenWrt:~# bleSynchronize 69 | MODULE_CB_MSG >> { "type": "module_start", "major": 2, "minor": 13, "patch": 10, "build": 423, "bootloader": 17563648, "hw": 1, "ble_hash": "4d5a9661" } 70 | The ble module firmware version is not 4_2_0, please switch it. 71 | ``` 72 | 73 | 74 | 75 | - customize parameters 76 | 77 | ```shell 78 | root@OpenWrt:~# bleSynchronize 0 100 94:de:b8:f1:35:1a 0 0 79 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 80 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 81 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 82 | ``` 83 | 84 | - default parameters 85 | 86 | The default parameters is [skip:0] [timeout:100] [address:NULL] [address_type:NULL] [adv_sid:NULL] 87 | 88 | If you don't need to customize the parameters, you can use the default parameters. It automatically synchronizes the first periodic broadcast package scanned into the environment. 89 | 90 | ```shell 91 | root@OpenWrt:~# bleSynchronize 92 | MODULE_CB_MSG >> { "type": "module_start", "major": 4, "minor": 2, "patch": 0, "build": 321, "bootloader": 0, "hw": 257, "ble_hash": "1b0e33cd" } 93 | GAP_CB_MSG >> { "type": "periodic_adv_result", "mac": "94:de:b8:f1:35:1a", "address_type": 0, "rssi": -10, "adv_sid": 0, "periodic_interval": 120 } 94 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 95 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -11, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 96 | GAP_CB_MSG >> { "type": "sync_result", "rssi": -12, "data": "0201060709474c5f424c45111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344" } 97 | ``` 98 | 99 | You can use **CTRL+C** or **CTRL+\\** to terminate the application. 100 | 101 | -------------------------------------------------------------------------------- /src/example/bleSynchronize/demo_bleSynchronize.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * @file demo_bleSynchronize.c 3 | * @brief Start the BLE Synchronize and subscribe the BLE event 4 | ******************************************************************************* 5 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ******************************************************************************/ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gl_errno.h" 29 | #include "gl_type.h" 30 | #include "gl_bleapi.h" 31 | 32 | static void sigal_hander(int sig); 33 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data); 34 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data); 35 | static int addr2str(BLE_MAC adr, char *str); 36 | static int hex2str(uint8_t* head, int len, char* value); 37 | static int str2addr(char* str, BLE_MAC address) ; 38 | 39 | static bool module_work = false; 40 | static bool is_specified = false; 41 | 42 | 43 | static uint16_t handle = 0xffff; 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | signal(SIGTERM, sigal_hander); 48 | signal(SIGINT, sigal_hander); 49 | signal(SIGQUIT, sigal_hander); 50 | 51 | // init msg callback 52 | gl_ble_cbs ble_cb; 53 | memset(&ble_cb, 0, sizeof(gl_ble_cbs)); 54 | 55 | ble_cb.ble_gap_event = ble_gap_cb; 56 | ble_cb.ble_gatt_event = NULL; 57 | ble_cb.ble_module_event = ble_module_cb; 58 | 59 | // get synchronize param 60 | uint16_t skip = 0; 61 | uint16_t timeout = 100; 62 | BLE_MAC address_u8; 63 | uint8_t address_type; 64 | uint8_t adv_sid; 65 | 66 | if((argc != 1) && (argc != 6)) 67 | { 68 | printf("param err!"); 69 | return GL_ERR_PARAM; 70 | } 71 | 72 | 73 | if(argc == 6) 74 | { 75 | is_specified = true; 76 | char *addr = NULL; 77 | skip = atoi(argv[1]); 78 | timeout = atoi(argv[2]); 79 | addr = argv[3]; 80 | str2addr(addr, address_u8); 81 | address_type = atoi(argv[4]); 82 | adv_sid = atoi(argv[5]); 83 | } 84 | 85 | // init ble module 86 | GL_RET ret; 87 | ret = gl_ble_init(); 88 | if (GL_SUCCESS != ret) 89 | { 90 | printf("gl_ble_init failed: %d\n", ret); 91 | exit(-1); 92 | } 93 | 94 | ret = gl_ble_subscribe(&ble_cb); 95 | if (GL_SUCCESS != ret) 96 | { 97 | printf("gl_ble_subscribe failed: %d\n", ret); 98 | exit(-1); 99 | } 100 | 101 | // ble module check, will auto update firmware if module firmware not work. 102 | // after update firmware if not work, will exit the program. 103 | ret = gl_ble_check_module(&ble_cb, false); 104 | if(ret != GL_SUCCESS) 105 | { 106 | printf("The ble module firmware not work.\n"); 107 | exit(-1); 108 | } 109 | 110 | // wait for module reset 111 | while (!module_work) 112 | { 113 | usleep(100000); 114 | } 115 | 116 | // start scan before sync 117 | ret = gl_ble_start_discovery(5, 16, 16, 0, 2); 118 | if (ret != GL_SUCCESS) 119 | { 120 | printf("Start ble scanner error!! Err code: %d\n", ret); 121 | exit(-1); 122 | } 123 | 124 | ret = gl_ble_set_sync_parameters(skip, timeout); 125 | if (ret != GL_SUCCESS) 126 | { 127 | printf("Set sync parameters error!! Err code: %d\n", ret); 128 | exit(-1); 129 | } 130 | 131 | // Start synchronizing the specified address 132 | if(argc == 6) 133 | { 134 | ret = gl_ble_start_sync(address_u8, address_type, adv_sid, &handle); 135 | if (ret != GL_SUCCESS) 136 | { 137 | gl_ble_stop_discovery(); 138 | printf("Start ble synchronize error!! Err code: %d\n", ret); 139 | exit(-1); 140 | } 141 | gl_ble_stop_discovery(); 142 | } 143 | 144 | while (1) 145 | { 146 | sleep(1000); 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | static int addr2str(BLE_MAC adr, char *str) 153 | { 154 | sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", adr[5], adr[4], 155 | adr[3], adr[2], adr[1], adr[0]); 156 | return 0; 157 | } 158 | 159 | static int str2addr(char* str, BLE_MAC address) 160 | { 161 | int mac[6] = {0}; 162 | sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", &mac[5], &mac[4], &mac[3], 163 | &mac[2], &mac[1], &mac[0]); 164 | 165 | uint8_t i = 0; 166 | for(;i < 6; i++) 167 | { 168 | address[i] = mac[i]; 169 | } 170 | return 0; 171 | } 172 | 173 | static int hex2str(uint8_t* head, int len, char* value) 174 | { 175 | int i = 0; 176 | 177 | // FIXME: (Sometime kernel don't mask all uart print) When wifi network up/down, it will recv a big message 178 | // if(len >= 256/2) 179 | // { 180 | // strcpy(value,"00"); 181 | // // printf("recv a err msg! err len = %d\n",len); 182 | // return -1; 183 | // } 184 | 185 | while (i < len) { 186 | sprintf(value + i * 2, "%02x", head[i]); 187 | i++; 188 | } 189 | return 0; 190 | } 191 | 192 | static int ble_gap_cb(gl_ble_gap_event_t event, gl_ble_gap_data_t *data) 193 | { 194 | char address[BLE_MAC_LEN] = {0}; 195 | char ble_adv[MAX_ADV_DATA_LEN * 2 + 1] = {0}; 196 | switch (event) 197 | { 198 | case GAP_BLE_EXTENDED_SCAN_RESULT_EVT: 199 | { 200 | addr2str(data->extended_scan_rst.address, address); 201 | 202 | // json format 203 | json_object* o = NULL; 204 | o = json_object_new_object(); 205 | 206 | hex2str(data->extended_scan_rst.ble_adv, data->extended_scan_rst.ble_adv_len, ble_adv); 207 | json_object_object_add(o, "type", json_object_new_string("extended_adv_result")); 208 | json_object_object_add(o, "mac", json_object_new_string(address)); 209 | json_object_object_add(o, "address_type", json_object_new_int(data->extended_scan_rst.ble_addr_type)); 210 | json_object_object_add(o, "rssi", json_object_new_int(data->extended_scan_rst.rssi)); 211 | json_object_object_add(o, "tx_power", json_object_new_int(data->extended_scan_rst.tx_power)); 212 | json_object_object_add(o, "event_flags", json_object_new_int(data->extended_scan_rst.event_flags)); 213 | json_object_object_add(o, "adv_sid", json_object_new_int(data->extended_scan_rst.adv_sid)); 214 | json_object_object_add(o, "periodic_interval", json_object_new_int(data->extended_scan_rst.periodic_interval)); 215 | json_object_object_add(o, "bonding", json_object_new_int(data->extended_scan_rst.bonding)); 216 | json_object_object_add(o, "data", json_object_new_string(ble_adv)); 217 | const char *temp = json_object_to_json_string(o); 218 | printf("GAP_CB_MSG >> %s\n",temp); 219 | 220 | json_object_put(o); 221 | 222 | //if no synchronization address is specified, the first periodic broadcast packet scanned synchronously 223 | if(data->extended_scan_rst.periodic_interval != 0) 224 | { 225 | if (!is_specified) 226 | { 227 | GL_RET ret = gl_ble_start_sync(data->extended_scan_rst.address, data->extended_scan_rst.ble_addr_type, data->extended_scan_rst.adv_sid, &handle); 228 | if (ret != GL_SUCCESS) 229 | { 230 | printf("Start ble synchronize error!! Err code: %d\n", ret); 231 | } 232 | gl_ble_stop_discovery(); 233 | } 234 | } 235 | 236 | 237 | break; 238 | } 239 | 240 | case GAP_BLE_SYNC_SCAN_RESULT_EVT: 241 | { 242 | hex2str(data->sync_scan_rst.ble_adv, data->sync_scan_rst.ble_adv_len, ble_adv); 243 | 244 | // json format 245 | json_object* o = NULL; 246 | o = json_object_new_object(); 247 | json_object_object_add(o, "type", json_object_new_string("sync_result")); 248 | json_object_object_add(o, "tx_power", json_object_new_int(data->sync_scan_rst.tx_power)); 249 | json_object_object_add(o, "rssi", json_object_new_int(data->sync_scan_rst.rssi)); 250 | json_object_object_add(o, "data", json_object_new_string(ble_adv)); 251 | const char *temp = json_object_to_json_string(o); 252 | printf("GAP_CB_MSG >> %s\n",temp); 253 | 254 | json_object_put(o); 255 | break; 256 | } 257 | 258 | case GAP_BLE_SYNC_CLOSED_EVT: 259 | { 260 | printf("sync closed\n"); 261 | is_specified = false; 262 | break; 263 | } 264 | default: 265 | break; 266 | } 267 | 268 | return 0; 269 | } 270 | 271 | static int ble_module_cb(gl_ble_module_event_t event, gl_ble_module_data_t *data) 272 | { 273 | switch (event) 274 | { 275 | case MODULE_BLE_SYSTEM_BOOT_EVT: 276 | { 277 | json_object *o = NULL; 278 | o = json_object_new_object(); 279 | json_object_object_add(o, "type", json_object_new_string("module_start")); 280 | json_object_object_add(o, "major", json_object_new_int(data->system_boot_data.major)); 281 | json_object_object_add(o, "minor", json_object_new_int(data->system_boot_data.minor)); 282 | json_object_object_add(o, "patch", json_object_new_int(data->system_boot_data.patch)); 283 | json_object_object_add(o, "build", json_object_new_int(data->system_boot_data.build)); 284 | json_object_object_add(o, "bootloader", json_object_new_int(data->system_boot_data.bootloader)); 285 | json_object_object_add(o, "hw", json_object_new_int(data->system_boot_data.hw)); 286 | json_object_object_add(o, "ble_hash", json_object_new_string(data->system_boot_data.ble_hash)); 287 | const char *temp = json_object_to_json_string(o); 288 | printf("MODULE_CB_MSG >> %s\n", temp); 289 | 290 | json_object_put(o); 291 | 292 | 293 | 294 | module_work = true; 295 | 296 | break; 297 | } 298 | default: 299 | break; 300 | } 301 | 302 | return 0; 303 | } 304 | 305 | static void sigal_hander(int sig) 306 | { 307 | printf("\nbleScanner exit!\n"); 308 | 309 | is_specified = false; 310 | gl_ble_stop_sync(handle); 311 | 312 | gl_ble_unsubscribe(); 313 | gl_ble_destroy(); 314 | 315 | exit(0); 316 | } 317 | -------------------------------------------------------------------------------- /src/example/bletool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( EXEC_NAME "bletool" ) 3 | 4 | aux_source_directory(./ SOURCES) 5 | 6 | include_directories(./ ) 7 | include_directories( ${PROJECT_SOURCE_DIR}/lib/include ) 8 | include_directories( ${PROJECT_SOURCE_DIR}/bledriver/silabs ) 9 | 10 | 11 | add_executable( ${EXEC_NAME} ${SOURCES} ) 12 | 13 | # link_directories( ${PROJECT_SOURCE_DIR}/build/lib ) 14 | target_link_libraries( ${EXEC_NAME} PRIVATE json-c glbleapi readline ncurses) 15 | 16 | 17 | install( 18 | TARGETS ${EXEC_NAME} 19 | RUNTIME DESTINATION bin 20 | ) 21 | -------------------------------------------------------------------------------- /src/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set( LIB_NAME "glbleapi" ) 3 | 4 | # debug log 5 | # add_definitions(-DENABLE_DEBUG ) 6 | 7 | # lib c file 8 | aux_source_directory(./ SOURCES) 9 | aux_source_directory(${PROJECT_SOURCE_DIR}/bledriver/silabs SOURCES) 10 | aux_source_directory(${PROJECT_SOURCE_DIR}/bledriver/util SOURCES) 11 | aux_source_directory(${PROJECT_SOURCE_DIR}/components/dev_mgr SOURCES) 12 | aux_source_directory(${PROJECT_SOURCE_DIR}/components/log SOURCES) 13 | aux_source_directory(${PROJECT_SOURCE_DIR}/components/thread SOURCES) 14 | aux_source_directory(${PROJECT_SOURCE_DIR}/components/timestamp SOURCES) 15 | 16 | # compile h file 17 | include_directories(./include ) 18 | include_directories( ${PROJECT_SOURCE_DIR}/bledriver/model_hw_cfg ) 19 | include_directories( ${PROJECT_SOURCE_DIR}/bledriver/silabs ) 20 | include_directories( ${PROJECT_SOURCE_DIR}/bledriver/util ) 21 | include_directories( ${PROJECT_SOURCE_DIR}/components/dev_mgr ) 22 | include_directories( ${PROJECT_SOURCE_DIR}/components/log ) 23 | include_directories( ${PROJECT_SOURCE_DIR}/components/thread ) 24 | include_directories( ${PROJECT_SOURCE_DIR}/components/timestamp ) 25 | 26 | # lib h file 27 | set( HEADERS ./include/gl_bleapi.h 28 | ./include/gl_errno.h 29 | ./include/gl_type.h ) 30 | 31 | add_compile_options(-fPIC) 32 | 33 | add_library( ${LIB_NAME} SHARED ${SOURCES} ) 34 | add_library( lib_static STATIC ${SOURCES} ) 35 | SET_TARGET_PROPERTIES(lib_static PROPERTIES OUTPUT_NAME "glbleapi") 36 | 37 | target_link_libraries( ${LIB_NAME} PRIVATE pthread uci) 38 | 39 | install( 40 | TARGETS ${LIB_NAME} 41 | DESTINATION lib 42 | ) 43 | 44 | install( 45 | TARGETS lib_static 46 | DESTINATION lib 47 | ) 48 | 49 | install( 50 | FILES ${HEADERS} 51 | DESTINATION include 52 | ) -------------------------------------------------------------------------------- /src/lib/include/gl_errno.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright 2022 GL-iNet. https://www.gl-inet.com/ 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | ******************************************************************************/ 16 | #ifndef _GL_ERRNO_H_ 17 | #define _GL_ERRNO_H_ 18 | 19 | #include 20 | /** 21 | * @defgroup RETURN_CODE RETURN_CODE 22 | * The return value definition of the API 23 | */ 24 | 25 | /** 26 | * @defgroup GL_RETURN_CODE GL_RETURN_CODE 27 | * @ingroup RETURN_CODE 28 | * RETURN CODE define by GL-iNet 29 | * @{ 30 | */ 31 | 32 | /* 33 | * 0x0000 - 0x00FF Error code defined by GL-iNet 34 | * 0x0100 - 0xFFFF Error code defined by ble module manufacturer 35 | * Error code defined by Silabs: \src\daemon\bledriver\silabs\bg_errorcodes.h 36 | * 37 | */ 38 | 39 | enum gl_error_spaces { 40 | /** 41 | * @brief The base num of return code for GL-iNet. 42 | */ 43 | GL_ERR_BASE = 0, 44 | 45 | /** 46 | * @brief The base num of return code for chip manufacturer. 47 | */ 48 | MANUFACTURER_ERR_BASE = 0x0100, 49 | }; 50 | 51 | typedef int32_t GL_RET; 52 | 53 | typedef enum gl_error { 54 | 55 | /** 56 | * @brief The generic "no error" message. 57 | */ 58 | GL_SUCCESS = GL_ERR_BASE + 0, 59 | 60 | /** 61 | * @brief The generic "unknow error" message. 62 | */ 63 | GL_UNKNOW_ERR = GL_ERR_BASE + 1, 64 | 65 | /** 66 | * @brief Response missing. 67 | */ 68 | GL_ERR_RESP_MISSING = GL_ERR_BASE + 2, 69 | 70 | /** 71 | * @brief Event missing. 72 | */ 73 | GL_ERR_EVENT_MISSING = GL_ERR_BASE + 3, 74 | 75 | /** 76 | * @brief Param missing. 77 | */ 78 | GL_ERR_PARAM_MISSING = GL_ERR_BASE + 4, 79 | 80 | /** 81 | * @brief Message error. 82 | */ 83 | GL_ERR_MSG = GL_ERR_BASE + 5, 84 | 85 | /** 86 | * @brief Param error. 87 | */ 88 | GL_ERR_PARAM = GL_ERR_BASE + 6, 89 | 90 | /** 91 | * @brief Invoking function in error mode. 92 | */ 93 | GL_ERR_INVOKE = GL_ERR_BASE + 7, 94 | 95 | /** 96 | * @brief Unsupprot hardware model. 97 | */ 98 | GL_ERR_UNSUPPORT_MODEL = GL_ERR_BASE + 8, 99 | }errcode_t; 100 | 101 | #endif -------------------------------------------------------------------------------- /version.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2020 Jianhui Zhao 3 | # 4 | # This is free software, licensed under the MIT. 5 | # 6 | 7 | define findrev 8 | $(shell \ 9 | if git log -1 >/dev/null 2>/dev/null; then \ 10 | set -- $$(git log -1 --format="%ct %h" --abbrev=7 -- .); \ 11 | if [ -n "$$1" ]; then 12 | secs="$$(($$1 % 86400))"; \ 13 | yday="$$(date --utc --date="@$$1" "+%Y.%j")"; \ 14 | printf 'git-%s.%05d-%s' "$$yday" "$$secs" "$$2"; \ 15 | else \ 16 | echo "unknown"; \ 17 | fi; \ 18 | else \ 19 | ts=$$(find . -type f -printf '%T@\n' 2>/dev/null | sort -rn | head -n1 | cut -d. -f1); \ 20 | if [ -n "$$ts" ]; then \ 21 | secs="$$(($$ts % 86400))"; \ 22 | date="$$(date --utc --date="@$$ts" "+%Y%m%d")"; \ 23 | printf '%s.%05d' "$$date" "$$secs"; \ 24 | else \ 25 | echo "unknown"; \ 26 | fi; \ 27 | fi \ 28 | ) 29 | endef 30 | --------------------------------------------------------------------------------