mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-10 15:44:32 +00:00
Merge branch 'develop' into a2dp
Conflicts: example/Makefile.inc example/sco_demo_util.c port/pic32-harmony/app.X/nbproject/Makefile-default.mk port/pic32-harmony/app.X/nbproject/Makefile-genesis.properties port/pic32-harmony/app.X/nbproject/configurations.xml port/pic32-harmony/create_examples.py src/classic/btstack_cvsd_plc.c src/classic/btstack_sbc_bludroid.c src/classic/btstack_sbc_plc.c test/ring_buffer/.gitignore
This commit is contained in:
commit
25234a7e05
30
README.md
30
README.md
@ -27,8 +27,8 @@ It has been qualified with the the Bluetooth SIG for GAP, IOP, HFP, HSP, SPP, PA
|
||||
GATT, SM of the Bluetooth 4.2 LE Central and Peripheral roles (QD ID 25340).
|
||||
|
||||
## Documentation
|
||||
- [HTML](http://bluekitchen-gmbh.com/btstack)
|
||||
- [PDF](http://bluekitchen-gmbh.com/btstack.pdf)
|
||||
- [HTML](http://bluekitchen-gmbh.com/btstack/develop/)
|
||||
- [PDF](http://bluekitchen-gmbh.com/btstack_develop.pdf)
|
||||
|
||||
## Supported Protocols
|
||||
* L2CAP
|
||||
@ -55,24 +55,24 @@ Coming next: HID, HOGP, A2DP, and more.
|
||||
#### Embedded Platforms:
|
||||
Status | Platform
|
||||
-------------- | ------
|
||||
 | [EZ430-RF256x Bluetooth Evaluation Tool for MSP430](http://www.ti.com/tool/ez430-rf256x)
|
||||
 | [MSP430F5438 Experimenter Board for MSP430](http://www.ti.com/tool/msp-exp430f5438) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem)
|
||||
 | [MSP-EXP430F5529LP LaunchPad](http://www.ti.com/ww/en/launchpad/launchpads-msp430-msp-exp430f5529lp.html#tabs) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator
|
||||
 | [STM32 Nucleo development board NUCLEO-F103RB](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator
|
||||
 | [Microchip's PIC32 Bluetooth Audio Development Kit](http://www.microchip.com/Developmenttools/ProductDetails.aspx?PartNO=DV320032)
|
||||
 | [RedBear Duo](https://github.com/redbear/WICED-SDK) with Broadcom BCM43438 A1
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-ez430-rf2560-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-ez430-rf2560-develop) | [EZ430-RF256x Bluetooth Evaluation Tool for MSP430](http://www.ti.com/tool/ez430-rf256x)
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-msp-exp430f5438-cc2564b-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-msp-exp430f5438-cc2564b-develop) | [MSP430F5438 Experimenter Board for MSP430](http://www.ti.com/tool/msp-exp430f5438) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem)
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-msp430f5229lp-cc2564b-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-msp430f5229lp-cc2564b-develop) | [MSP-EXP430F5529LP LaunchPad](http://www.ti.com/ww/en/launchpad/launchpads-msp430-msp-exp430f5529lp.html#tabs) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-stm32-f103rb-nucleo-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-stm32-f103rb-nucleo-develop) | [STM32 Nucleo development board NUCLEO-F103RB](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-pic32-harmony-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-pic32-harmony-develop) | [Microchip's PIC32 Bluetooth Audio Development Kit](http://www.microchip.com/Developmenttools/ProductDetails.aspx?PartNO=DV320032)
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-wiced-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-wiced-develop) | [RedBear Duo](https://github.com/redbear/WICED-SDK) with Broadcom BCM43438 A1
|
||||
|
||||
|
||||
#### Other Platforms:
|
||||
Status | Platform
|
||||
-------------- | ------
|
||||
| posix: Unix-based system talking to Bluetooth module via serial port
|
||||
| libusb: Unix-based system talking via USB Bluetooth dongle
|
||||
| daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients
|
||||
| java: Java wrapper for daemon
|
||||
| iOS: daemon for iOS jailbreak devices, C client-server API
|
||||
| mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API
|
||||
 | wiced: Broadcom platforms that support the WICED SDK
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-posix-h4-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-posix-h4-develop) | posix: Unix-based system talking to Bluetooth module via serial port
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-libusb-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-libusb-develop) | libusb: Unix-based system talking via USB Bluetooth dongle
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-daemon-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-daemon-develop) | daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=java-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/java-develop) | java: Java wrapper for daemon
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-ios-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-ios-develop) | iOS: daemon for iOS jailbreak devices, C client-server API
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-mtk-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-mtk-develop) | mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-wiced-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-wiced-develop) | wiced: Broadcom platforms that support the WICED SDK
|
||||
|
||||
## Supported Chipsets
|
||||
Chipsets | Status
|
||||
|
@ -1,8 +1,6 @@
|
||||
all:
|
||||
rm -rf tmp
|
||||
mkdir tmp
|
||||
./update_apis.py
|
||||
./update_listings.py
|
||||
all: update_docs_and_apis html pdf
|
||||
|
||||
html:
|
||||
rm -rf docs_tmp
|
||||
rm -rf docs_final
|
||||
cp -r docs docs_tmp
|
||||
@ -11,6 +9,8 @@ all:
|
||||
rm -rf docs_tmp
|
||||
mkdocs build --clean
|
||||
./mkdocs2html.py
|
||||
|
||||
pdf:
|
||||
mkdir -p latex
|
||||
cp -r docs/picts latex
|
||||
./markdown2pdf.py
|
||||
@ -18,7 +18,19 @@ all:
|
||||
cd latex && pdflatex btstack_gettingstarted.tex && pdflatex btstack_gettingstarted.tex
|
||||
mv latex/btstack_gettingstarted.pdf btstack.pdf
|
||||
rm -rf latex tmp
|
||||
|
||||
|
||||
|
||||
preview: update_docs_and_apis html
|
||||
# race condition, open browser before startnig MKdocs
|
||||
open http://127.0.0.1:8000
|
||||
mkdocs serve
|
||||
|
||||
update_docs_and_apis:
|
||||
rm -rf tmp
|
||||
mkdir tmp
|
||||
./update_apis.py
|
||||
./update_listings.py
|
||||
|
||||
clean:
|
||||
rm -rf docs_final tmp btstack *.pdf latex/btstack_generated.* latex/btstack_final.tex
|
||||
rm -rf docs/appendix/apis.md docs/appendix/index.md docs/examples/examples.md
|
||||
|
95
doc/manual/docs/chipsets.md
Normal file
95
doc/manual/docs/chipsets.md
Normal file
@ -0,0 +1,95 @@
|
||||
In this chapter, we first explain how Bluetooth chipsets are connected physically and
|
||||
then provide information about popular Bluetooth chipset and their use with BTstack.
|
||||
|
||||
The communication between a Host (a computer or an MCU) and a Host Controller (the actual Bluetoot chipset) follows the Host Controller Interface (HCI), see {@fig:HostChipsetConnection}. HCI defines how commands, events, asynchronous and synchronous data packets are exchanged, see [here]). Asynchronous packets (ACL) are used for data transfer, while synchronous packets (SCO) are used for Voice with the Headset and the Hands-free Profiles.
|
||||
|
||||
{#fig:HostChipsetConnection}
|
||||
|
||||
On desktop-class computers incl. laptops, USB is mainly used as HCI transport layer. On embedded systems, UART connections are used instead, although USB could be used as well.
|
||||
|
||||
For UART connections, different transport layer variants exist. The most common one is the official "UART Transport", also called H4. It requires hardware flow control via the CTS/RTS lines and assumes no errors on the UART lines. The "Three-Wire UART Transport", also called H5, makes use of the SLIP protocol to transmit a packet and can deal with packet loss and bit-errors by retranssion. Finally, Texas Instruments created the "eHCILL transport" layer based on H4 that allows both sides to enter sleep mode without loosing synchronisation.
|
||||
|
||||
Unfortunately, the HCI standard misses a few relevant details:
|
||||
|
||||
* For UART based connections, the initial baud rate isn't defined but most Bluetooth chipsets use 115200 baud. For better throughput, a higher baud rate is necessary, but there's no standard HCI command to change it. Instead, each vendor had to come up with their own set of vendor-specific commands. Sometimes, additional steps, e.g. doing a warm reset, are neceesary to activate the baud rate change as well.
|
||||
|
||||
* Some Bluetooth chipsets don't have a unique MAC address. On start, the MAC address needs to be set, but there's no standard HCI command to set it.
|
||||
|
||||
* SCO data for Voice can either be transmitted via the HCI interface or via an explicit PCM/I2S interface on the chipset. Most chipsets default to the PCM/I2S interface. To use it via USB or for Wide-Band Speech in the Hands-Free Profile, the data needs to be delivered to the host MCU. Newer Bluetooth standards define a HCI command to configure the routing, but it is not implemented in the chipsets we've tested so far. Instead, this is configured in a vendor-specific way as well.
|
||||
|
||||
* In addition, most vendors allow to patch their chipsets at run time by sending patch comands to the chipset. Obviously, this is also vendor dependent.
|
||||
|
||||
|
||||
The level of developer documentation and support varies widely between the various Bluetooth chipset providers.
|
||||
|
||||
From our experience, only Texas Instruments and EM Microelectronics provide all relevant information directly on their website. Nordic Semiconductor does not officially have Bluetooth chipsets with HCI interface, but their the documentation on their nRF5 series is complete and very informative. TI and Nordic also provide excellent support via their web forum.
|
||||
|
||||
Broadcom, whose Bluetooth + Wifi division has been acquired by the Cypress Semiconductor Corporation, provides developer documentation only to large customers as far as we know. It's possible to join their Community forum and download the WICED SDK. The WICED SDK is targeted at Wifi + Bluetooth Combo chipsets and contains the necessary chipset patch files.
|
||||
|
||||
CSR, which has been acquired by Qualcomm, provides all relevant information on their Support website after signing an NDA.
|
||||
|
||||
Chipset | HCI Transport | SCO over HCI | BTstack support | Comment
|
||||
-------------------- | ---------------|------------------|-------------------|--------
|
||||
Broadcom USB Dongles | USB | No (didn't work) | chipset/bcm |
|
||||
Broadcom BCM43438 | H4, H5 | No (didn't work) | chipset/bcm | max UART baudrate 3 mbps
|
||||
CSR 8x10, 8x11 | H4, H5 | No (didn't work) | chipset/csr |
|
||||
CSR USB Dongles | USB | Yes | chipset/csr |
|
||||
EM 9301 | SPI | n.a. | chipset/em9301 | LE only, custom HCI SPI implementation
|
||||
Nordic nRF | H4 | n.a. | n.a. | LE only, requires HCI firmware
|
||||
STM STLC2500D | H4 | No (didn't try) | chipset/stlc2500d | custom deep sleep management not supported
|
||||
TC35661 | H4 | No (didn't try) | chipset/tc3566 | BLE patches missing
|
||||
TI CC256x, WL183x | H4, H5, eHCILL | Yes | chipset/cc256x | also WL185x, WL187x, and WL189x
|
||||
|
||||
**Note** All Bluetooth Classic chipsets support SCO over HCI, for those that are marked with No, we either didn't try or didn't found enough information to configure it correctly.
|
||||
|
||||
## Broadcom
|
||||
|
||||
## CSR
|
||||
|
||||
## EM Microelectronic Marin
|
||||
|
||||
## Nordic nRF5 series
|
||||
|
||||
## ST Micro
|
||||
|
||||
## Texas Instruments CC256x series
|
||||
|
||||
The Texas Instruments CC256x series is currently in its third iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT model (CC2567). A variant of the Dual-mode chipset is also integrated into TI's WiLink 8 Wifi+Bluetooth combo modules of the WL183x, WL185x, WL187x, and WL189x series.
|
||||
|
||||
The CC256x chipset is connected via an UART connection and supports the H4, H5 (since third iteration), and eHCILL.
|
||||
|
||||
**SCO data** is routed to the I2S/PCM interface but can be configured with the [HCI_VS_Write_SCO_Configuration](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Write_SCO_Configuration_.280xFE10.29) command.
|
||||
|
||||
**Baud rate** can be set with [HCI_VS_Update_UART_HCI_Baudrate](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Update_UART_HCI_Baudrate_.280xFF36.29)
|
||||
|
||||
**BD Addr** can be set with [HCI_VS_Write_BD_Addr](2.2.1 HCI_VS_Write_BD_Addr (0xFC06)) although all chipsets have an official address stored.
|
||||
|
||||
**CC256x Init Scripts.** In order to use the CC256x chipset an initialization script must be obtained and converted into a C file for use with BTstack.
|
||||
|
||||
The Makefile at *chipset/cc256x/Makefile* is able to automatically download and convert the requested file. It does this by:
|
||||
|
||||
- Downloading one or more [BTS files](http://processors.wiki.ti.com/index.php/CC256x_Downloads) for your chipset.
|
||||
- Running runnig the Python script:
|
||||
|
||||
<!-- -->
|
||||
|
||||
./convert_bts_init_scripts.py
|
||||
|
||||
**Update:** For the latest revision of the CC256x chipsets, the CC2560B
|
||||
and CC2564B, TI decided to split the init script into a main part and
|
||||
the BLE part. The conversion script has been updated to detect
|
||||
*bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts*
|
||||
if present and merges them into a single .c file.
|
||||
|
||||
**Update 2:** In May 2015, TI renamed the init scripts to match
|
||||
the naming scheme previously used on Linux systems. The conversion
|
||||
script has been updated to also detect *initscripts_TIInit_6.7.16_bt_spec_4.1.bts*
|
||||
and integrates *initscripts_TIInit_6.7.16_ble_add-on.bts* if present.
|
||||
|
||||
**BTstack integration**: The common code for all CC256x chipsets is provided by *btstack_chipset_cc256x.c*. During the setup, *btstack_chipset_cc256x_instance* function is used to get a *btstack_control_t* instance and passed to *hci_init* function.
|
||||
|
||||
SCO Data can be route over HCI, so HFP Wide-Band Speech is supported.
|
||||
|
||||
## Toshiba
|
||||
|
||||
|
20
doc/manual/docs/gatt_services.md
Normal file
20
doc/manual/docs/gatt_services.md
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
BTstack allows to implement and use GATT Services in a modular way.
|
||||
|
||||
To use an already implemented GATT Service, you only have to add it to your application's
|
||||
GATT file with:
|
||||
|
||||
- *#import <service_name.gatt>* for .gatt files located in *src/ble/gatt-service*
|
||||
- *#import "service_name.gatt"* for .gatt files located in the same folder as your application's .gatt file.
|
||||
|
||||
Each service will have an API at *src/ble/gatt-service/service_name_server.h. To activate it, you need
|
||||
to call *service_name_init(..)*. Please see the .h file for details.
|
||||
|
||||
### Battery Service {#sec:BatteryService}}
|
||||
|
||||
The Battery Service allows to query your device's battery level in a standardized way.
|
||||
|
||||
After adding it to your .gatt file, you call *battery_service_server_init(value)* with the
|
||||
current value of your battery. The valid range for the battery level is 0-100.
|
||||
|
||||
If the battery level changes, you can call *battery_service_server_set_battery_value(value)*. The service supports sending Notifications if the client enables them.
|
@ -75,7 +75,7 @@ ENABLE_LOG_INFO | Enable log_info messages
|
||||
ENABLE_LOG_INTO_HCI_DUMP | Log debug messages as part of packet log
|
||||
ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (only CC256x/WL18xx and USB CSR controllers)
|
||||
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections using [mbed TLS library](https://tls.mbed.org)
|
||||
|
||||
ENABLE_LE_DATA_CHANNELS | Enable LE Data Channels in credit-based flow control mode
|
||||
|
||||
### Memory configuration directives {#sec:memoryConfigurationHowTo}
|
||||
|
||||
|
BIN
doc/manual/docs/picts/host_chipset_connection.pdf
Normal file
BIN
doc/manual/docs/picts/host_chipset_connection.pdf
Normal file
Binary file not shown.
BIN
doc/manual/docs/picts/host_chipset_connection.png
Normal file
BIN
doc/manual/docs/picts/host_chipset_connection.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
@ -77,10 +77,10 @@ struct suitable for the CC256x chipset.
|
||||
|
||||
|
||||
On embedded systems, a Bluetooth module can be connected via USB or an
|
||||
UART port. BTstack implements two UART based protocols for carrying HCI
|
||||
UART port. BTstack implements three UART based protocols for carrying HCI
|
||||
commands, events and data between a host and a Bluetooth module: HCI
|
||||
UART Transport Layer (H4) and H4 with eHCILL support, a lightweight
|
||||
low-power variant by Texas Instruments.
|
||||
UART Transport Layer (H4), H4 with eHCILL support, a lightweight
|
||||
low-power variant by Texas Instruments, and the Three-Wire UART Transport Layer (H5).
|
||||
|
||||
|
||||
### HCI UART Transport Layer (H4) {#sec:hciUARTPorting}
|
||||
@ -137,6 +137,19 @@ callback for CTS interrupts.
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep);
|
||||
|
||||
|
||||
### H5
|
||||
|
||||
H5, makes use of the SLIP protocol to transmit a packet and can deal
|
||||
with packet loss and bit-errors by retranssion. Since it can recover
|
||||
from packet loss, it's also possible for either side to enter sleep
|
||||
mode without loosing synchronization.
|
||||
|
||||
The use of hardware flow control in H5 is ooptional, however, since
|
||||
BTstack uses hardware flow control to avoid packet buffers, it's
|
||||
recommended to only use H5 with RTS/CTS as well.
|
||||
|
||||
For porting, the implementation follows the regular H4 procotol described above.
|
||||
|
||||
## Persistent Storage APIs {#sec:persistentStoragePorting}
|
||||
|
||||
On embedded systems there is no generic way to persist data like link
|
||||
|
@ -408,6 +408,9 @@ The current format is shown in Listing [below](#lst:GATTServerProfile).
|
||||
|
||||
~~~~ {#lst:GATTServerProfile .c caption="{GATT profile.}"}
|
||||
|
||||
// import service_name
|
||||
#import <service_name.gatt>
|
||||
|
||||
PRIMARY_SERVICE, {SERVICE_UUID}
|
||||
CHARACTERISTIC, {ATTRIBUTE_TYPE_UUID}, {PROPERTIES}, {VALUE}
|
||||
CHARACTERISTIC, {ATTRIBUTE_TYPE_UUID}, {PROPERTIES}, {VALUE}
|
||||
@ -438,6 +441,9 @@ To require encryption or authentication before a Characteristic can be
|
||||
accessed, you can add ENCRYPTION_KEY_SIZE_X - with $X \in [7..16]$ -
|
||||
or AUTHENTICATION_REQUIRED.
|
||||
|
||||
To use already implemented GATT Services, you can import it
|
||||
using the *#import <service_name.gatt>* command. See [list of provided services](gatt_services.md).
|
||||
|
||||
BTstack only provides an ATT Server, while the GATT Server logic is
|
||||
mainly provided by the GATT compiler. While GATT identifies
|
||||
Characteristics by UUIDs, ATT uses Handles (16 bit values). To allow to
|
||||
@ -447,3 +453,88 @@ compiler creates a list of defines in the generated \*.h file.
|
||||
Similar to other protocols, it might be not possible to send any time.
|
||||
To send a Notification, you can call *att_server_request_can_send_now*
|
||||
to receive a ATT_EVENT_CAN_SEND_NOW event.
|
||||
|
||||
### Implementing Standard GATT Services {#sec:GATTStandardServices}
|
||||
|
||||
Implementation of a standard GATT Service consists of the following 4 steps:
|
||||
|
||||
1. Identify full Service Name
|
||||
2. Use Service Name to fetch XML definition at Bluetooth SIG site and convert into generic .gatt file
|
||||
3. Edit .gatt file to set constant values and exclude unwanted Characteristics
|
||||
4. Implement Service server, e.g., battery_service_server.c
|
||||
|
||||
Step 1:
|
||||
|
||||
To facilitate the creation of .gatt files for standard profiles defined by the Bluetooth SIG,
|
||||
the *tool/convert_gatt_service.py* script can be used. When run without a parameter, it queries the
|
||||
Bluetooth SIG website and lists the available Services by their Specification Name, e.g.,
|
||||
*org.bluetooth.service.battery_service*.
|
||||
|
||||
$ tool/convert_gatt_service.py
|
||||
Fetching list of services from https://www.bluetooth.com/specifications/gatt/services
|
||||
|
||||
Specification Type | Specification Name | UUID
|
||||
-------------------------------------------------------+-------------------------------+-----------
|
||||
org.bluetooth.service.alert_notification | Alert Notification Service | 0x1811
|
||||
org.bluetooth.service.automation_io | Automation IO | 0x1815
|
||||
org.bluetooth.service.battery_service | Battery Service | 0x180F
|
||||
...
|
||||
org.bluetooth.service.weight_scale | Weight Scale | 0x181D
|
||||
|
||||
To convert a service into a .gatt file template, please call the script again with the requested Specification Type and the output file name
|
||||
Usage: tool/convert_gatt_service.py SPECIFICATION_TYPE [service_name.gatt]
|
||||
|
||||
Step 2:
|
||||
|
||||
To convert service into .gatt file, call *tool/convert_gatt_service.py with the requested Specification Type and the output file name.
|
||||
|
||||
$ tool/convert_gatt_service.py org.bluetooth.service.battery_service battery_service.gatt
|
||||
Fetching org.bluetooth.service.battery_service from
|
||||
https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml
|
||||
|
||||
Service Battery Service
|
||||
- Characteristic Battery Level - properties ['Read', 'Notify']
|
||||
-- Descriptor Characteristic Presentation Format - TODO: Please set values
|
||||
-- Descriptor Client Characteristic Configuration
|
||||
|
||||
Service successfully converted into battery_service.gatt
|
||||
Please check for TODOs in the .gatt file
|
||||
|
||||
|
||||
Step 3:
|
||||
|
||||
In most cases, you will need to customize the .gatt file. Please pay attention to the tool output and have a look
|
||||
at the generated .gatt file.
|
||||
|
||||
E.g. in the generated .gatt file for the Battery Service
|
||||
|
||||
// Specification Type org.bluetooth.service.battery_service
|
||||
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml
|
||||
|
||||
// Battery Service 180F
|
||||
PRIMARY_SERVICE, ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, DYNAMIC | READ | NOTIFY,
|
||||
// TODO: Characteristic Presentation Format: please set values
|
||||
#TODO CHARACTERISTIC_FORMAT, READ, _format_, _exponent_, _unit_, _name_space_, _description_
|
||||
CLIENT_CHARACTERISTIC_CONFIGURATION, READ | WRITE,
|
||||
|
||||
you could delete the line regarding the CHARACTERISTIC_FORMAT, since it's not required if there is a single instance of the service.
|
||||
Please compare the .gatt file against the [Adopted Specifications](https://www.bluetooth.com/specifications/adopted-specifications).
|
||||
|
||||
Step 4:
|
||||
|
||||
As described [above](#sec:GATTServerProfiles) all read/write requests are handled by the application.
|
||||
To implement the new services as a reusable module, it's neccessary to get access to all read/write requests related to this service.
|
||||
|
||||
For this, the ATT DB allows to register read/write callbacks for a specific handle range with *att_server_register_can_send_now_callback()*.
|
||||
|
||||
Since the handle range depends on the application's .gatt file, the handle range for Primary and Secondary Services can be queried with *gatt_server_get_get_handle_range_for_service_with_uuid16*.
|
||||
|
||||
Similarly, you will need to know the attribute handle for particular Characteristics to handle Characteristic read/writes requests. You can get the attribute value handle for a Characteristics *gatt_server_get_value_handle_for_characteristic_with_uuid16()*.
|
||||
|
||||
In addition to the attribute value handle, the handle for the Client Characteristic Configuration is needed to support Indications/Notifications. You can get this attribute handle with *gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16()*
|
||||
|
||||
Finally, in order to send Notifications and Indications independently from the main application, *att_server_register_can_send_now_callback* can be used to request a callback when it's possible to send a Notification or Indication.
|
||||
|
||||
To see how this works together, please check out the Battery Service Server in *src/ble/battery_service_server.c*.
|
||||
|
||||
|
@ -303,6 +303,26 @@ as soon as possible. It might happen that the event is received via
|
||||
packet handler before the *l2cap_request_can_send_now_event* function returns.
|
||||
The L2CAP_EVENT_CAN_SEND_NOW indicates a channel ID on which sending is possible.
|
||||
|
||||
### LE Data Channels
|
||||
|
||||
The full title for LE Data Channels is actually LE Connection-Oriented Channels with LE Credit-Based Flow-Control Mode. In this mode, data is sent as Service Data Units (SDUs) that can be larger than an individual HCI LE ACL packet.
|
||||
|
||||
LE Data Channels are similar to Classic L2CAP Channels but also provide a credit-based flow control similar to RFCOMM Channels.
|
||||
Unless the LE Data Packet Extension of Bluetooth Core 4.2 specification is used, the maximum packet size for LE ACL packets is 27 bytes. In order to send larger packets, each packet will be split into multiple ACL LE packets and recombined on the receiving side.
|
||||
|
||||
Since multiple SDUs can be transmitted at the same time and the individual ACL LE packets can be sent interleaved, BTstack requires a dedicated receive buffer per channel that has to be passed when creating the channel or accepting it. Similarly, when sending SDUs, the data provided to the *l2cap_le_send_data* must stay valid until the *L2CAP_EVENT_LE_PACKET_SENT* is received.
|
||||
|
||||
When creating an outgoing connection of accepting an incoming, the *initial_credits* allows to provide a fixed number of credits to the remote side. Further credits can be provided anytime with *l2cap_le_provide_credits*. If *L2CAP_LE_AUTOMATIC_CREDITS* is used, BTstack automatically provides credits as needed - effectively trading in the flow-control functionality for convenience.
|
||||
|
||||
The remainder of the API is similar to the one of L2CAP:
|
||||
|
||||
* *l2cap_le_register_service* and *l2cap_le_unregister_service* are used to manage local services.
|
||||
* *l2cap_le_accept_connection* and *l2cap_le_decline_connection* are used to accept or deny an incoming connection request.
|
||||
* *l2cap_le_create_channel* creates an outgoing connections.
|
||||
* *l2cap_le_can_send_now* checks if a packet can be scheduled for transmission now.
|
||||
* *l2cap_le_request_can_send_now_event* requests an *L2CAP_EVENT_LE_CAN_SEND_NOW* event as soon as possible.
|
||||
* *l2cap_le_disconnect* closes the connection.
|
||||
|
||||
## RFCOMM - Radio Frequency Communication Protocol
|
||||
|
||||
The Radio frequency communication (RFCOMM) protocol provides emulation
|
||||
@ -311,7 +331,6 @@ for the Serial Port Profile and other profiles used for
|
||||
telecommunication like Head-Set Profile, Hands-Free Profile, Object
|
||||
Exchange (OBEX) etc.
|
||||
|
||||
|
||||
### RFCOMM flow control {#sec:flowControlProtocols}
|
||||
|
||||
RFCOMM has a mandatory credit-based flow-control. This means that two
|
||||
|
@ -8,6 +8,7 @@ pages:
|
||||
- [how_to.md, How to configure BTstack]
|
||||
- [protocols.md, Supported Protocols]
|
||||
- [profiles.md, Supported Profiles]
|
||||
- [gatt_services.md, Implemented GATT Services]
|
||||
- [examples/examples.md, Embedded Examples]
|
||||
- [porting.md, Porting to Other Platforms]
|
||||
- [integration.md, Integrating with Existing Systems]
|
||||
|
53
doc/notes/hci_commands_used.txt
Normal file
53
doc/notes/hci_commands_used.txt
Normal file
@ -0,0 +1,53 @@
|
||||
hci_accept_connection_request
|
||||
hci_accept_synchronous_connection
|
||||
hci_authentication_requested
|
||||
hci_create_connection
|
||||
hci_delete_stored_link_key
|
||||
hci_disconnect
|
||||
hci_io_capability_request_negative_reply
|
||||
hci_io_capability_request_reply
|
||||
hci_le_add_device_to_white_list
|
||||
hci_le_connection_update
|
||||
hci_le_create_connection
|
||||
hci_le_create_connection_cancel
|
||||
hci_le_encrypt
|
||||
hci_le_long_term_key_negative_reply
|
||||
hci_le_long_term_key_request_reply
|
||||
hci_le_rand
|
||||
hci_le_read_buffer_size
|
||||
hci_le_read_white_list_size
|
||||
hci_le_remove_device_from_white_list
|
||||
hci_le_set_advertise_enable
|
||||
hci_le_set_advertising_data
|
||||
hci_le_set_advertising_parameters
|
||||
hci_le_set_random_address
|
||||
hci_le_set_scan_enable
|
||||
hci_le_set_scan_parameters
|
||||
hci_le_set_scan_response_data
|
||||
hci_le_start_encryption
|
||||
hci_link_key_request_negative_reply
|
||||
hci_link_key_request_reply
|
||||
hci_pin_code_request_negative_reply
|
||||
hci_read_bd_addr
|
||||
hci_read_buffer_size
|
||||
hci_read_local_supported_commands
|
||||
hci_read_local_supported_features
|
||||
hci_read_local_version_information
|
||||
hci_read_remote_supported_features_command
|
||||
hci_reject_connection_request
|
||||
hci_reset
|
||||
hci_set_connection_encryption
|
||||
hci_set_event_mask
|
||||
hci_setup_synchronous_connection
|
||||
hci_user_confirmation_request_reply
|
||||
hci_user_passkey_request_reply
|
||||
hci_write_class_of_device
|
||||
hci_write_default_erroneous_data_reporting
|
||||
hci_write_extended_inquiry_response
|
||||
hci_write_inquiry_mode
|
||||
hci_write_le_host_supported
|
||||
hci_write_local_name
|
||||
hci_write_page_timeout
|
||||
hci_write_scan_enable
|
||||
hci_write_simple_pairing_mode
|
||||
hci_write_synchronous_flow_control_enable
|
53
doc/notes/hci_commands_used_all.txt
Normal file
53
doc/notes/hci_commands_used_all.txt
Normal file
@ -0,0 +1,53 @@
|
||||
hci_accept_connection_request
|
||||
hci_accept_synchronous_connection
|
||||
hci_authentication_requested
|
||||
hci_create_connection
|
||||
hci_delete_stored_link_key
|
||||
hci_disconnect
|
||||
hci_io_capability_request_negative_reply
|
||||
hci_io_capability_request_reply
|
||||
hci_le_add_device_to_white_list
|
||||
hci_le_connection_update
|
||||
hci_le_create_connection
|
||||
hci_le_create_connection_cancel
|
||||
hci_le_encrypt
|
||||
hci_le_long_term_key_negative_reply
|
||||
hci_le_long_term_key_request_reply
|
||||
hci_le_rand
|
||||
hci_le_read_buffer_size
|
||||
hci_le_read_white_list_size
|
||||
hci_le_remove_device_from_white_list
|
||||
hci_le_set_advertise_enable
|
||||
hci_le_set_advertising_data
|
||||
hci_le_set_advertising_parameters
|
||||
hci_le_set_random_address
|
||||
hci_le_set_scan_enable
|
||||
hci_le_set_scan_parameters
|
||||
hci_le_set_scan_response_data
|
||||
hci_le_start_encryption
|
||||
hci_link_key_request_negative_reply
|
||||
hci_link_key_request_reply
|
||||
hci_pin_code_request_negative_reply
|
||||
hci_read_bd_addr
|
||||
hci_read_buffer_size
|
||||
hci_read_local_supported_commands
|
||||
hci_read_local_supported_features
|
||||
hci_read_local_version_information
|
||||
hci_read_remote_supported_features_command
|
||||
hci_reject_connection_request
|
||||
hci_reset
|
||||
hci_set_connection_encryption
|
||||
hci_set_event_mask
|
||||
hci_setup_synchronous_connection
|
||||
hci_user_confirmation_request_reply
|
||||
hci_user_passkey_request_reply
|
||||
hci_write_class_of_device
|
||||
hci_write_default_erroneous_data_reporting
|
||||
hci_write_extended_inquiry_response
|
||||
hci_write_inquiry_mode
|
||||
hci_write_le_host_supported
|
||||
hci_write_local_name
|
||||
hci_write_page_timeout
|
||||
hci_write_scan_enable
|
||||
hci_write_simple_pairing_mode
|
||||
hci_write_synchronous_flow_control_enable
|
34
doc/notes/hci_commands_used_classic.txt
Normal file
34
doc/notes/hci_commands_used_classic.txt
Normal file
@ -0,0 +1,34 @@
|
||||
hci_accept_connection_request
|
||||
hci_accept_synchronous_connection
|
||||
hci_authentication_requested
|
||||
hci_create_connection
|
||||
hci_delete_stored_link_key
|
||||
hci_disconnect
|
||||
hci_io_capability_request_negative_reply
|
||||
hci_io_capability_request_reply
|
||||
hci_le_add_device_to_white_list
|
||||
hci_link_key_request_negative_reply
|
||||
hci_link_key_request_reply
|
||||
hci_pin_code_request_negative_reply
|
||||
hci_read_bd_addr
|
||||
hci_read_buffer_size
|
||||
hci_read_local_supported_commands
|
||||
hci_read_local_supported_features
|
||||
hci_read_local_version_information
|
||||
hci_read_remote_supported_features_command
|
||||
hci_reject_connection_request
|
||||
hci_reset
|
||||
hci_set_connection_encryption
|
||||
hci_set_event_mask
|
||||
hci_setup_synchronous_connection
|
||||
hci_user_confirmation_request_reply
|
||||
hci_user_passkey_request_reply
|
||||
hci_write_class_of_device
|
||||
hci_write_default_erroneous_data_reporting
|
||||
hci_write_extended_inquiry_response
|
||||
hci_write_inquiry_mode
|
||||
hci_write_local_name
|
||||
hci_write_page_timeout
|
||||
hci_write_scan_enable
|
||||
hci_write_simple_pairing_mode
|
||||
hci_write_synchronous_flow_control_enable
|
29
doc/notes/hci_commands_used_le.txt
Normal file
29
doc/notes/hci_commands_used_le.txt
Normal file
@ -0,0 +1,29 @@
|
||||
hci_disconnect
|
||||
hci_le_add_device_to_white_list
|
||||
hci_le_connection_update
|
||||
hci_le_create_connection
|
||||
hci_le_create_connection_cancel
|
||||
hci_le_encrypt
|
||||
hci_le_long_term_key_negative_reply
|
||||
hci_le_long_term_key_request_reply
|
||||
hci_le_rand
|
||||
hci_le_read_buffer_size
|
||||
hci_le_read_white_list_size
|
||||
hci_le_remove_device_from_white_list
|
||||
hci_le_set_advertise_enable
|
||||
hci_le_set_advertising_data
|
||||
hci_le_set_advertising_parameters
|
||||
hci_le_set_random_address
|
||||
hci_le_set_scan_enable
|
||||
hci_le_set_scan_parameters
|
||||
hci_le_set_scan_response_data
|
||||
hci_le_start_encryption
|
||||
hci_read_bd_addr
|
||||
hci_read_buffer_size
|
||||
hci_read_local_supported_commands
|
||||
hci_read_local_supported_features
|
||||
hci_read_local_version_information
|
||||
hci_read_remote_supported_features_command
|
||||
hci_reset
|
||||
hci_set_event_mask
|
||||
hci_write_le_host_supported
|
@ -1,6 +1,7 @@
|
||||
|
||||
VPATH += ${BTSTACK_ROOT}/src
|
||||
VPATH += ${BTSTACK_ROOT}/src/ble
|
||||
VPATH += ${BTSTACK_ROOT}/src/ble/gatt-service
|
||||
VPATH += ${BTSTACK_ROOT}/src/classic
|
||||
VPATH += ${BTSTACK_ROOT}/example
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/mbedtls/library
|
||||
@ -33,6 +34,8 @@ COMMON += \
|
||||
hci_dump.c \
|
||||
l2cap.c \
|
||||
l2cap_signaling.c \
|
||||
|
||||
CLASSIC += \
|
||||
btstack_link_key_db_memory.c \
|
||||
sdp_util.c \
|
||||
spp_server.c \
|
||||
@ -55,7 +58,7 @@ GATT_CLIENT += \
|
||||
ad_parser.c \
|
||||
gatt_client.c \
|
||||
|
||||
SM_REAL += \
|
||||
SM += \
|
||||
sm.c \
|
||||
|
||||
PAN += \
|
||||
@ -122,7 +125,8 @@ EXAMPLES_USING_LE = \
|
||||
# .o for .c
|
||||
CORE_OBJ = $(CORE:.c=.o)
|
||||
COMMON_OBJ = $(COMMON:.c=.o)
|
||||
SM_REAL_OBJ = $(SM_REAL:.c=.o) $(MBEDTLS:.c=.o)
|
||||
CLASSIC_OBJ = $(CLASSIC:.c=.o)
|
||||
SM_OBJ = $(SM:.c=.o) $(MBEDTLS:.c=.o)
|
||||
ATT_OBJ = $(ATT:.c=.o)
|
||||
GATT_CLIENT_OBJ = $(GATT_CLIENT:.c=.o)
|
||||
GATT_SERVER_OBJ = $(GATT_SERVER:.c=.o)
|
||||
@ -148,55 +152,55 @@ sm_pairing_peripheral.h: sm_pairing_peripheral.gatt
|
||||
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
|
||||
|
||||
# examples
|
||||
sdp_rfcomm_query: ${CORE_OBJ} ${COMMON_OBJ} ${PAN_OBJ} ${SDP_CLIENT} sdp_rfcomm_query.c
|
||||
sdp_rfcomm_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${PAN_OBJ} ${SDP_CLIENT} sdp_rfcomm_query.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sdp_general_query: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} sdp_general_query.c
|
||||
sdp_general_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} sdp_general_query.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sdp_bnep_query: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} sdp_bnep_query.c
|
||||
sdp_bnep_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} sdp_bnep_query.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
spp_counter: ${CORE_OBJ} ${COMMON_OBJ} spp_counter.c
|
||||
spp_counter: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} spp_counter.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
le_counter: le_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} le_counter.c
|
||||
le_counter: le_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_OBJ} battery_service_server.o le_counter.c
|
||||
${CC} $(filter-out le_counter.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} sm_pairing_peripheral.c
|
||||
sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_OBJ} sm_pairing_peripheral.c
|
||||
${CC} $(filter-out sm_pairing_peripheral.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sm_pairing_central: ${CORE_OBJ} ${COMMON_OBJ} ${SM_REAL_OBJ} ad_parser.o sm_pairing_central.o
|
||||
sm_pairing_central: ${CORE_OBJ} ${COMMON_OBJ} ${SM_OBJ} ad_parser.o sm_pairing_central.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
le_streamer: le_streamer.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} le_streamer.c
|
||||
le_streamer: le_streamer.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_OBJ} le_streamer.c
|
||||
${CC} $(filter-out le_streamer.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
spp_and_le_counter: spp_and_le_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} spp_and_le_counter.c
|
||||
spp_and_le_counter: spp_and_le_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_OBJ} spp_and_le_counter.c
|
||||
${CC} $(filter-out spp_and_le_counter.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
spp_counter_ssp: ${CORE_OBJ} ${COMMON_OBJ} spp_counter_ssp.c
|
||||
spp_counter_ssp: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} spp_counter_ssp.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
spp_streamer: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} spp_streamer.c
|
||||
spp_streamer: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} spp_streamer.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
gap_dedicated_bonding: ${CORE_OBJ} ${COMMON_OBJ} gap_dedicated_bonding.c
|
||||
gap_dedicated_bonding: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} gap_dedicated_bonding.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
gap_inquiry: ${CORE_OBJ} ${COMMON_OBJ} ad_parser.o gap_inquiry.c
|
||||
gap_inquiry: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ad_parser.o gap_inquiry.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
panu_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} panu_demo.c
|
||||
panu_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} panu_demo.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
gatt_browser: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${SM_REAL_OBJ} gatt_browser.c
|
||||
gatt_browser: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${SM_OBJ} gatt_browser.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
gatt_battery_query: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${SM_REAL_OBJ} gatt_battery_query.c
|
||||
gatt_battery_query: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${SM_OBJ} gatt_battery_query.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
ancs_client_demo: ancs_client_demo.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${GATT_CLIENT_OBJ} ${SM_REAL_OBJ} ancs_client.c ancs_client_demo.c
|
||||
ancs_client_demo: ancs_client_demo.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${GATT_CLIENT_OBJ} ${SM_OBJ} ancs_client.c ancs_client_demo.c
|
||||
${CC} $(filter-out ancs_client_demo.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
led_counter: ${CORE_OBJ} ${COMMON_OBJ} led_counter.c
|
||||
@ -205,16 +209,16 @@ led_counter: ${CORE_OBJ} ${COMMON_OBJ} led_counter.c
|
||||
gap_le_advertisements: ${CORE_OBJ} ${COMMON_OBJ} ad_parser.c gap_le_advertisements.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
hsp_hs_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hsp_hs.o hsp_hs_demo.c
|
||||
hsp_hs_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hsp_hs.o hsp_hs_demo.c
|
||||
${CC} $^ ${CFLAGS} -I${BTSTACK_ROOT}/platform/posix ${LDFLAGS} -o $@
|
||||
|
||||
hsp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hsp_ag.o hsp_ag_demo.c
|
||||
hsp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hsp_ag.o hsp_ag_demo.c
|
||||
${CC} $^ ${CFLAGS} -I${BTSTACK_ROOT}/platform/posix ${LDFLAGS} -o $@
|
||||
|
||||
hfp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hfp.o hfp_gsm_model.o hfp_ag.o hfp_ag_demo.c
|
||||
hfp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hfp.o hfp_gsm_model.o hfp_ag.o hfp_ag_demo.c
|
||||
${CC} $^ ${CFLAGS} -I${BTSTACK_ROOT}/platform/posix ${LDFLAGS} -o $@
|
||||
|
||||
hfp_hf_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hfp.o hfp_hf.o hfp_hf_demo.c
|
||||
hfp_hf_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${CVSD_PLC_OBJ} wav_util.o sco_demo_util.o btstack_ring_buffer.o hfp.o hfp_hf.o hfp_hf_demo.c
|
||||
${CC} $^ ${CFLAGS} -I${BTSTACK_ROOT}/platform/posix ${LDFLAGS} -o $@
|
||||
|
||||
clean:
|
||||
|
@ -199,9 +199,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
const uint8_t * data = ad_iterator_get_data(&context);
|
||||
// Prefer Complete Local Name over Shortend Local Name
|
||||
switch (data_type){
|
||||
case 0x08: // Shortened Local Name
|
||||
case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
|
||||
if (devices[deviceCount].state == REMOTE_NAME_FETCHED) break;
|
||||
case 0x09: // Complete Local Name
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
|
||||
devices[deviceCount].state = REMOTE_NAME_FETCHED;
|
||||
memcpy(name_buffer, data, data_size);
|
||||
name_buffer[data_size] = 0;
|
||||
@ -215,7 +215,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
(unsigned int) devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
|
||||
devices[deviceCount].clockOffset);
|
||||
if (event >= HCI_EVENT_INQUIRY_RESULT_WITH_RSSI){
|
||||
printf(", rssi 0x%02x: ", devices[deviceCount].rssi);
|
||||
printf(", rssi 0x%02x", devices[deviceCount].rssi);
|
||||
}
|
||||
if (devices[deviceCount].state == REMOTE_NAME_FETCHED){
|
||||
printf(", name '%s'", name_buffer);
|
||||
|
@ -144,7 +144,7 @@ static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
|
||||
// Assigned Numbers GAP
|
||||
|
||||
switch (data_type){
|
||||
case 0x01: // Flags
|
||||
case BLUETOOTH_DATA_TYPE_FLAGS:
|
||||
// show only first octet, ignore rest
|
||||
for (i=0; i<8;i++){
|
||||
if (data[0] & (1<<i)){
|
||||
@ -153,64 +153,65 @@ static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
|
||||
|
||||
}
|
||||
break;
|
||||
case 0x02: // Incomplete List of 16-bit Service Class UUIDs
|
||||
case 0x03: // Complete List of 16-bit Service Class UUIDs
|
||||
case 0x14: // List of 16-bit Service Solicitation UUIDs
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
|
||||
for (i=0; i<size;i+=2){
|
||||
printf("%02X ", little_endian_read_16(data, i));
|
||||
}
|
||||
break;
|
||||
case 0x04: // Incomplete List of 32-bit Service Class UUIDs
|
||||
case 0x05: // Complete List of 32-bit Service Class UUIDs
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
|
||||
for (i=0; i<size;i+=4){
|
||||
printf("%04"PRIX32, little_endian_read_32(data, i));
|
||||
}
|
||||
break;
|
||||
case 0x06: // Incomplete List of 128-bit Service Class UUIDs
|
||||
case 0x07: // Complete List of 128-bit Service Class UUIDs
|
||||
case 0x15: // List of 128-bit Service Solicitation UUIDs
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
|
||||
reverse_128(data, uuid_128);
|
||||
printf("%s", uuid128_to_str(uuid_128));
|
||||
break;
|
||||
case 0x08: // Shortened Local Name
|
||||
case 0x09: // Complete Local Name
|
||||
case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
|
||||
for (i=0; i<size;i++){
|
||||
printf("%c", (char)(data[i]));
|
||||
}
|
||||
break;
|
||||
case 0x0A: // Tx Power Level
|
||||
case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
|
||||
printf("%d dBm", *(int8_t*)data);
|
||||
break;
|
||||
case 0x12: // Slave Connection Interval Range
|
||||
case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
|
||||
printf("Connection Interval Min = %u ms, Max = %u ms", little_endian_read_16(data, 0) * 5/4, little_endian_read_16(data, 2) * 5/4);
|
||||
break;
|
||||
case 0x16: // Service Data
|
||||
case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
|
||||
printf_hexdump(data, size);
|
||||
break;
|
||||
case 0x17: // Public Target Address
|
||||
case 0x18: // Random Target Address
|
||||
case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
|
||||
case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
|
||||
reverse_bd_addr(data, address);
|
||||
printf("%s", bd_addr_to_str(address));
|
||||
break;
|
||||
case 0x19: // Appearance
|
||||
case BLUETOOTH_DATA_TYPE_APPEARANCE:
|
||||
// https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
|
||||
printf("%02X", little_endian_read_16(data, 0) );
|
||||
break;
|
||||
case 0x1A: // Advertising Interval
|
||||
case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
|
||||
printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
|
||||
break;
|
||||
case 0x3D: // 3D Information Data
|
||||
case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
|
||||
printf_hexdump(data, size);
|
||||
break;
|
||||
case 0xFF: // Manufacturer Specific Data
|
||||
case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // Manufacturer Specific Data
|
||||
break;
|
||||
case 0x0D: // Class of Device (3B)
|
||||
case 0x0E: // Simple Pairing Hash C (16B)
|
||||
case 0x0F: // Simple Pairing Randomizer R (16B)
|
||||
case 0x10: // Device ID
|
||||
case 0x11: // Security Manager TK Value (16B)
|
||||
case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
|
||||
case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
|
||||
case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
|
||||
case BLUETOOTH_DATA_TYPE_DEVICE_ID:
|
||||
case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
|
||||
default:
|
||||
printf("Unknown Advertising Data Type");
|
||||
printf("Advertising Data Type 0x%2x not handled yet", data_type);
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -71,7 +71,7 @@ const char hfp_ag_service_name[] = "BTstack HFP AG Test";
|
||||
// static bd_addr_t device_addr = {0x00, 0x07, 0xB0, 0x83, 0x02, 0x5E};
|
||||
// CC256x
|
||||
// bd_addr_t device_addr = { 0xD0, 0x39, 0x72, 0xCD, 0x83, 0x45};
|
||||
// Minijamox
|
||||
// Mini Jambox
|
||||
bd_addr_t device_addr = { 0x00, 0x15, 0x83, 0x5F, 0x9D, 0x46};
|
||||
|
||||
// static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC};
|
||||
@ -129,18 +129,26 @@ enum STATE state = INIT;
|
||||
|
||||
static void dump_supported_codecs(void){
|
||||
int i;
|
||||
printf("Supported codecs: ");
|
||||
int mSBC_skipped = 0;
|
||||
printf("Supported codecs:");
|
||||
for (i = 0; i < sizeof(codecs); i++){
|
||||
switch(codecs[i]){
|
||||
case HFP_CODEC_CVSD:
|
||||
printf(" CVSD");
|
||||
break;
|
||||
case HFP_CODEC_MSBC:
|
||||
printf(" mSBC");
|
||||
if (hci_extended_sco_link_supported()){
|
||||
printf("mSBC");
|
||||
} else {
|
||||
mSBC_skipped = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
if (mSBC_skipped){
|
||||
printf("mSBC codec disabled because eSCO not supported by local controller.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int getDeviceIndexForAddress( bd_addr_t addr){
|
||||
@ -290,61 +298,30 @@ static void show_usage(void){
|
||||
gap_local_bd_addr(iut_address);
|
||||
|
||||
printf("\n--- Bluetooth HFP Audiogateway (AG) unit Test Console %s ---\n", bd_addr_to_str(iut_address));
|
||||
printf("---\n");
|
||||
printf("\n");
|
||||
|
||||
printf("a - establish HFP connection to PTS module %s\n", bd_addr_to_str(device_addr));
|
||||
// printf("A - release HFP connection to PTS module\n");
|
||||
|
||||
printf("b - establish AUDIO connection\n");
|
||||
printf("B - release AUDIO connection\n");
|
||||
|
||||
printf("c - simulate incoming call from 1234567\n");
|
||||
printf("C - simulate call from 1234567 dropped\n");
|
||||
|
||||
printf("b - establish AUDIO connection | B - release AUDIO connection\n");
|
||||
printf("c - simulate incoming call from 1234567 | C - simulate call from 1234567 dropped\n");
|
||||
printf("d - report AG failure\n");
|
||||
|
||||
printf("e - answer call on AG\n");
|
||||
printf("E - reject call on AG\n");
|
||||
|
||||
printf("r - disable in-band ring tone\n");
|
||||
printf("R - enable in-band ring tone\n");
|
||||
|
||||
printf("f - Disable cellular network\n");
|
||||
printf("F - Enable cellular network\n");
|
||||
|
||||
printf("g - Set signal strength to 0\n");
|
||||
printf("G - Set signal strength to 5\n");
|
||||
|
||||
printf("h - Disable roaming\n");
|
||||
printf("H - Enable roaming\n");
|
||||
|
||||
printf("i - Set battery level to 3\n");
|
||||
printf("I - Set battery level to 5\n");
|
||||
|
||||
printf("e - answer call on AG | E - reject call on AG\n");
|
||||
printf("r - disable in-band ring tone | R - enable in-band ring tone\n");
|
||||
printf("f - Disable cellular network | F - Enable cellular network\n");
|
||||
printf("g - Set signal strength to 0 | G - Set signal strength to 5\n");
|
||||
printf("h - Disable roaming | H - Enable roaming\n");
|
||||
printf("i - Set battery level to 3 | I - Set battery level to 5\n");
|
||||
printf("j - Answering call on remote side\n");
|
||||
|
||||
printf("k - Clear memory #1\n");
|
||||
printf("K - Set memory #1\n");
|
||||
|
||||
printf("l - Clear last number\n");
|
||||
printf("L - Set last number\n");
|
||||
|
||||
printf("k - Clear memory #1 | K - Set memory #1\n");
|
||||
printf("l - Clear last number | L - Set last number\n");
|
||||
printf("m - simulate incoming call from 7654321\n");
|
||||
// printf("M - simulate call from 7654321 dropped\n");
|
||||
|
||||
printf("n - Disable Voice Regocnition\n");
|
||||
printf("N - Enable Voice Recognition\n");
|
||||
|
||||
printf("o - Set speaker volume to 0 (minimum)\n");
|
||||
printf("O - Set speaker volume to 9 (default)\n");
|
||||
printf("p - Set speaker volume to 12 (higher)\n");
|
||||
printf("P - Set speaker volume to 15 (maximum)\n");
|
||||
|
||||
printf("q - Set microphone gain to 0 (minimum)\n");
|
||||
printf("Q - Set microphone gain to 9 (default)\n");
|
||||
printf("s - Set microphone gain to 12 (higher)\n");
|
||||
printf("S - Set microphone gain to 15 (maximum)\n");
|
||||
|
||||
printf("n - Disable Voice Regocnition | N - Enable Voice Recognition\n");
|
||||
printf("o - Set speaker volume to 0 (minimum) | O - Set speaker volume to 9 (default)\n");
|
||||
printf("p - Set speaker volume to 12 (higher) | P - Set speaker volume to 15 (maximum)\n");
|
||||
printf("q - Set microphone gain to 0 (minimum) | Q - Set microphone gain to 9 (default)\n");
|
||||
printf("s - Set microphone gain to 12 (higher) | S - Set microphone gain to 15 (maximum)\n");
|
||||
printf("t - terminate connection\n");
|
||||
printf("u - join held call\n");
|
||||
printf("v - discover nearby HF units\n");
|
||||
@ -592,11 +569,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(event, hci_read_local_supported_features)){
|
||||
if (hci_extended_sco_link_supported()){
|
||||
printf("Supported Codecs: CVSD, mSBC.\n");
|
||||
} else {
|
||||
printf("Supported Codecs: CVSD. mSBC disabled, eSCO not supported by controller).\n");
|
||||
}
|
||||
dump_supported_codecs();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -618,14 +591,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
acl_handle = hfp_subevent_service_level_connection_established_get_con_handle(event);
|
||||
hfp_subevent_service_level_connection_established_get_bd_addr(event, device_addr);
|
||||
printf("Service level connection established from %s.\n", bd_addr_to_str(device_addr));
|
||||
|
||||
dump_supported_codecs();
|
||||
if (hci_extended_sco_link_supported()){
|
||||
printf("eSCO supported by controller.\n");
|
||||
} else {
|
||||
printf("eSCO not supported by controller.\n");
|
||||
}
|
||||
|
||||
break;
|
||||
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
|
||||
printf("Service level connection released.\n");
|
||||
@ -639,7 +605,17 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
sco_handle = hfp_subevent_audio_connection_established_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
negotiated_codec = hfp_subevent_audio_connection_established_get_negotiated_codec(event);
|
||||
printf("Using codec 0x%02x.\n", negotiated_codec);
|
||||
switch (negotiated_codec){
|
||||
case 0x01:
|
||||
printf("Using CVSD codec.\n");
|
||||
break;
|
||||
case 0x02:
|
||||
printf("Using mSBC codec.\n");
|
||||
break;
|
||||
default:
|
||||
printf("Using unknown codec 0x%02x.\n", negotiated_codec);
|
||||
break;
|
||||
}
|
||||
sco_demo_set_codec(negotiated_codec);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
|
@ -56,21 +56,21 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack.h"
|
||||
|
||||
#include "sco_demo_util.h"
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
#include <unistd.h>
|
||||
#include "stdin_support.h"
|
||||
#endif
|
||||
|
||||
uint8_t hfp_service_buffer[150];
|
||||
const uint8_t rfcomm_channel_nr = 1;
|
||||
const char hfp_hf_service_name[] = "BTstack HFP HF Demo";
|
||||
static bd_addr_t device_addr = {0x80,0xbe,0x05,0xd5,0x28,0x48};
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
static bd_addr_t device_addr = {0x80,0xbe,0x05,0xd5,0x28,0x48};
|
||||
// 80:BE:05:D5:28:48
|
||||
// prototypes
|
||||
static void show_usage(void);
|
||||
@ -83,6 +83,29 @@ static uint8_t negotiated_codec = HFP_CODEC_CVSD;
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
char cmd;
|
||||
|
||||
static void dump_supported_codecs(void){
|
||||
int i;
|
||||
int mSBC_skipped = 0;
|
||||
printf("Supported codecs:");
|
||||
for (i = 0; i < sizeof(codecs); i++){
|
||||
switch(codecs[i]){
|
||||
case HFP_CODEC_CVSD:
|
||||
printf(" CVSD");
|
||||
break;
|
||||
case HFP_CODEC_MSBC:
|
||||
if (hci_extended_sco_link_supported()){
|
||||
printf("mSBC");
|
||||
} else {
|
||||
mSBC_skipped = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
if (mSBC_skipped){
|
||||
printf("mSBC codec disabled because eSCO not supported by local controller.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
|
||||
@ -92,82 +115,37 @@ static void show_usage(void){
|
||||
gap_local_bd_addr(iut_address);
|
||||
|
||||
printf("\n--- Bluetooth HFP Hands-Free (HF) unit Test Console %s ---\n", bd_addr_to_str(iut_address));
|
||||
printf("---\n");
|
||||
|
||||
printf("a - establish SLC connection to device %s\n", bd_addr_to_str(device_addr));
|
||||
printf("\n");
|
||||
printf("a - establish SLC to %s | ", bd_addr_to_str(device_addr));
|
||||
printf("A - release SLC connection to device\n");
|
||||
|
||||
printf("b - establish Audio connection\n");
|
||||
printf("B - release Audio connection\n");
|
||||
|
||||
printf("c - disable registration status update for all AG indicators\n");
|
||||
printf("C - enable registration status update for all AG indicators\n");
|
||||
|
||||
printf("d - query network operator.\n");
|
||||
printf("D - set HFP AG registration status update for individual indicators (IIA)\n");
|
||||
|
||||
printf("e - disable reporting of the extended AG error result code\n");
|
||||
printf("E - enable reporting of the extended AG error result code\n");
|
||||
|
||||
printf("f - answer incoming call\n");
|
||||
printf("F - Hangup call\n");
|
||||
|
||||
printf("g - query network operator name\n");
|
||||
printf("G - reject incoming call\n");
|
||||
|
||||
printf("i - dial 1234567\n");
|
||||
printf("I - dial 7654321\n");
|
||||
|
||||
printf("j - dial #1\n");
|
||||
printf("J - dial #99\n");
|
||||
|
||||
printf("k - deactivate call waiting notification\n");
|
||||
printf("K - activate call waiting notification\n");
|
||||
|
||||
printf("l - deactivate calling line notification\n");
|
||||
printf("L - activate calling line notification\n");
|
||||
|
||||
printf("m - deactivate echo canceling and noise reduction\n");
|
||||
printf("M - activate echo canceling and noise reduction\n");
|
||||
|
||||
printf("n - deactivate voice recognition\n");
|
||||
printf("N - activate voice recognition\n");
|
||||
|
||||
printf("o - Set speaker volume to 0 (minimum)\n");
|
||||
printf("O - Set speaker volume to 9 (default)\n");
|
||||
printf("p - Set speaker volume to 12 (higher)\n");
|
||||
printf("P - Set speaker volume to 15 (maximum)\n");
|
||||
|
||||
printf("q - Set microphone gain to 0 (minimum)\n");
|
||||
printf("Q - Set microphone gain to 9 (default)\n");
|
||||
printf("s - Set microphone gain to 12 (higher)\n");
|
||||
printf("S - Set microphone gain to 15 (maximum)\n");
|
||||
|
||||
printf("b - establish Audio connection | B - release Audio connection\n");
|
||||
printf("d - query network operator | D - Enable HFP AG registration status update via bitmap(IIA)\n");
|
||||
printf("f - answer incoming call | F - Hangup call\n");
|
||||
printf("g - query network operator name | G - reject incoming call\n");
|
||||
printf("i - dial 1234567 | I - dial 7654321\n");
|
||||
printf("j - dial #1 | J - dial #99\n");
|
||||
printf("o - Set speaker volume to 0 (minimum) | O - Set speaker volume to 9 (default)\n");
|
||||
printf("p - Set speaker volume to 12 (higher) | P - Set speaker volume to 15 (maximum)\n");
|
||||
printf("q - Set microphone gain to 0 (minimum) | Q - Set microphone gain to 9 (default)\n");
|
||||
printf("s - Set microphone gain to 12 (higher) | S - Set microphone gain to 15 (maximum)\n");
|
||||
printf("t - terminate connection\n");
|
||||
|
||||
printf("u - send 'user busy' (TWC 0)\n");
|
||||
printf("U - end active call and accept other call' (TWC 1)\n");
|
||||
printf("v - Swap active call and hold/waiting call (TWC 2)\n");
|
||||
printf("V - Join held call (TWC 3)\n");
|
||||
printf("w - Connect calls (TWC 4)\n");
|
||||
printf("W - redial\n");
|
||||
|
||||
printf("v - Swap active call call (TWC 2) | V - Join held call (TWC 3)\n");
|
||||
printf("w - Connect calls (TWC 4) | W - redial\n");
|
||||
printf("c/C - disable/enable registration status update for all AG indicators\n");
|
||||
printf("e/E - disable/enable reporting of the extended AG error result code\n");
|
||||
printf("k/K - deactivate/activate call waiting notification\n");
|
||||
printf("l/L - deactivate/activate calling line notification\n");
|
||||
printf("m/M - deactivate/activate echo canceling and noise reduction\n");
|
||||
printf("n/N - deactivate/activate voice recognition\n");
|
||||
printf("0123456789#*-+ - send DTMF dial tones\n");
|
||||
|
||||
printf("x - request phone number for voice tag\n");
|
||||
printf("X - current call status (ECS)\n");
|
||||
printf("y - release call with index 2 (ECC)\n");
|
||||
printf("Y - private consulation with call 2(ECC)\n");
|
||||
|
||||
printf("[ - Query Response and Hold status (RHH ?)\n");
|
||||
printf("] - Place call in a response and held state(RHH 0)\n");
|
||||
printf("{ - Accept held call(RHH 1)\n");
|
||||
printf("} - Reject held call(RHH 2)\n");
|
||||
|
||||
printf("x - request phone number for voice tag | X - current call status (ECS)\n");
|
||||
printf("y - release call with index 2 (ECC) | Y - private consulation with call 2(ECC)\n");
|
||||
printf("[ - Query Response and Hold status (RHH ?) | ] - Place call in a response and held state(RHH 0)\n");
|
||||
printf("{ - Accept held call(RHH 1) | } - Reject held call(RHH 2)\n");
|
||||
printf("? - Query Subscriber Number (NUM)\n");
|
||||
|
||||
printf("! - Update HF indicator with assigned number 1 (HFI)\n");
|
||||
|
||||
printf("---\n");
|
||||
printf("Ctrl-c - exit\n");
|
||||
printf("---\n");
|
||||
@ -467,17 +445,18 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
sco_demo_send(sco_handle);
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(event, hci_read_local_supported_features)){
|
||||
dump_supported_codecs();
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_HFP_META:
|
||||
switch (event[2]) {
|
||||
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
|
||||
acl_handle = hfp_subevent_service_level_connection_established_get_con_handle(event);
|
||||
hfp_subevent_service_level_connection_established_get_bd_addr(event, device_addr);
|
||||
printf("Service level connection established %s.\n\n", bd_addr_to_str(device_addr));
|
||||
if (hci_extended_sco_link_supported()){
|
||||
printf("Supported Codecs: CVSD, mSBC.\n");
|
||||
} else {
|
||||
printf("Supported Codecs: CVSD. mSBC disabled, eSCO not supported by controller).\n");
|
||||
}
|
||||
break;
|
||||
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
|
||||
printf("Service level connection released.\n\n");
|
||||
@ -490,7 +469,17 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
sco_handle = hfp_subevent_audio_connection_established_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
negotiated_codec = hfp_subevent_audio_connection_established_get_negotiated_codec(event);
|
||||
printf("Using codec 0x%02x.\n", negotiated_codec);
|
||||
switch (negotiated_codec){
|
||||
case 0x01:
|
||||
printf("Using CVSD codec.\n");
|
||||
break;
|
||||
case 0x02:
|
||||
printf("Using mSBC codec.\n");
|
||||
break;
|
||||
default:
|
||||
printf("Using unknown codec 0x%02x.\n", negotiated_codec);
|
||||
break;
|
||||
}
|
||||
sco_demo_set_codec(negotiated_codec);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
|
@ -52,6 +52,7 @@
|
||||
|
||||
#include "le_counter.h"
|
||||
#include "btstack.h"
|
||||
#include "ble/gatt-service/battery_service_server.h"
|
||||
|
||||
#define HEARTBEAT_PERIOD_MS 1000
|
||||
|
||||
@ -59,7 +60,9 @@
|
||||
*
|
||||
* @text Listing MainConfiguration shows main application code.
|
||||
* It initializes L2CAP, the Security Manager and configures the ATT Server with the pre-compiled
|
||||
* ATT Database generated from $le_counter.gatt$. Finally, it configures the advertisements
|
||||
* ATT Database generated from $le_counter.gatt$.
|
||||
* Additionally, it enables the Battery Service Server with the current battery level.
|
||||
* Finally, it configures the advertisements
|
||||
* and the heartbeat handler and boots the Bluetooth stack.
|
||||
* In this example, the Advertisement contains the Flags attribute and the device name.
|
||||
* The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not supported.
|
||||
@ -70,6 +73,7 @@ static int le_notification_enabled;
|
||||
static btstack_timer_source_t heartbeat;
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static hci_con_handle_t con_handle;
|
||||
static uint8_t battery = 100;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);
|
||||
@ -103,6 +107,9 @@ static void le_counter_setup(void){
|
||||
att_server_init(profile_data, att_read_callback, att_write_callback);
|
||||
att_server_register_packet_handler(packet_handler);
|
||||
|
||||
// setup battery service
|
||||
battery_service_server_init(battery);
|
||||
|
||||
// setup advertisements
|
||||
uint16_t adv_int_min = 0x0030;
|
||||
uint16_t adv_int_max = 0x0030;
|
||||
@ -146,6 +153,14 @@ static void heartbeat_handler(struct btstack_timer_source *ts){
|
||||
beat();
|
||||
att_server_request_can_send_now_event(con_handle);
|
||||
}
|
||||
|
||||
// simulate battery drain
|
||||
battery--;
|
||||
if (battery < 50) {
|
||||
battery = 100;
|
||||
}
|
||||
battery_service_server_set_battery_value(battery);
|
||||
|
||||
btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
|
||||
btstack_run_loop_add_timer(ts);
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
PRIMARY_SERVICE, GAP_SERVICE
|
||||
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SPP+LE Counter"
|
||||
|
||||
PRIMARY_SERVICE, GATT_SERVICE
|
||||
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
|
||||
|
||||
// Counter Service
|
||||
PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
|
||||
// Counter Characteristic, with read and notify
|
||||
CHARACTERISTIC, 0000FF11-0000-1000-8000-00805F9B34FB, READ | NOTIFY | DYNAMIC,
|
||||
|
||||
|
||||
PRIMARY_SERVICE, GAP_SERVICE
|
||||
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SPP+LE Counter"
|
||||
|
||||
// add Battery Service
|
||||
#import <battery_service.gatt>
|
||||
|
||||
PRIMARY_SERVICE, GATT_SERVICE
|
||||
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
|
||||
|
||||
// Counter Service
|
||||
PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
|
||||
// Counter Characteristic, with read and notify
|
||||
CHARACTERISTIC, 0000FF11-0000-1000-8000-00805F9B34FB, READ | NOTIFY | DYNAMIC,
|
||||
|
@ -44,12 +44,14 @@
|
||||
|
||||
#include "sco_demo_util.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_sbc.h"
|
||||
#include "btstack_cvsd_plc.h"
|
||||
#include "hfp_msbc.h"
|
||||
#include "hfp.h"
|
||||
#include "classic/btstack_sbc.h"
|
||||
#include "classic/btstack_cvsd_plc.h"
|
||||
#include "classic/hfp_msbc.h"
|
||||
#include "classic/hfp.h"
|
||||
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
#include "wav_util.h"
|
||||
#endif
|
||||
|
||||
// configure test mode
|
||||
#define SCO_DEMO_MODE_SINE 0
|
||||
@ -115,6 +117,58 @@ FILE * msbc_file_out;
|
||||
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
|
||||
|
||||
// input signal: pre-computed sine wave, at 8000 kz
|
||||
static const uint8_t sine_uint8[] = {
|
||||
0, 15, 31, 46, 61, 74, 86, 97, 107, 114,
|
||||
120, 124, 126, 126, 124, 120, 114, 107, 97, 86,
|
||||
74, 61, 46, 31, 15, 0, 241, 225, 210, 195,
|
||||
182, 170, 159, 149, 142, 136, 132, 130, 130, 132,
|
||||
136, 142, 149, 159, 170, 182, 195, 210, 225, 241,
|
||||
};
|
||||
|
||||
|
||||
// input signal: pre-computed sine wave, 160 Hz at 16000 kHz
|
||||
static const int16_t sine_int16[] = {
|
||||
0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557,
|
||||
19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466,
|
||||
31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738,
|
||||
31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886,
|
||||
19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057,
|
||||
0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557,
|
||||
-19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466,
|
||||
-31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738,
|
||||
-31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886,
|
||||
-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
|
||||
};
|
||||
|
||||
static int phase = 0;
|
||||
static void sco_demo_sine_wave_int8(int num_samples, int8_t * data){
|
||||
int i;
|
||||
for (i=0; i<num_samples; i++){
|
||||
data[i] = (int8_t)sine_uint8[phase];
|
||||
phase++;
|
||||
if (phase >= sizeof(sine_uint8)) phase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sco_demo_sine_wave_int16(int num_samples, int16_t * data){
|
||||
int i;
|
||||
for (i=0; i < num_samples; i++){
|
||||
data[i] = sine_int16[phase++];
|
||||
if (phase >= (sizeof(sine_int16) / sizeof(int16_t))){
|
||||
phase = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sco_demo_fill_audio_frame(void){
|
||||
if (!hfp_msbc_can_encode_audio_frame_now()) return;
|
||||
int num_samples = hfp_msbc_num_audio_samples_per_frame();
|
||||
int16_t sample_buffer[num_samples];
|
||||
sco_demo_sine_wave_int16(num_samples, sample_buffer);
|
||||
hfp_msbc_encode_audio_frame(sample_buffer);
|
||||
num_audio_frames++;
|
||||
}
|
||||
|
||||
#ifdef SCO_WAV_FILENAME
|
||||
static btstack_sbc_decoder_state_t decoder_state;
|
||||
@ -178,15 +232,6 @@ static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, i
|
||||
}
|
||||
}
|
||||
|
||||
static void sco_demo_fill_audio_frame(void){
|
||||
if (!hfp_msbc_can_encode_audio_frame_now()) return;
|
||||
int num_samples = hfp_msbc_num_audio_samples_per_frame();
|
||||
int16_t sample_buffer[num_samples];
|
||||
wav_synthesize_sine_wave_int16(num_samples, sample_buffer);
|
||||
hfp_msbc_encode_audio_frame(sample_buffer);
|
||||
num_audio_frames++;
|
||||
}
|
||||
|
||||
static void sco_demo_init_mSBC(void){
|
||||
int sample_rate = 16000;
|
||||
wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate);
|
||||
@ -447,7 +492,7 @@ void sco_demo_send(hci_con_handle_t sco_handle){
|
||||
|
||||
sco_demo_fill_audio_frame();
|
||||
} else {
|
||||
wav_synthesize_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3));
|
||||
sco_demo_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3));
|
||||
}
|
||||
#else
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
|
||||
|
@ -54,7 +54,12 @@ extern "C" {
|
||||
*/
|
||||
void sco_demo_init(void);
|
||||
|
||||
void sco_demo_set_codec(uint8_t codec);
|
||||
/**
|
||||
* @brief Set codec (cvsd:0x01, msbc:0x02) and initalize wav writter and portaudio .
|
||||
* @param codec
|
||||
*/
|
||||
void sco_demo_set_codec(uint8_t codec);
|
||||
|
||||
/**
|
||||
* @brief Send next data on con_handle
|
||||
* @param con_handle
|
||||
@ -66,6 +71,9 @@ void sco_demo_send(hci_con_handle_t con_handle);
|
||||
*/
|
||||
void sco_demo_receive(uint8_t * packet, uint16_t size);
|
||||
|
||||
/**
|
||||
* @brief Close WAV writer, stop portaudio stream
|
||||
*/
|
||||
void sco_demo_close(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -147,6 +147,7 @@ static void sm_peripheral_setup(void){
|
||||
|
||||
/* LISTING_START(packetHandler): Packet Handler */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
bd_addr_t addr;
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
@ -161,6 +162,18 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
|
||||
printf("Display Passkey: %u\n", sm_event_passkey_display_number_get_passkey(packet));
|
||||
break;
|
||||
case SM_EVENT_IDENTITY_CREATED:
|
||||
sm_event_identity_created_get_identity_address(packet, addr);
|
||||
printf("Identity created: type %u address %s\n", sm_event_identity_created_get_identity_addr_type(packet), bd_addr_to_str(addr));
|
||||
break;
|
||||
case SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED:
|
||||
sm_event_identity_resolving_succeeded_get_identity_address(packet, addr);
|
||||
printf("Identity resolved: type %u address %s\n", sm_event_identity_resolving_succeeded_get_identity_addr_type(packet), bd_addr_to_str(addr));
|
||||
break;
|
||||
case SM_EVENT_IDENTITY_RESOLVING_FAILED:
|
||||
sm_event_identity_created_get_address(packet, addr);
|
||||
printf("Identity resolving failed\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -880,8 +880,10 @@ void daemon_gatt_serialize_characteristic_descriptor(gatt_client_characteristic_
|
||||
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){
|
||||
|
||||
bd_addr_t addr;
|
||||
#ifdef ENABLE_BLE
|
||||
bd_addr_type_t addr_type;
|
||||
hci_con_handle_t handle;
|
||||
#endif
|
||||
uint16_t cid;
|
||||
uint16_t psm;
|
||||
uint16_t service_channel;
|
||||
@ -1132,6 +1134,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
|
||||
sdp_client_query(&handle_sdp_client_query_result, addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]);
|
||||
break;
|
||||
#ifdef ENABLE_BLE
|
||||
case GAP_LE_SCAN_START:
|
||||
gap_start_scan();
|
||||
break;
|
||||
@ -1153,6 +1156,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
gap_disconnect(handle);
|
||||
break;
|
||||
#endif
|
||||
#if defined(HAVE_MALLOC) && defined(ENABLE_BLE)
|
||||
case GATT_DISCOVER_ALL_PRIMARY_SERVICES:
|
||||
gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
|
||||
@ -1967,14 +1971,19 @@ int main (int argc, char * const * argv){
|
||||
|
||||
btstack_control_t * control = NULL;
|
||||
void * config;
|
||||
|
||||
const btstack_uart_block_t * uart_block_implementation = NULL;
|
||||
(void) uart_block_implementation;
|
||||
|
||||
#ifdef HAVE_TRANSPORT_H4
|
||||
hci_transport_config_uart.type = HCI_TRANSPORT_CONFIG_UART;
|
||||
hci_transport_config_uart.baudrate_init = UART_SPEED;
|
||||
hci_transport_config_uart.baudrate_main = 0;
|
||||
hci_transport_config_uart.flowcontrol = 1;
|
||||
hci_transport_config_uart.device_name = UART_DEVICE;
|
||||
transport = hci_transport_h4_instance(btstack_uart_block_posix_instance());
|
||||
|
||||
#ifndef HAVE_PLATFORM_IPHONE_OS
|
||||
uart_block_implementation = btstack_uart_block_posix_instance();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PLATFORM_IPHONE_OS
|
||||
// use default (max) UART baudrate over netgraph interface
|
||||
@ -1982,6 +1991,7 @@ int main (int argc, char * const * argv){
|
||||
#endif
|
||||
|
||||
config = &hci_transport_config_uart;
|
||||
transport = hci_transport_h4_instance(uart_block_implementation);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TRANSPORT_USB
|
||||
|
@ -107,6 +107,13 @@ static int btstack_uart_embedded_open(void){
|
||||
}
|
||||
|
||||
static int btstack_uart_embedded_close(void){
|
||||
|
||||
// remove data source
|
||||
btstack_run_loop_disable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_POLL);
|
||||
btstack_run_loop_remove_data_source(&transport_data_source);
|
||||
|
||||
// close device
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,9 +210,10 @@ static int h4_set_baudrate(uint32_t baudrate){
|
||||
}
|
||||
|
||||
static int h4_close(void){
|
||||
// first remove run loop handler
|
||||
btstack_run_loop_remove_data_source(&hci_transport_h4_dma_ds);
|
||||
|
||||
// remove data source
|
||||
btstack_run_loop_disable_data_source_callbacks(&hci_transport_h4_dma_ds, DATA_SOURCE_CALLBACK_POLL);
|
||||
btstack_run_loop_remove_data_source(&hci_transport_h4_dma_ds);
|
||||
|
||||
// stop IRQ
|
||||
hal_uart_dma_set_csr_irq_handler(NULL);
|
||||
|
||||
|
@ -157,7 +157,9 @@ static int h4_open(void){
|
||||
}
|
||||
|
||||
static int h4_close(void){
|
||||
// first remove run loop handler
|
||||
|
||||
// remove data source
|
||||
btstack_run_loop_disable_data_source_callbacks(&hci_transport_h4_dma_ds, DATA_SOURCE_CALLBACK_POLL);
|
||||
btstack_run_loop_remove_data_source(&hci_transport_h4_dma_ds);
|
||||
|
||||
// close device
|
||||
|
@ -49,6 +49,12 @@
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef __APPLE__
|
||||
#include <sys/ioctl.h>
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#endif
|
||||
|
||||
// uart config
|
||||
static const btstack_uart_config_t * uart_config;
|
||||
@ -151,16 +157,32 @@ static void hci_transport_h5_process(btstack_data_source_t *ds, btstack_data_sou
|
||||
}
|
||||
}
|
||||
|
||||
static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
||||
static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
||||
|
||||
int fd = transport_data_source.fd;
|
||||
|
||||
log_info("h4_set_baudrate %u", baudrate);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
// From https://developer.apple.com/library/content/samplecode/SerialPortSample/Listings/SerialPortSample_SerialPortSample_c.html
|
||||
|
||||
// The IOSSIOSPEED ioctl can be used to set arbitrary baud rates
|
||||
// other than those specified by POSIX. The driver for the underlying serial hardware
|
||||
// ultimately determines which baud rates can be used. This ioctl sets both the input
|
||||
// and output speed.
|
||||
|
||||
speed_t speed = baudrate;
|
||||
if (ioctl(fd, IOSSIOSPEED, &speed) == -1) {
|
||||
log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
struct termios toptions;
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
perror("posix_open: Couldn't get term attributes");
|
||||
log_error("btstack_uart_posix_set_baudrate: Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -205,9 +227,10 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
||||
cfsetispeed(&toptions, brate);
|
||||
|
||||
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
||||
perror("posix_set_baudrate: Couldn't set term attributes");
|
||||
log_error("btstack_uart_posix_set_baudrate: Couldn't set term attributes");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -222,13 +245,12 @@ static int btstack_uart_posix_open(void){
|
||||
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
|
||||
int fd = open(device_name, flags);
|
||||
if (fd == -1) {
|
||||
perror("posix_open: Unable to open port ");
|
||||
perror(device_name);
|
||||
log_error("posix_open: Unable to open port %s", device_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
perror("posix_open: Couldn't get term attributes");
|
||||
log_error("posix_open: Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -258,7 +280,7 @@ static int btstack_uart_posix_open(void){
|
||||
toptions.c_cc[VTIME] = 0;
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
||||
perror("posix_open: Couldn't set term attributes");
|
||||
log_error("posix_open: Couldn't set term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -303,7 +325,7 @@ static int btstack_uart_posix_set_parity(int parity){
|
||||
|
||||
struct termios toptions;
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
perror("posix_set_parity: Couldn't get term attributes");
|
||||
log_error("btstack_uart_posix_set_parity: Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
if (parity){
|
||||
@ -312,7 +334,7 @@ static int btstack_uart_posix_set_parity(int parity){
|
||||
toptions.c_cflag &= ~PARENB; // enable even parity
|
||||
}
|
||||
if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
||||
perror("posix_set_parity: Couldn't set term attributes");
|
||||
log_error("posix_set_parity: Couldn't set term attributes");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -45,31 +45,6 @@
|
||||
#include "wav_util.h"
|
||||
#include "btstack_util.h"
|
||||
|
||||
static const uint8_t sine_uint8[] = {
|
||||
0, 15, 31, 46, 61, 74, 86, 97, 107, 114,
|
||||
120, 124, 126, 126, 124, 120, 114, 107, 97, 86,
|
||||
74, 61, 46, 31, 15, 0, 241, 225, 210, 195,
|
||||
182, 170, 159, 149, 142, 136, 132, 130, 130, 132,
|
||||
136, 142, 149, 159, 170, 182, 195, 210, 225, 241,
|
||||
};
|
||||
|
||||
|
||||
// input signal: pre-computed sine wave, 160 Hz at 16000 kHz
|
||||
static const int16_t sine_int16[] = {
|
||||
0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557,
|
||||
19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466,
|
||||
31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738,
|
||||
31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886,
|
||||
19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057,
|
||||
0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557,
|
||||
-19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466,
|
||||
-31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738,
|
||||
-31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886,
|
||||
-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
|
||||
};
|
||||
|
||||
static int phase = 0;
|
||||
|
||||
static int wav_reader_fd;
|
||||
static int bytes_per_sample = 2;
|
||||
|
||||
@ -242,22 +217,4 @@ int wav_reader_read_int16(int num_samples, int16_t * data){
|
||||
return bytes_read == num_samples*bytes_per_sample;
|
||||
}
|
||||
|
||||
void wav_synthesize_sine_wave_int8(int num_samples, int8_t * data){
|
||||
int i;
|
||||
for (i=0; i<num_samples; i++){
|
||||
data[i] = (int8_t)sine_uint8[phase];
|
||||
phase++;
|
||||
if (phase >= sizeof(sine_uint8)) phase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wav_synthesize_sine_wave_int16(int num_samples, int16_t * data){
|
||||
int i;
|
||||
for (i=0; i < num_samples; i++){
|
||||
data[i] = sine_int16[phase++];
|
||||
if (phase >= (sizeof(sine_int16) / sizeof(int16_t))){
|
||||
phase = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,3 @@ int wav_reader_read_int8(int num_samples, int8_t * data);
|
||||
int wav_reader_read_int16(int num_samples, int16_t * data);
|
||||
int wav_reader_close(void);
|
||||
|
||||
//
|
||||
void wav_synthesize_sine_wave_int8(int num_samples, int8_t * data);
|
||||
void wav_synthesize_sine_wave_int16(int num_samples, int16_t * data);
|
||||
|
||||
|
@ -17,7 +17,7 @@ PORT_FILES = btstack_config.h bsp_arduino_em9301.cpp BTstack.cpp BTstack.h
|
||||
EMBEDDED_FILES = btstack_run_loop_embedded.c hci_transport_h4_embedded.c btstack_uart_block_embedded.c
|
||||
|
||||
PATHS = $(addprefix ${BTSTACK_ROOT}/src/, ${SRC_FILES})
|
||||
PATHS += $(wildcard ${BTSTACK_ROOT}/src/*.h)
|
||||
PATHS += $(filter-out ${BTSTACK_ROOT}/src/btstack.h, $(wildcard ${BTSTACK_ROOT}/src/*.h))
|
||||
PATHS += $(addprefix ${BTSTACK_ROOT}/src/ble/, ${BLE_FILES})
|
||||
PATHS += $(wildcard ${BTSTACK_ROOT}/src/ble/*.h)
|
||||
PATHS += $(addprefix ${BTSTACK_ROOT}/platform/embedded/, ${EMBEDDED_FILES})
|
||||
|
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@ THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode-4.4.1.app/Contents/Developer
|
||||
SDKVERSION_armv6 = 5.1
|
||||
TARGET_IPHONEOS_DEPLOYMENT_VERSION = 3.0
|
||||
TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0
|
||||
ARCHS = armv7 arm64
|
||||
ARCHS = armv6
|
||||
|
||||
TOOL_NAME = PatchBlueTool
|
||||
|
||||
|
@ -17,6 +17,7 @@ BTstack_CFLAGS = -g -I.. \
|
||||
-I$(BTSTACK_ROOT)/platform/corefoundation \
|
||||
|
||||
BTstack_LDFLAGS = -L../src/.theos/obj -lBTstack
|
||||
BTstack_LDFLAGS += -F../Frameworks
|
||||
BTstack_PRIVATE_FRAMEWORKS = Preferences
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
|
@ -8,7 +8,7 @@ TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0
|
||||
ARCHS = armv6 arm64
|
||||
|
||||
BTSTACK_ROOT=../../..
|
||||
VPATH += $(BTSTACK_ROOT)/platform/daemon/example
|
||||
# VPATH += $(BTSTACK_ROOT)/platform/daemon/example
|
||||
|
||||
ADDITIONAL_CFLAGS = -I.. \
|
||||
-I$(BTSTACK_ROOT)/src \
|
||||
@ -20,13 +20,13 @@ ADDITIONAL_LDFLAGS = -L../src/.theos/obj -lBTstack
|
||||
|
||||
TOOL_NAME = inquiry l2cap_test rfcomm_echo rfcomm_cat rfcomm_test l2cap_server l2cap_throughput
|
||||
|
||||
inquiry_FILES = inquiry.c
|
||||
rfcomm_echo_FILES = rfcomm_echo.c
|
||||
rfcomm_cat_FILES = rfcomm_cat.c
|
||||
rfcomm_test_FILES = rfcomm_test.c
|
||||
l2cap_test_FILES = test.c
|
||||
l2cap_server_FILES = l2cap_server.c
|
||||
l2cap_throughput_FILES = l2cap_throughput.c
|
||||
inquiry_FILES = $(BTSTACK_ROOT)/platform/daemon/example/inquiry.c
|
||||
rfcomm_echo_FILES = $(BTSTACK_ROOT)/platform/daemon/example/rfcomm_echo.c
|
||||
rfcomm_cat_FILES = $(BTSTACK_ROOT)/platform/daemon/example/rfcomm_cat.c
|
||||
rfcomm_test_FILES = $(BTSTACK_ROOT)/platform/daemon/example/rfcomm_test.c
|
||||
l2cap_test_FILES = $(BTSTACK_ROOT)/platform/daemon/example/test.c
|
||||
l2cap_server_FILES = $(BTSTACK_ROOT)/platform/daemon/example/l2cap_server.c
|
||||
l2cap_throughput_FILES = $(BTSTACK_ROOT)/platform/daemon/example/l2cap_throughput.c
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
include $(THEOS_MAKE_PATH)/tool.mk
|
||||
|
@ -8,51 +8,43 @@ ARCHS = armv6 arm64
|
||||
|
||||
BTSTACK_ROOT=../../..
|
||||
|
||||
VPATH += $(BTSTACK_ROOT)/src \
|
||||
$(BTSTACK_ROOT)/src/classic \
|
||||
$(BTSTACK_ROOT)/platform/posix \
|
||||
$(BTSTACK_ROOT)/platform/daemon/src \
|
||||
$(BTSTACK_ROOT)/platform/corefoundation \
|
||||
$(BTSTACK_ROOT)/port/ios/SpringBoardAccess
|
||||
|
||||
LIBRARY_NAME = libBTstack
|
||||
libBTstack_FILES = \
|
||||
btstack.c \
|
||||
btstack_linked_list.c \
|
||||
btstack_run_loop.c \
|
||||
btstack_run_loop_corefoundation.m \
|
||||
btstack_run_loop_posix.c \
|
||||
daemon_cmds.c \
|
||||
hci_cmd.c \
|
||||
hci_dump.c \
|
||||
sdp_util.c \
|
||||
spp_server.c \
|
||||
socket_connection.c \
|
||||
btstack_util.c \
|
||||
$(BTSTACK_ROOT)/src/btstack_linked_list.c \
|
||||
$(BTSTACK_ROOT)/src/btstack_run_loop.c \
|
||||
$(BTSTACK_ROOT)/src/hci_cmd.c \
|
||||
$(BTSTACK_ROOT)/src/hci_dump.c \
|
||||
$(BTSTACK_ROOT)/src/btstack_util.c \
|
||||
$(BTSTACK_ROOT)/platform/daemon/src/btstack.c \
|
||||
$(BTSTACK_ROOT)/platform/daemon/src/daemon_cmds.c \
|
||||
$(BTSTACK_ROOT)/platform/daemon/src/socket_connection.c \
|
||||
$(BTSTACK_ROOT)/platform/corefoundation/btstack_run_loop_corefoundation.m \
|
||||
$(BTSTACK_ROOT)/platform/posix/btstack_run_loop_posix.c \
|
||||
$(BTSTACK_ROOT)/src/classic/sdp_util.c \
|
||||
$(BTSTACK_ROOT)/src/classic/spp_server.c \
|
||||
|
||||
libBTstack_CFLAGS = -I$(BTSTACK_ROOT)/src/ble -I$(BTSTACK_ROOT)/src -I..
|
||||
|
||||
TOOL_NAME = BTdaemon
|
||||
BTdaemon_FILES = \
|
||||
$(libBTstack_FILES) \
|
||||
$(libBTstack_FILES) \
|
||||
$(BTSTACK_ROOT)/src/hci.c \
|
||||
$(BTSTACK_ROOT)/src/l2cap.c \
|
||||
$(BTSTACK_ROOT)/src/l2cap_signaling.c \
|
||||
$(BTSTACK_ROOT)/src/btstack_memory.c \
|
||||
$(BTSTACK_ROOT)/src/btstack_memory_pool.c \
|
||||
$(BTSTACK_ROOT)/src/classic/rfcomm.c \
|
||||
$(BTSTACK_ROOT)/src/classic/sdp_server.c \
|
||||
$(BTSTACK_ROOT)/src/classic/sdp_client.c \
|
||||
$(BTSTACK_ROOT)/src/classic/sdp_client_rfcomm.c \
|
||||
$(BTSTACK_ROOT)/platform/corefoundation/btstack_device_name_db_corefoundation.m \
|
||||
$(BTSTACK_ROOT)/platform/corefoundation/btstack_link_key_db_corefoundation.m \
|
||||
$(BTSTACK_ROOT)/platform/corefoundation/rfcomm_service_db_corefoundation.m \
|
||||
$(BTSTACK_ROOT)/platform/daemon/src/daemon.c \
|
||||
btstack_control_iphone.m \
|
||||
btstack_device_name_db_corefoundation.m \
|
||||
btstack_link_key_db_corefoundation.m \
|
||||
btstack_memory.c \
|
||||
btstack_memory_pool.c \
|
||||
daemon.c \
|
||||
hci.c \
|
||||
hci_transport_h4_iphone.c \
|
||||
btstack_uart_block_posix.c \
|
||||
l2cap.c \
|
||||
l2cap_signaling.c \
|
||||
platform_iphone.m \
|
||||
rfcomm.c \
|
||||
sdp_server.c \
|
||||
SpringBoardAccess.c \
|
||||
rfcomm_service_db_corefoundation.m \
|
||||
sdp_client.c \
|
||||
sdp_client_rfcomm.c \
|
||||
../SpringBoardAccess/SpringBoardAccess.c \
|
||||
|
||||
BTdaemon_CFLAGS = \
|
||||
-I$(BTSTACK_ROOT)/src \
|
||||
@ -62,6 +54,11 @@ BTdaemon_CFLAGS = \
|
||||
-I..
|
||||
BTdaemon_PRIVATE_FRAMEWORKS = IOKIT
|
||||
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
include $(THEOS_MAKE_PATH)/library.mk
|
||||
include $(THEOS_MAKE_PATH)/tool.mk
|
||||
|
||||
before-all::
|
||||
../../../tool/get_version.sh
|
||||
|
||||
@ -71,7 +68,3 @@ after-BTdaemon-stage::
|
||||
mkdir -p ../.theos/_/usr/local/bin
|
||||
ln -s /usr/lib/libBTstack.dylib ../.theos/_/usr/local/lib
|
||||
ln -s /usr/bin/BTdaemon ../.theos/_/usr/local/bin/BTdaemon
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
include $(THEOS_MAKE_PATH)/library.mk
|
||||
include $(THEOS_MAKE_PATH)/tool.mk
|
||||
|
@ -3,7 +3,7 @@ BTSTACK_ROOT = ../..
|
||||
|
||||
CORE += main.c stdin_support.c
|
||||
|
||||
COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c btstack_link_key_db_fs.c le_device_db_fs.c
|
||||
COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c le_device_db_fs.c btstack_link_key_db_fs.c
|
||||
|
||||
include ${BTSTACK_ROOT}/example/Makefile.inc
|
||||
|
||||
|
@ -136,8 +136,11 @@ int main(int argc, const char * argv[]){
|
||||
|
||||
// init HCI
|
||||
hci_init(hci_transport_usb_instance(), NULL);
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
hci_set_link_key_db(btstack_link_key_db_fs_instance());
|
||||
|
||||
#endif
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
5
port/nrf5-zephyr/Kconfig
Normal file
5
port/nrf5-zephyr/Kconfig
Normal file
@ -0,0 +1,5 @@
|
||||
menuconfig BTSTACK
|
||||
bool "BTstack support"
|
||||
default n
|
||||
help
|
||||
This option enables the BTstack Bluetooth stack.
|
5
port/nrf5-zephyr/Makefile
Normal file
5
port/nrf5-zephyr/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
KERNEL_TYPE = nano
|
||||
CONF_FILE ?= nrf5.conf
|
||||
BOARD ?= nrf52_pca10040
|
||||
|
||||
include ${ZEPHYR_BASE}/Makefile.inc
|
14
port/nrf5-zephyr/Makefile.ble
Normal file
14
port/nrf5-zephyr/Makefile.ble
Normal file
@ -0,0 +1,14 @@
|
||||
obj-y += \
|
||||
ancs_client.o \
|
||||
att_db.o \
|
||||
att_dispatch.o \
|
||||
att_server.o \
|
||||
gatt_client.o \
|
||||
le_device_db_memory.o \
|
||||
sm.o \
|
||||
sm_mbedtls_allocator.o \
|
||||
|
||||
# att_db_util.o \
|
||||
|
||||
obj-y += gatt-service/
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack
|
2
port/nrf5-zephyr/Makefile.bluedroid
Normal file
2
port/nrf5-zephyr/Makefile.bluedroid
Normal file
@ -0,0 +1,2 @@
|
||||
obj-y += encoder/srce/
|
||||
obj-y += decoder/srce/
|
17
port/nrf5-zephyr/Makefile.bluedroid-decoder
Normal file
17
port/nrf5-zephyr/Makefile.bluedroid-decoder
Normal file
@ -0,0 +1,17 @@
|
||||
obj-y += \
|
||||
alloc.o \
|
||||
bitalloc.o \
|
||||
bitalloc-sbc.o \
|
||||
bitstream-decode.o \
|
||||
decoder-oina.o \
|
||||
decoder-private.o \
|
||||
decoder-sbc.o \
|
||||
dequant.o \
|
||||
framing.o \
|
||||
framing-sbc.o \
|
||||
oi_codec_version.o \
|
||||
synthesis-sbc.o \
|
||||
synthesis-dct8.o \
|
||||
synthesis-8-generated.o \
|
||||
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack/bluedroid/decoder/include
|
11
port/nrf5-zephyr/Makefile.bluedroid-encoder
Normal file
11
port/nrf5-zephyr/Makefile.bluedroid-encoder
Normal file
@ -0,0 +1,11 @@
|
||||
obj-y += \
|
||||
sbc_analysis.o \
|
||||
sbc_dct.o \
|
||||
sbc_dct_coeffs.o \
|
||||
sbc_enc_bit_alloc_mono.o \
|
||||
sbc_enc_bit_alloc_ste.o \
|
||||
sbc_enc_coeffs.o \
|
||||
sbc_encoder.o \
|
||||
sbc_packing.o \
|
||||
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack/bluedroid/encoder/include
|
4
port/nrf5-zephyr/Makefile.gatt-service
Normal file
4
port/nrf5-zephyr/Makefile.gatt-service
Normal file
@ -0,0 +1,4 @@
|
||||
obj-y += \
|
||||
battery_service_server.o \
|
||||
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack
|
22
port/nrf5-zephyr/Makefile.src
Normal file
22
port/nrf5-zephyr/Makefile.src
Normal file
@ -0,0 +1,22 @@
|
||||
obj-y += \
|
||||
ad_parser.o \
|
||||
btstack_linked_list.o \
|
||||
btstack_memory.o \
|
||||
btstack_memory_pool.o \
|
||||
btstack_ring_buffer.o \
|
||||
btstack_run_loop.o \
|
||||
btstack_util.o \
|
||||
hci.o \
|
||||
hci_cmd.o \
|
||||
hci_dump.o \
|
||||
hci_transport_h4.o \
|
||||
l2cap.o \
|
||||
l2cap_signaling.o \
|
||||
btstack_run_loop_embedded.o \
|
||||
|
||||
obj-y += ble/
|
||||
# obj-y += classic/
|
||||
# obj-y += bluedroid/
|
||||
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack
|
||||
ccflags-y += -I${ZEPHYR_BASE}/ext/hal/nordic/mdk
|
34
port/nrf5-zephyr/btstack_config.h
Normal file
34
port/nrf5-zephyr/btstack_config.h
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// btstack_config.h for mRF5-Zephyr port
|
||||
//
|
||||
|
||||
#ifndef __BTSTACK_CONFIG
|
||||
#define __BTSTACK_CONFIG
|
||||
|
||||
// Port related features
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE 52
|
||||
#define MAX_NR_WHITELIST_ENTRIES 1
|
||||
#define MAX_NR_HCI_CONNECTIONS 1
|
||||
#define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||
#define MAX_NR_L2CAP_SERVICES 1
|
||||
#define MAX_NR_L2CAP_CHANNELS 1
|
||||
#define MAX_NR_GATT_CLIENTS 1
|
||||
#define MAX_NR_GATT_SUBCLIENTS 1
|
||||
|
||||
#define MAX_NR_RFCOMM_MULTIPLEXERS 0
|
||||
#define MAX_NR_RFCOMM_SERVICES 0
|
||||
#define MAX_NR_RFCOMM_CHANNELS 0
|
||||
#define MAX_NR_HFP_CONNECTIONS 0
|
||||
#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 0
|
||||
#define MAX_NR_BNEP_SERVICES 0
|
||||
#define MAX_NR_BNEP_CHANNELS 0
|
||||
#define MAX_NR_SERVICE_RECORD_ITEMS 1
|
||||
|
||||
#endif
|
105
port/nrf5-zephyr/create_examples.py
Executable file
105
port/nrf5-zephyr/create_examples.py
Executable file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Create project files for all BTstack embedded examples in zephyr/samples/btstack
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
mk_template = '''#
|
||||
# BTstack example 'EXAMPLE' for nRF5-zephyr port
|
||||
#
|
||||
# Generated by TOOL
|
||||
# On DATE
|
||||
|
||||
obj-y += EXAMPLE.o
|
||||
obj-y += main.o
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/bluetooth/controller/ll
|
||||
|
||||
'''
|
||||
|
||||
gatt_update_template = '''#!/bin/sh
|
||||
DIR=`dirname $0`
|
||||
BTSTACK_ROOT=$DIR/../../../btstack
|
||||
echo "Creating src/EXAMPLE.h from EXAMPLE.gatt"
|
||||
$BTSTACK_ROOT/tool/compile_gatt.py $BTSTACK_ROOT/example/EXAMPLE.gatt $DIR/src/EXAMPLE.h
|
||||
'''
|
||||
|
||||
# get script path
|
||||
script_path = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||
|
||||
# validate nRF5x SDK root by reading include/zephyr.h
|
||||
zpehyr_base = script_path + "/../../../"
|
||||
|
||||
zephyr_h = ""
|
||||
try:
|
||||
with open(zpehyr_base + '/include/zephyr.h', 'r') as fin:
|
||||
zephyr_h = fin.read() # Read the contents of the file into memory.
|
||||
except:
|
||||
pass
|
||||
if not "_ZEPHYR__H" in zephyr_h:
|
||||
print("Cannot find Zpehyr root. Make sure BTstack is checked out as zephyr/btstack")
|
||||
sys.exit(1)
|
||||
|
||||
# path to examples
|
||||
examples_embedded = script_path + "/../../example/"
|
||||
|
||||
# path to zephyr/samples/btstack
|
||||
apps_btstack = zpehyr_base + "/samples/btstack/"
|
||||
|
||||
print("Creating examples in samples/btstack:")
|
||||
|
||||
# iterate over btstack examples
|
||||
for file in os.listdir(examples_embedded):
|
||||
if not file.endswith(".c"):
|
||||
continue
|
||||
|
||||
example = file[:-2]
|
||||
gatt_path = examples_embedded + example + ".gatt"
|
||||
|
||||
# filter LE-only applications
|
||||
if not os.path.exists(gatt_path) and not example in [
|
||||
"ancs_cient_demo","gap_le_advertisements", "gatt_battery_query","gatt_browser","sm_pairing_central"]:
|
||||
continue
|
||||
if example == "spp_and_le_counter":
|
||||
continue
|
||||
|
||||
# create folder
|
||||
apps_folder = apps_btstack + example + "/"
|
||||
if not os.path.exists(apps_folder):
|
||||
os.makedirs(apps_folder)
|
||||
|
||||
# copy files
|
||||
for item in ['nrf5.conf', 'flash_nrf51_pca10028.sh', 'flash_nrf52_pca10040.sh', 'Makefile']:
|
||||
shutil.copyfile(script_path + '/' + item, apps_folder + '/' + item)
|
||||
|
||||
# create src folder
|
||||
src_folder = apps_folder + "src/"
|
||||
if not os.path.exists(src_folder):
|
||||
os.makedirs(src_folder)
|
||||
|
||||
# create Makefile file
|
||||
with open(src_folder + "Makefile", "wt") as fout:
|
||||
fout.write(mk_template.replace("EXAMPLE", example).replace("TOOL", script_path).replace("DATE",time.strftime("%c")))
|
||||
|
||||
# copy port main.c
|
||||
shutil.copyfile(script_path + '/main.c', src_folder + "/main.c")
|
||||
|
||||
# copy example file
|
||||
shutil.copyfile(examples_embedded + file, src_folder + "/" + example + ".c")
|
||||
|
||||
# create update_gatt.sh if .gatt file is present
|
||||
gatt_path = examples_embedded + example + ".gatt"
|
||||
if os.path.exists(gatt_path):
|
||||
update_gatt_script = apps_folder + "update_gatt_db.sh"
|
||||
with open(update_gatt_script, "wt") as fout:
|
||||
fout.write(gatt_update_template.replace("EXAMPLE", example))
|
||||
os.chmod(update_gatt_script, 0o755)
|
||||
subprocess.call(update_gatt_script + "> /dev/null", shell=True)
|
||||
print("- %s including compiled GATT DB" % example)
|
||||
else:
|
||||
print("- %s" % example)
|
||||
|
4
port/nrf5-zephyr/flash_nrf51_pca10028.sh
Executable file
4
port/nrf5-zephyr/flash_nrf51_pca10028.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
nrfjprog --eraseall -f nrf51
|
||||
nrfjprog --program outdir/nrf51_pca10028/zephyr.hex -f nrf51
|
||||
nrfjprog --reset -f nrf51
|
4
port/nrf5-zephyr/flash_nrf52_pca10040.sh
Executable file
4
port/nrf5-zephyr/flash_nrf52_pca10040.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
nrfjprog --eraseall -f nrf52
|
||||
nrfjprog --program outdir/nrf52_pca10040/zephyr.hex -f nrf52
|
||||
nrfjprog --reset -f nrf52
|
46
port/nrf5-zephyr/hci_uart.patch
Normal file
46
port/nrf5-zephyr/hci_uart.patch
Normal file
@ -0,0 +1,46 @@
|
||||
diff --git a/samples/bluetooth/hci_uart/src/main.c b/samples/bluetooth/hci_uart/src/main.c
|
||||
index b103f05..80a82d3 100644
|
||||
--- a/samples/bluetooth/hci_uart/src/main.c
|
||||
+++ b/samples/bluetooth/hci_uart/src/main.c
|
||||
@@ -36,6 +36,9 @@
|
||||
#include <bluetooth/buf.h>
|
||||
#include <bluetooth/hci_raw.h>
|
||||
|
||||
+#include "ll.h"
|
||||
+#include "nrf.h"
|
||||
+
|
||||
static struct device *hci_uart_dev;
|
||||
|
||||
#define STACK_SIZE 1024
|
||||
@@ -301,6 +304,18 @@ static int hci_uart_init(struct device *unused)
|
||||
DEVICE_INIT(hci_uart, "hci_uart", &hci_uart_init, NULL, NULL,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
|
||||
+void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
|
||||
+ buffer[pos++] = value;
|
||||
+ buffer[pos++] = value >> 8;
|
||||
+}
|
||||
+
|
||||
+void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
|
||||
+ buffer[pos++] = value;
|
||||
+ buffer[pos++] = value >> 8;
|
||||
+ buffer[pos++] = value >> 16;
|
||||
+ buffer[pos++] = value >> 24;
|
||||
+}
|
||||
+
|
||||
void main(void)
|
||||
{
|
||||
/* incoming events and data from the controller */
|
||||
@@ -320,6 +335,12 @@ void main(void)
|
||||
(nano_fiber_entry_t)tx_fiber, 0, 0, 7, 0);
|
||||
|
||||
bt_enable_raw(&rx_queue);
|
||||
+
|
||||
+ // make Random Static Address available via HCI Read BD ADDR as fake public address
|
||||
+ uint8_t addr[6];
|
||||
+ little_endian_store_16(addr, 4, NRF_FICR->DEVICEADDR[1] | 0xc000);
|
||||
+ little_endian_store_32(addr, 0, NRF_FICR->DEVICEADDR[0]);
|
||||
+ ll_address_set(0, addr);
|
||||
|
||||
while (1) {
|
||||
struct net_buf *buf;
|
68
port/nrf5-zephyr/integrate_btstack.sh
Executable file
68
port/nrf5-zephyr/integrate_btstack.sh
Executable file
@ -0,0 +1,68 @@
|
||||
#/bin/sh
|
||||
|
||||
ZEPHYR_BASE=../../..
|
||||
|
||||
echo "Adding BTstack sources as subsys/btstack"
|
||||
|
||||
|
||||
# add btstack folder to subsys/Makefile
|
||||
MAKEFILE_ADD_ON='obj-$(CONFIG_BTSTACK) += btstack/'
|
||||
NET_MAKEFILE=${ZEPHYR_BASE}/subsys/Makefile
|
||||
grep -q -F btstack ${NET_MAKEFILE} || echo ${MAKEFILE_ADD_ON} >> ${NET_MAKEFILE}
|
||||
|
||||
# add BTstack KConfig to net/Kconfig
|
||||
SUBSYS_KCONFIG=${ZEPHYR_BASE}/subsys/Kconfig
|
||||
grep -q -F btstack ${SUBSYS_KCONFIG} || echo 'source "subsys/btstack/Kconfig"' >> ${SUBSYS_KCONFIG}
|
||||
|
||||
# set Nordic Semiconductor as manufacturer
|
||||
CTRL_H=${ZEPHYR_BASE}/subsys/bluetooth/controller/ll/ctrl.h
|
||||
sed -i "s|#define RADIO_BLE_COMPANY_ID.*0xFFFF.|#define RADIO_BLE_COMPANY_ID (0x0059) // Nordic Semiconductor ASA|g" ${CTRL_H}
|
||||
|
||||
|
||||
# create subsys/btstack
|
||||
mkdir -p ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy sources
|
||||
rsync -a ../../src/ ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy embedded run loop
|
||||
rsync -a ../../platform/embedded/hal_cpu.h ${ZEPHYR_BASE}/subsys/btstack
|
||||
rsync -a ../../platform/embedded/hal_time_ms.h ${ZEPHYR_BASE}/subsys/btstack
|
||||
rsync -a ../../platform/embedded/hal_tick.h ${ZEPHYR_BASE}/subsys/btstack
|
||||
rsync -a ../../platform/embedded/btstack_run_loop_embedded.h ${ZEPHYR_BASE}/subsys/btstack
|
||||
rsync -a ../../platform/embedded/btstack_run_loop_embedded.c ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy bludroid
|
||||
rsync -a ../../3rd-party/bluedroid ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy btstack_config.h
|
||||
rsync -a btstack_config.h ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy Kconfig
|
||||
rsync -a Kconfig ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
# copy Makefiles
|
||||
rsync -a Makefile.src ${ZEPHYR_BASE}/subsys/btstack/Makefile
|
||||
rsync -a Makefile.classic ${ZEPHYR_BASE}/subsys/btstack/classic/Makefile
|
||||
rsync -a Makefile.ble ${ZEPHYR_BASE}/subsys/btstack/ble/Makefile
|
||||
rsync -a Makefile.gatt-service ${ZEPHYR_BASE}/subsys/btstack/ble/gatt-service/Makefile
|
||||
rsync -a Makefile.bluedroid ${ZEPHYR_BASE}/subsys/btstack/bluedroid/Makefile
|
||||
rsync -a Makefile.bluedroid-encoder ${ZEPHYR_BASE}/subsys/btstack/bluedroid/encoder/srce/Makefile
|
||||
rsync -a Makefile.bluedroid-decoder ${ZEPHYR_BASE}/subsys/btstack/bluedroid/decoder/srce/Makefile
|
||||
|
||||
# create samples/btstack
|
||||
./create_examples.py
|
||||
|
||||
|
||||
## Additonal changes for HCI Controller firmware in samples/bluetooth/hci-uart
|
||||
HCI_UART=${ZEPHYR_BASE}/samples/bluetooth/hci_uart
|
||||
|
||||
# add flash scripts to hci-uart
|
||||
rsync -a flash_nrf51_pca10028.sh ${HCI_UART}/flash_nrf51_pca10028.sh
|
||||
rsync -a flash_nrf52_pca10040.sh ${HCI_UART}/flash_nrf52_pca10040.sh
|
||||
|
||||
# use 115200 baud
|
||||
sed -i 's|CONFIG_UART_NRF5_BAUD_RATE=1000000|CONFIG_UART_NRF5_BAUD_RATE=115200|g' ${HCI_UART}/nrf5.conf
|
||||
|
||||
# provide static random address to host via hci read bd addr
|
||||
grep -q -F ll_address_set ${HCI_UART}/src/main.c || cat hci-uart.patch | patch -d ${ZEPHYR_BASE} -p1
|
388
port/nrf5-zephyr/main.c
Normal file
388
port/nrf5-zephyr/main.c
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* BTstack port for Zephyr Bluetooth Controller
|
||||
*
|
||||
* Data Sources aside from the HCI Controller are not supported yet
|
||||
* Timers are supported by waiting on the HCI Controller RX queue until the next timeout is due
|
||||
*/
|
||||
|
||||
// libc
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// zephyr
|
||||
#include <arch/cpu.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/kernel_event_logger.h>
|
||||
#include <misc/sys_log.h>
|
||||
#include <misc/util.h>
|
||||
#include <net/buf.h>
|
||||
#include <sys_clock.h>
|
||||
#include <uart.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
// Bluetooth Controller
|
||||
#include "ll.h"
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/buf.h>
|
||||
#include <bluetooth/hci_raw.h>
|
||||
|
||||
// Nordic NFK
|
||||
#include "nrf.h"
|
||||
|
||||
// BTstack
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
#include "hci_transport.h"
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void (*transport_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
|
||||
|
||||
//
|
||||
// hci_transport_zephyr.c
|
||||
//
|
||||
|
||||
/* HCI command buffers */
|
||||
#define CMD_BUF_SIZE (CONFIG_BLUETOOTH_HCI_SEND_RESERVE + \
|
||||
sizeof(struct bt_hci_cmd_hdr) + \
|
||||
CONFIG_BLUETOOTH_MAX_CMD_LEN)
|
||||
|
||||
static struct nano_fifo avail_cmd_tx;
|
||||
static NET_BUF_POOL(cmd_tx_pool, CONFIG_BLUETOOTH_HCI_CMD_COUNT, CMD_BUF_SIZE,
|
||||
&avail_cmd_tx, NULL, BT_BUF_USER_DATA_MIN);
|
||||
|
||||
#define BT_L2CAP_MTU 64
|
||||
/** Data size needed for ACL buffers */
|
||||
#define BT_BUF_ACL_SIZE (CONFIG_BLUETOOTH_HCI_RECV_RESERVE + \
|
||||
sizeof(struct bt_hci_acl_hdr) + \
|
||||
4 /* L2CAP header size */ + \
|
||||
BT_L2CAP_MTU)
|
||||
|
||||
static struct nano_fifo avail_acl_tx;
|
||||
static NET_BUF_POOL(acl_tx_pool, CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS,
|
||||
BT_BUF_ACL_SIZE, &avail_acl_tx, NULL, BT_BUF_USER_DATA_MIN);
|
||||
|
||||
static struct nano_fifo rx_queue;
|
||||
static struct nano_fifo tx_queue;
|
||||
|
||||
/**
|
||||
* init transport
|
||||
* @param transport_config
|
||||
*/
|
||||
static void transport_init(const void *transport_config){
|
||||
/* Initialize the buffer pools */
|
||||
net_buf_pool_init(cmd_tx_pool);
|
||||
net_buf_pool_init(acl_tx_pool);
|
||||
|
||||
/* Initialize the FIFOs */
|
||||
nano_fifo_init(&tx_queue);
|
||||
nano_fifo_init(&rx_queue);
|
||||
|
||||
/* startup Controller */
|
||||
bt_enable_raw(&rx_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* open transport connection
|
||||
*/
|
||||
static int transport_open(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* close transport connection
|
||||
*/
|
||||
static int transport_close(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* register packet handler for HCI packets: ACL, SCO, and Events
|
||||
*/
|
||||
static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
|
||||
transport_packet_handler = handler;
|
||||
}
|
||||
|
||||
static void send_hardware_error(uint8_t error_code){
|
||||
// hci_outgoing_event[0] = HCI_EVENT_HARDWARE_ERROR;
|
||||
// hci_outgoing_event[1] = 1;
|
||||
// hci_outgoing_event[2] = error_code;
|
||||
// hci_outgoing_event_ready = 1;
|
||||
}
|
||||
|
||||
static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
|
||||
struct net_buf *buf;
|
||||
switch (packet_type){
|
||||
case HCI_COMMAND_DATA_PACKET:
|
||||
buf = net_buf_get(&avail_cmd_tx, 0);
|
||||
if (buf) {
|
||||
bt_buf_set_type(buf, BT_BUF_CMD);
|
||||
memcpy(net_buf_add(buf, size), packet, size);
|
||||
bt_send(buf);
|
||||
} else {
|
||||
log_error("No available command buffers!\n");
|
||||
}
|
||||
break;
|
||||
case HCI_ACL_DATA_PACKET:
|
||||
buf = net_buf_get(&avail_acl_tx, 0);
|
||||
if (buf) {
|
||||
bt_buf_set_type(buf, BT_BUF_ACL_OUT);
|
||||
memcpy(net_buf_add(buf, size), packet, size);
|
||||
bt_send(buf);
|
||||
} else {
|
||||
log_error("No available ACL buffers!\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
send_hardware_error(0x01); // invalid HCI packet
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const hci_transport_t transport = {
|
||||
/* const char * name; */ "nRF5-Zephyr",
|
||||
/* void (*init) (const void *transport_config); */ &transport_init,
|
||||
/* int (*open)(void); */ &transport_open,
|
||||
/* int (*close)(void); */ &transport_close,
|
||||
/* void (*register_packet_handler)(void (*handler)(...); */ &transport_register_packet_handler,
|
||||
/* int (*can_send_packet_now)(uint8_t packet_type); */ NULL,
|
||||
/* int (*send_packet)(...); */ &transport_send_packet,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ NULL,
|
||||
/* void (*reset_link)(void); */ NULL,
|
||||
};
|
||||
|
||||
static const hci_transport_t * transport_get_instance(void){
|
||||
return &transport;
|
||||
}
|
||||
|
||||
static void transport_deliver_controller_packet(struct net_buf * buf){
|
||||
uint16_t size = buf->len;
|
||||
uint8_t * packet = buf->data;
|
||||
switch (bt_buf_get_type(buf)) {
|
||||
case BT_BUF_ACL_IN:
|
||||
transport_packet_handler(HCI_ACL_DATA_PACKET, packet, size);
|
||||
break;
|
||||
case BT_BUF_EVT:
|
||||
transport_packet_handler(HCI_EVENT_PACKET, packet, size);
|
||||
break;
|
||||
default:
|
||||
log_error("Unknown type %u\n", bt_buf_get_type(buf));
|
||||
net_buf_unref(buf);
|
||||
break;
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
// btstack_run_loop_zephry.c
|
||||
|
||||
// the run loop
|
||||
static btstack_linked_list_t timers;
|
||||
|
||||
static int sys_clock_ms_per_tick; // set in btstack_run_loop_zephyr_init()
|
||||
|
||||
static uint32_t btstack_run_loop_zephyr_get_time_ms(void){
|
||||
return sys_tick_get_32() * sys_clock_ms_per_tick;
|
||||
}
|
||||
|
||||
static uint32_t btstack_run_loop_zephyr_ticks_for_ms(uint32_t time_in_ms){
|
||||
return time_in_ms / sys_clock_ms_per_tick;
|
||||
}
|
||||
|
||||
static void btstack_run_loop_zephyr_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){
|
||||
uint32_t ticks = btstack_run_loop_zephyr_ticks_for_ms(timeout_in_ms);
|
||||
if (ticks == 0) ticks++;
|
||||
// time until next tick is < hal_tick_get_tick_period_in_ms() and we don't know, so we add one
|
||||
ts->timeout = sys_tick_get_32() + 1 + ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add timer to run_loop (keep list sorted)
|
||||
*/
|
||||
static void btstack_run_loop_zephyr_add_timer(btstack_timer_source_t *ts){
|
||||
btstack_linked_item_t *it;
|
||||
for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){
|
||||
// don't add timer that's already in there
|
||||
if ((btstack_timer_source_t *) it->next == ts){
|
||||
log_error( "btstack_run_loop_timer_add error: timer to add already in list!");
|
||||
return;
|
||||
}
|
||||
if (ts->timeout < ((btstack_timer_source_t *) it->next)->timeout) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ts->item.next = it->next;
|
||||
it->next = (btstack_linked_item_t *) ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove timer from run loop
|
||||
*/
|
||||
static int btstack_run_loop_zephyr_remove_timer(btstack_timer_source_t *ts){
|
||||
return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts);
|
||||
}
|
||||
|
||||
static void btstack_run_loop_zephyr_dump_timer(void){
|
||||
#ifdef ENABLE_LOG_INFO
|
||||
btstack_linked_item_t *it;
|
||||
int i = 0;
|
||||
for (it = (btstack_linked_item_t *) timers; it ; it = it->next){
|
||||
btstack_timer_source_t *ts = (btstack_timer_source_t*) it;
|
||||
log_info("timer %u, timeout %u\n", i, (unsigned int) ts->timeout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute run_loop
|
||||
*/
|
||||
static void btstack_run_loop_zephyr_execute(void) {
|
||||
while (1) {
|
||||
// get next timeout
|
||||
int32_t timeout_ticks = TICKS_UNLIMITED;
|
||||
if (timers) {
|
||||
btstack_timer_source_t * ts = (btstack_timer_source_t *) timers;
|
||||
uint32_t now = sys_tick_get_32();
|
||||
if (ts->timeout < now){
|
||||
// remove timer before processing it to allow handler to re-register with run loop
|
||||
btstack_run_loop_remove_timer(ts);
|
||||
// printf("RL: timer %p\n", ts->process);
|
||||
ts->process(ts);
|
||||
continue;
|
||||
}
|
||||
timeout_ticks = ts->timeout - now;
|
||||
}
|
||||
|
||||
// process RX fifo only
|
||||
struct net_buf *buf = net_buf_get_timeout(&rx_queue, 0, timeout_ticks);
|
||||
if (buf){
|
||||
transport_deliver_controller_packet(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_run_loop_zephyr_btstack_run_loop_init(void){
|
||||
timers = NULL;
|
||||
sys_clock_ms_per_tick = sys_clock_us_per_tick / 1000;
|
||||
log_info("btstack_run_loop_init: ms_per_tick %u", sys_clock_ms_per_tick);
|
||||
}
|
||||
|
||||
static const btstack_run_loop_t btstack_run_loop_wiced = {
|
||||
&btstack_run_loop_zephyr_btstack_run_loop_init,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&btstack_run_loop_zephyr_set_timer,
|
||||
&btstack_run_loop_zephyr_add_timer,
|
||||
&btstack_run_loop_zephyr_remove_timer,
|
||||
&btstack_run_loop_zephyr_execute,
|
||||
&btstack_run_loop_zephyr_dump_timer,
|
||||
&btstack_run_loop_zephyr_get_time_ms,
|
||||
};
|
||||
/**
|
||||
* @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init
|
||||
*/
|
||||
const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void){
|
||||
return &btstack_run_loop_wiced;
|
||||
}
|
||||
|
||||
// main.c
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
}
|
||||
|
||||
int btstack_main(void);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printf("BTstack booting up..\n");
|
||||
|
||||
// start with BTstack init - especially configure HCI Transport
|
||||
btstack_memory_init();
|
||||
btstack_run_loop_init(btstack_run_loop_zephyr_get_instance());
|
||||
|
||||
// enable full log output while porting
|
||||
hci_dump_open(NULL, HCI_DUMP_STDOUT);
|
||||
|
||||
// init HCI
|
||||
hci_init(transport_get_instance(), NULL);
|
||||
|
||||
// nRF5 chipsets don't have an official public address
|
||||
// Instead, they use a Static Random Address set in the factory
|
||||
bd_addr_t addr;
|
||||
#if 0
|
||||
// set random static address
|
||||
big_endian_store_16(addr, 0, NRF_FICR->DEVICEADDR[1] | 0xc000);
|
||||
big_endian_store_32(addr, 2, NRF_FICR->DEVICEADDR[0]);
|
||||
gap_random_address_set(addr);
|
||||
printf("Random Static Address: %s\n", bd_addr_to_str(addr));
|
||||
#else
|
||||
// make Random Static Address available via HCI Read BD ADDR as fake public address
|
||||
little_endian_store_32(addr, 0, NRF_FICR->DEVICEADDR[0]);
|
||||
little_endian_store_16(addr, 4, NRF_FICR->DEVICEADDR[1] | 0xc000);
|
||||
ll_address_set(0, addr);
|
||||
#endif
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
||||
// hand over to btstack embedded code
|
||||
btstack_main();
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
|
||||
while (1){};
|
||||
}
|
11
port/nrf5-zephyr/net-Kconfig.patch
Normal file
11
port/nrf5-zephyr/net-Kconfig.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- Kconfig 2016-11-03 15:27:17.000000000 +0100
|
||||
+++ Kconfig-new 2016-11-04 10:59:50.000000000 +0100
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
source "net/bluetooth/Kconfig"
|
||||
|
||||
+source "net/btstack/Kconfig"
|
||||
+
|
||||
source "net/ip/Kconfig"
|
||||
|
||||
config NET_BUF
|
18
port/nrf5-zephyr/nrf5.conf
Normal file
18
port/nrf5-zephyr/nrf5.conf
Normal file
@ -0,0 +1,18 @@
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_UART_NRF5_BAUD_RATE=115200
|
||||
# CONFIG_UART_NRF5_FLOW_CONTROL=y
|
||||
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
|
||||
CONFIG_BLUETOOTH=y
|
||||
CONFIG_BLUETOOTH_STACK_HCI_RAW=y
|
||||
CONFIG_BLUETOOTH_MAX_CONN=16
|
||||
CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS=4
|
||||
CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS=4
|
||||
|
||||
CONFIG_BTSTACK=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
31
port/nrf5-zephyr/readme.md
Normal file
31
port/nrf5-zephyr/readme.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Experimental port of BTstack to Zephyr running on Nordic nRF5 Series
|
||||
|
||||
## Overview
|
||||
|
||||
This port targets the bare Nordic nRF5-Series chipsets with the BLE Link Layer provided by the Zephyr project.
|
||||
|
||||
## Status
|
||||
|
||||
Working with nRF52 pca10040 dev board. Public BD ADDR is set to 11:22:33:44:55:66 since the default 00:00:00:00:00:00 is filtered by iOS.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To integrate BTstack into Zephyr, please move the BTstack project into the Zephyr root folder 'zephyr'.
|
||||
|
||||
Then integrate BTstack:
|
||||
|
||||
cd /path/to/zephy/btstack/port/nrf5-zephyr
|
||||
./integrate_btstack.sh
|
||||
|
||||
Now, the BTstack examples can be build from the Zephyr examples folder in the same way as other examples, e.g.:
|
||||
|
||||
cd /path/to/zephyr/samples/btstack/le_counter
|
||||
make
|
||||
|
||||
to build the le_counter example for the pca10040 dev kit using the ARM GCC compiler.
|
||||
|
||||
See nRF5 SDK documentation about how to install it.
|
||||
|
||||
All examples that provide a GATT Server use the GATT DB in the .gatt file. Therefore you need to run ./update_gatt_db.sh in the example folder after modifying the .gatt file.
|
||||
|
||||
This port does not support Data Sources aside from the HCI Controller.
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
#
|
||||
#Sun Oct 23 22:44:44 CEST 2016
|
||||
#Mon Oct 24 22:05:18 CEST 2016
|
||||
default.com-microchip-mplab-nbide-toolchainXC32-XC32LanguageToolchain.md5=53fb2ac0203ca7bc347fa1cfc029d2dd
|
||||
default.languagetoolchain.dir=/Applications/microchip/xc32/v1.40/bin
|
||||
configurations-xml=880fc707b92b93228f793a58d9edff81
|
||||
configurations-xml=285233d36c15a8f39094c0464f5526d5
|
||||
com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=4b47e815d50912689a67d0b162f47a58
|
||||
default.languagetoolchain.version=1.40
|
||||
host.platform=mac
|
||||
|
@ -17,8 +17,57 @@
|
||||
<itemPath>../src/app.h</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="f3" displayName="btstack" projectFiles="true">
|
||||
<logicalFolder name="3rd-party" displayName="3rd-party" projectFiles="true">
|
||||
<logicalFolder name="bluedroid" displayName="bluedroid" projectFiles="true">
|
||||
<logicalFolder name="decoder" displayName="decoder" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_assert.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_bitstream.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_bt_spec.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_codec_sbc.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_codec_sbc_private.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_common.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_cpu_dep.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_modules.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_osinterface.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_status.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_stddefs.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_string.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_time.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/include/oi_utils.h</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="srce" displayName="srce" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/readsamplesjoint.inc</itemPath>
|
||||
</logicalFolder>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/Makefile.inc</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="encoder" displayName="encoder" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/include/sbc_dct.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/include/sbc_enc_func_declare.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/include/sbc_encoder.h</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/include/sbc_types.h</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="srce" displayName="srce" projectFiles="true">
|
||||
</logicalFolder>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/Makefile.inc</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="mbedtls" displayName="mbedtls" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
<logicalFolder name="mbedtls" displayName="mbedtls" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/bignum.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/bn_mul.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/check_config.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/config.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/ecp.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/memory_buffer_alloc.h</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/include/mbedtls/platform.h</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="ble" displayName="ble" projectFiles="true">
|
||||
<itemPath>../../../src/ad_parser.h</itemPath>
|
||||
<itemPath>../../../src/ble/ancs_client.h</itemPath>
|
||||
<itemPath>../../../src/ble/att_db.h</itemPath>
|
||||
<itemPath>../../../src/ble/att_dispatch.h</itemPath>
|
||||
@ -59,6 +108,7 @@
|
||||
<itemPath>../../../src/l2cap.h</itemPath>
|
||||
<itemPath>../../../src/l2cap_signaling.h</itemPath>
|
||||
<itemPath>../../../src/btstack_uart_block.h</itemPath>
|
||||
<itemPath>../../../src/ad_parser.h</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="f2" displayName="framework" projectFiles="true">
|
||||
@ -107,13 +157,55 @@
|
||||
<itemPath>../../../example/spp_and_le_counter.c</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="f3" displayName="btstack" projectFiles="true">
|
||||
<logicalFolder name="f2" displayName="3rd-party" projectFiles="true">
|
||||
<logicalFolder name="library" displayName="library" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/mbedtls/library/bignum.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/ecp.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/ecp_curves.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/memory_buffer_alloc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/platform.c</itemPath>
|
||||
<logicalFolder name="3rd-party" displayName="3rd-party" projectFiles="true">
|
||||
<logicalFolder name="bluedroid" displayName="bluedroid" projectFiles="true">
|
||||
<logicalFolder name="decoder" displayName="decoder" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
</logicalFolder>
|
||||
<logicalFolder name="srce" displayName="srce" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/alloc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/bitalloc-sbc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/bitalloc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/bitstream-decode.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/decoder-oina.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/decoder-private.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/decoder-sbc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/dequant.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/framing-sbc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/framing.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/oi_codec_version.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/synthesis-8-generated.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/synthesis-dct8.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/decoder/srce/synthesis-sbc.c</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="encoder" displayName="encoder" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
</logicalFolder>
|
||||
<logicalFolder name="srce" displayName="srce" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_analysis.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_dct.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_dct_coeffs.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_enc_bit_alloc_mono.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_enc_bit_alloc_ste.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_enc_coeffs.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_encoder.c</itemPath>
|
||||
<itemPath>../../../3rd-party/bluedroid/encoder/srce/sbc_packing.c</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="mbedtls" displayName="mbedtls" projectFiles="true">
|
||||
<logicalFolder name="include" displayName="include" projectFiles="true">
|
||||
<logicalFolder name="mbedtls" displayName="mbedtls" projectFiles="true">
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="library" displayName="library" projectFiles="true">
|
||||
<itemPath>../../../3rd-party/mbedtls/library/bignum.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/ecp.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/ecp_curves.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/memory_buffer_alloc.c</itemPath>
|
||||
<itemPath>../../../3rd-party/mbedtls/library/platform.c</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="ble" displayName="ble" projectFiles="true">
|
||||
@ -132,7 +224,6 @@
|
||||
<itemPath>../../../platform/embedded/btstack_uart_block_embedded.c</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="src" displayName="src" projectFiles="true">
|
||||
<itemPath>../../../src/ad_parser.c</itemPath>
|
||||
<itemPath>../../../src/btstack_memory.c</itemPath>
|
||||
<itemPath>../../../src/hci.c</itemPath>
|
||||
<itemPath>../../../src/hci_cmd.c</itemPath>
|
||||
@ -153,6 +244,7 @@
|
||||
<itemPath>../../../src/hci_transport_h4.c</itemPath>
|
||||
<itemPath>../../../src/hci_transport_h5.c</itemPath>
|
||||
<itemPath>../../../src/btstack_slip.c</itemPath>
|
||||
<itemPath>../../../src/ad_parser.c</itemPath>
|
||||
</logicalFolder>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="f2" displayName="framework" projectFiles="true">
|
||||
@ -208,8 +300,7 @@
|
||||
<Elem>../../../chipset/csr</Elem>
|
||||
<Elem>../../../example</Elem>
|
||||
<Elem>../../../platform/embedded</Elem>
|
||||
<Elem>../../../3rd-party/mbedtls/include</Elem>
|
||||
<Elem>../../../3rd-party/mbedtls/library</Elem>
|
||||
<Elem>../../../3rd-party</Elem>
|
||||
</sourceRootList>
|
||||
<projectmakefile>Makefile</projectmakefile>
|
||||
<confs>
|
||||
@ -255,7 +346,7 @@
|
||||
<property key="enable-unroll-loops" value="false"/>
|
||||
<property key="exclude-floating-point" value="false"/>
|
||||
<property key="extra-include-directories"
|
||||
value=".;../../../..;../src;../src/system_config/bt_audio_dk;../../../src;../../../chipset/csr;../../../platform/embedded;../../../3rd-party/mbedtls/include"/>
|
||||
value=".;../../../..;../src;../src/system_config/bt_audio_dk;../../../src;../../../chipset/csr;../../../platform/embedded;../../../3rd-party/mbedtls/include;../../../3rd-party/bluedroid/decoder/include;../../../3rd-party/bluedroid/encoder/include"/>
|
||||
<property key="generate-16-bit-code" value="false"/>
|
||||
<property key="generate-micro-compressed-code" value="false"/>
|
||||
<property key="isolate-each-function" value="false"/>
|
||||
|
@ -3,6 +3,11 @@
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group/>
|
||||
<group>
|
||||
<file>file:/Users/mringwal/microchip/harmony/v1_07/framework/btstack/port/pic32-harmony/src/main.c</file>
|
||||
<file>file:/Users/mringwal/microchip/harmony/v1_07/framework/btstack/example/spp_and_le_counter.c</file>
|
||||
<file>file:/Users/mringwal/microchip/harmony/v1_07/framework/btstack/port/pic32-harmony/src/app.c</file>
|
||||
<file>file:/Users/mringwal/microchip/harmony/v1_07/framework/btstack/port/pic32-harmony/src/btstack_port.c</file>
|
||||
</group>
|
||||
</open-files>
|
||||
</project-private>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<c-extensions>c</c-extensions>
|
||||
<cpp-extensions/>
|
||||
<header-extensions>h</header-extensions>
|
||||
<asminc-extensions/>
|
||||
<asminc-extensions>inc</asminc-extensions>
|
||||
<sourceEncoding>ISO-8859-1</sourceEncoding>
|
||||
<make-dep-projects/>
|
||||
</data>
|
||||
|
@ -102,6 +102,7 @@ for file in os.listdir(examples_embedded):
|
||||
template = template.replace(">../../../../system", ">../../../../framework/system")
|
||||
template = template.replace(">../../../chipset", ">../../../../framework/btstack/chipset")
|
||||
template = template.replace(">../../../platform", ">../../../../framework/btstack/platform")
|
||||
template = template.replace(">../../../3rd-party", ">../../../../framework/btstack/3rd-party")
|
||||
template = template.replace(">../../../src", ">../../../../framework/btstack/src")
|
||||
template = template.replace(">../src", ">../../../../framework/btstack/port/pic32-harmony/src")
|
||||
template = template.replace("app.X", example+".X")
|
||||
|
@ -158,6 +158,9 @@ static void local_version_information_callback(uint8_t * packet){
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
case COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semicondutor ASA nRF5 chipset.\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
|
@ -11,12 +11,16 @@ Requirements:
|
||||
Components:
|
||||
- STM32 F103RB Nucleo Board
|
||||
- User's Manual: http://www.st.com/web/en/resource/technical/document/user_manual/DM00105823.pdf
|
||||
- EM Wireless Booster Pack
|
||||
- Info: http://www.ti.com/tool/boost-ccemadapter
|
||||
- User Guide: http://www.ti.com/lit/ug/swru338a/swru338a.pdf
|
||||
- Booster Pack Pinout: http://www.ti.com/ww/en/launchpad/dl/boosterpack-pinout-v2.pdf
|
||||
- CC256x Evaluation Module
|
||||
- Info: http://www.ti.com/tool/cc256xqfnem
|
||||
- CC2564B Bluetooth Controller:
|
||||
1. The best option is to get it as a BoostPack
|
||||
- Info: BOOST-CC2564MODA: http://www.ti.com/tool/BOOST-CC2564MODA
|
||||
2. Alternatively, get the evaluation module together with the EM Wireless Booster pack and a 32.768 kHz oscillator
|
||||
- EM Wireless Booster Pack:
|
||||
- Info: http://www.ti.com/tool/boost-ccemadapter
|
||||
- User Guide: http://www.ti.com/lit/ug/swru338a/swru338a.pdf
|
||||
- Booster Pack Pinout: http://www.ti.com/ww/en/launchpad/dl/boosterpack-pinout-v2.pdf
|
||||
- CC256x Evaluation Module:
|
||||
- Info: http://www.ti.com/tool/cc256xqfnem
|
||||
|
||||
Configuration:
|
||||
- Sys tick 250 ms
|
||||
@ -24,9 +28,20 @@ Configuration:
|
||||
- Debug UART: USART2 - 9600/8/N/1, TX on PA2
|
||||
- Bluetooth: USART3 with hardware flowcontrol RTS. IRQ on CTS Rising. TX PB10, RX PB11, CTS PB13 (in), RTS PB14 (out), N_SHUTDOWN PB15
|
||||
|
||||
Setup:
|
||||
- Solder 32.768 kHz quarz oscillator to EM Adapter Booster Pack as explained in 4.7 of the EM Wireless Booster Pack User Guide. If you don't have an oscillator of that size, you might solder one upside done (turtle on back style) to the unused upper right pad and wire GCC, VCC, and clock with thin wires.
|
||||
- Connect STM32 Nucleo Board to EM Wireless Board (see boosterpack pinout)
|
||||
Setup with CC2564 BoosterPack (BOOST-CC2564MODA):
|
||||
- Connect STM32 Nucleo Board to EM Wireless Board (see BoosterPack pinout)
|
||||
- GND: CN10-9 - 20 (J2)
|
||||
- VCC: CN7 -16 - 1 (J1)
|
||||
- RX3: CN10-18 - 3 (J1)
|
||||
- TX3: CN10-25 - 4 (J1)
|
||||
- CTS3: CN10-30 - 36 (J4)
|
||||
- RTS3: CN10-28 - 37 (J4)
|
||||
- N_SHUTDOWN: CN10-26 - 19 (J2)
|
||||
|
||||
|
||||
Setup with EM Wireless BoosterPack + CC256x Evaluation Module:
|
||||
- Solder 32.768 kHz quarz oscillator to EM Adapter Booster Pack as explained in 4.7 of the EM Wireless Booster Pack User Guide. If you don't have an oscillator of that size, you might solder one upside done (turtle-on-back style) to the unused upper right pad and wire GCC, VCC, and clock with thin wires.
|
||||
- Connect STM32 Nucleo Board to EM Wireless Board (see BoosterPack pinout)
|
||||
- GND: CN10-9 - 20 (LP2)
|
||||
- VCC: CN7 -16 - 1 (LP1)
|
||||
- RX3: CN10-18 - 3 (LP1)
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define ENABLE_CLASSIC
|
||||
// #define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
// #define ENABLE_LOG_INFO
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE 52
|
||||
@ -35,4 +35,7 @@
|
||||
#define MAX_NR_SM_LOOKUP_ENTRIES 3
|
||||
#define MAX_NR_SERVICE_RECORD_ITEMS 1
|
||||
|
||||
// Nun Link Keys stored in WICED DCT
|
||||
#define NVM_NUM_LINK_KEYS 10
|
||||
|
||||
#endif
|
226
port/wiced/btstack_link_key_db_wiced_dct.c
Normal file
226
port/wiced/btstack_link_key_db_wiced_dct.c
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_link_key_db_wiced_dct.c
|
||||
*
|
||||
* Persistent Link Key implemenetation for WICED using DCT mechanism
|
||||
*/
|
||||
|
||||
#include "classic/btstack_link_key_db.h"
|
||||
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_util.h"
|
||||
|
||||
#include "wiced.h"
|
||||
|
||||
// Link Key Magic
|
||||
#define LINK_KEY_MAGIC ((uint32_t) 'B' << 24 | 'T' << 16 | 'L' << 8 | 'K')
|
||||
|
||||
typedef struct link_key_nvm {
|
||||
uint32_t magic;
|
||||
uint32_t seq_nr; // used for "last recently stored" eviction strategy
|
||||
bd_addr_t bd_addr;
|
||||
link_key_t link_key;
|
||||
link_key_type_t link_key_type;
|
||||
} link_key_nvm_t;
|
||||
|
||||
static char link_key_to_str_buffer[LINK_KEY_STR_LEN+1]; // 11223344556677889900112233445566\0
|
||||
static char *link_key_to_str(link_key_t link_key){
|
||||
char * p = link_key_to_str_buffer;
|
||||
int i;
|
||||
for (i = 0; i < LINK_KEY_LEN ; i++) {
|
||||
*p++ = char_for_nibble((link_key[i] >> 4) & 0x0F);
|
||||
*p++ = char_for_nibble((link_key[i] >> 0) & 0x0F);
|
||||
}
|
||||
*p = 0;
|
||||
return (char *) link_key_to_str_buffer;
|
||||
}
|
||||
|
||||
static void link_key_db_init(void){
|
||||
log_info("Link Key DB initialized for DCT\n");
|
||||
}
|
||||
|
||||
static void link_key_db_close(void){
|
||||
}
|
||||
|
||||
// @return valid
|
||||
static int link_key_read(int index, link_key_nvm_t * out_entry){
|
||||
|
||||
// calculate address
|
||||
uint32_t address = index * sizeof(link_key_nvm_t);
|
||||
|
||||
// read lock
|
||||
link_key_nvm_t * entry;
|
||||
wiced_dct_read_lock((void*) &entry, WICED_FALSE, DCT_APP_SECTION, address, sizeof(link_key_nvm_t));
|
||||
|
||||
if (entry->magic == LINK_KEY_MAGIC){
|
||||
memcpy(out_entry, entry, sizeof(link_key_nvm_t));
|
||||
} else {
|
||||
memset(out_entry, 0, sizeof(link_key_nvm_t));
|
||||
}
|
||||
|
||||
// read unlock
|
||||
wiced_dct_read_unlock((void*) entry, WICED_FALSE);
|
||||
|
||||
return out_entry->magic == LINK_KEY_MAGIC;
|
||||
}
|
||||
|
||||
static void link_key_write(int index, link_key_nvm_t * entry){
|
||||
// calculate address
|
||||
uint32_t address = index * sizeof(link_key_nvm_t);
|
||||
// write block
|
||||
wiced_dct_write((void*)entry, DCT_APP_SECTION, address, sizeof(link_key_nvm_t));
|
||||
}
|
||||
|
||||
// returns entry index or -1
|
||||
static int link_key_find_entry_for_address(bd_addr_t address){
|
||||
link_key_nvm_t item;
|
||||
int i;
|
||||
for (i=0;i<NVM_NUM_LINK_KEYS;i++){
|
||||
link_key_read(i, &item);
|
||||
if (item.magic != LINK_KEY_MAGIC) continue;
|
||||
if (memcmp(address, &item.bd_addr, 6) != 0) continue;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// returns index
|
||||
static int link_key_find_free_entry(void){
|
||||
link_key_nvm_t item;
|
||||
int i;
|
||||
uint32_t seq_nr = 0;
|
||||
int lowest_index = -1;
|
||||
for (i=0;i<NVM_NUM_LINK_KEYS;i++){
|
||||
link_key_read(i, &item);
|
||||
if (item.magic != LINK_KEY_MAGIC) return i;
|
||||
if ((lowest_index < 0) || (item.seq_nr < seq_nr)){
|
||||
lowest_index = i;
|
||||
seq_nr= item.seq_nr;
|
||||
}
|
||||
}
|
||||
return lowest_index;
|
||||
}
|
||||
|
||||
static uint32_t link_key_highest_seq_nr(void){
|
||||
link_key_nvm_t item;
|
||||
int i;
|
||||
uint32_t seq_nr = 0;
|
||||
for (i=0;i<NVM_NUM_LINK_KEYS;i++){
|
||||
link_key_read(i, &item);
|
||||
if (item.magic != LINK_KEY_MAGIC) continue;
|
||||
if (item.seq_nr < seq_nr) continue;
|
||||
seq_nr = item.seq_nr;
|
||||
}
|
||||
return seq_nr;
|
||||
}
|
||||
|
||||
// returns 1 if found
|
||||
static int link_key_db_get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) {
|
||||
int index = link_key_find_entry_for_address(bd_addr);
|
||||
if (index < 0) {
|
||||
log_info("link_key_db_get_link_key for %s -> not found\n", bd_addr_to_str(bd_addr));
|
||||
return 0;
|
||||
}
|
||||
link_key_nvm_t item;
|
||||
link_key_read(index, &item);
|
||||
memcpy(link_key, item.link_key, LINK_KEY_LEN);
|
||||
if (link_key_type) {
|
||||
*link_key_type = item.link_key_type;
|
||||
}
|
||||
log_info("link_key_db_get_link_key for %s -> found %s\n", bd_addr_to_str(bd_addr), link_key_to_str(link_key));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void link_key_db_delete_link_key(bd_addr_t bd_addr){
|
||||
int index = link_key_find_entry_for_address(bd_addr);
|
||||
if (index < 0) return;
|
||||
|
||||
link_key_nvm_t item;
|
||||
memset(&item, 0, sizeof(item));
|
||||
link_key_write(index, &item);
|
||||
}
|
||||
|
||||
|
||||
static void link_key_db_put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){
|
||||
// check for existing record
|
||||
int index = link_key_find_entry_for_address(bd_addr);
|
||||
|
||||
// if not found, use new entry
|
||||
if (index < 0) {
|
||||
index = link_key_find_free_entry();
|
||||
}
|
||||
|
||||
log_info("link_key_db_put_link_key for %s - key %s - at index %u\n", bd_addr_to_str(bd_addr), link_key_to_str(link_key), index);
|
||||
|
||||
link_key_nvm_t item;
|
||||
item.magic = LINK_KEY_MAGIC;
|
||||
item.seq_nr = link_key_highest_seq_nr() + 1;
|
||||
memcpy(item.bd_addr, bd_addr, sizeof(bd_addr_t));
|
||||
memcpy(item.link_key, link_key, LINK_KEY_LEN);
|
||||
item.link_key_type = link_key_type;
|
||||
link_key_write(index, &item);
|
||||
}
|
||||
|
||||
static void link_key_db_set_local_bd_addr(bd_addr_t bd_addr){
|
||||
}
|
||||
|
||||
const btstack_link_key_db_t btstack_link_key_db_wiced_dct = {
|
||||
link_key_db_init,
|
||||
link_key_db_set_local_bd_addr,
|
||||
link_key_db_close,
|
||||
link_key_db_get_link_key,
|
||||
link_key_db_put_link_key,
|
||||
link_key_db_delete_link_key,
|
||||
};
|
||||
|
||||
// custom function
|
||||
void btstack_link_key_db_wiced_dct_delete_all(void){
|
||||
int i;
|
||||
link_key_nvm_t entry;
|
||||
memset(&entry, 0, sizeof(link_key_nvm_t));
|
||||
for (i=0;i<NVM_NUM_LINK_KEYS;i++){
|
||||
link_key_write(i, &entry);
|
||||
}
|
||||
}
|
||||
|
||||
const btstack_link_key_db_t * btstack_link_key_db_wiced_dct_instance(void){
|
||||
return &btstack_link_key_db_wiced_dct;
|
||||
}
|
70
port/wiced/btstack_link_key_db_wiced_dct.h
Normal file
70
port/wiced/btstack_link_key_db_wiced_dct.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_link_key_db_wiced_dct.c
|
||||
*
|
||||
* Persistent Link Key implemenetation for WICED using DCT mechanism
|
||||
*/
|
||||
|
||||
#ifndef __BTSTACK_LINK_KEY_WICED_DCT_H
|
||||
#define __BTSTACK_LINK_KEY_WICED_DCT_H
|
||||
|
||||
#include "btstack_config.h"
|
||||
#include "classic/btstack_link_key_db.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get btstack_link_key_db_t instance
|
||||
*/
|
||||
const btstack_link_key_db_t * btstack_link_key_db_wiced_dct_instance(void);
|
||||
|
||||
/*
|
||||
* @brief Delete all link keys
|
||||
*/
|
||||
void btstack_link_key_db_wiced_dct_delete_all(void);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BTSTACK_LINK_KEY_DB_MEMORY_H
|
@ -48,6 +48,10 @@
|
||||
#include "btstack_run_loop.h"
|
||||
#include "wiced.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init
|
||||
*/
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "btstack.h"
|
||||
#include "btstack_chipset_bcm.h"
|
||||
#include "btstack_run_loop_wiced.h"
|
||||
#include "btstack_link_key_db_wiced_dct.h"
|
||||
|
||||
#include "generated_mac_address.txt"
|
||||
|
||||
@ -86,7 +87,7 @@ void application_start(void){
|
||||
|
||||
// init HCI
|
||||
hci_init(hci_transport_h4_instance(NULL), (void*) &hci_transport_config_uart);
|
||||
hci_set_link_key_db(btstack_link_key_db_memory_instance());
|
||||
hci_set_link_key_db(btstack_link_key_db_wiced_dct_instance());
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
|
||||
// inform about BTstack state
|
||||
|
@ -11,7 +11,7 @@ Now, the BTstack examples can be build from the WICED root in the same way as ot
|
||||
|
||||
./make btstack.spp_and_le_counter-RB_DUO
|
||||
|
||||
to build the SPP-and-LE-Counter example.
|
||||
to build the SPP-and-LE-Counter example for the RedBear Duo.
|
||||
|
||||
See WICED documentation about how to install it.
|
||||
|
||||
@ -20,8 +20,6 @@ It should work with all WICED platforms that contain a Broadcom Bluetooth chipse
|
||||
The maximal baud rate is limited to 3 mbps.
|
||||
|
||||
The port uses the generated WIFI address plus 1 as Bluetooth MAC address.
|
||||
It stores Classic Link Keys using the DCT mechanism.
|
||||
|
||||
The examples that implement a BLE Peripheral/provide a GATT Server that uses the GATT DB in the .gatt file.
|
||||
After modifying the .gatt file, please run ./update_gatt_db.sh in the apps/btstack/$(EXAMPLE) folder.
|
||||
|
||||
|
||||
All examples that rovide a GATT Server use the GATT DB in the .gatt file. Therefore you need to run ./update_gatt_db.sh in the apps/btstack/$(EXAMPLE) folder after modifying the .gatt file.
|
||||
|
@ -40,6 +40,7 @@ $(NAME)_SOURCES += \
|
||||
# WICED port incl. support for Broadcom chipset
|
||||
$(NAME)_SOURCES += \
|
||||
main.c \
|
||||
btstack_link_key_db_wiced_dct.c \
|
||||
btstack_run_loop_wiced.c \
|
||||
hci_transport_h4_wiced.c \
|
||||
../../chipset/bcm/btstack_chipset_bcm.c \
|
||||
|
@ -47,20 +47,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bluetooth_data_types.h"
|
||||
#include "btstack_util.h"
|
||||
#include "classic/sdp_util.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
|
||||
#include "hci.h"
|
||||
#include "ad_parser.h"
|
||||
|
||||
typedef enum {
|
||||
IncompleteList16 = 0x02,
|
||||
CompleteList16 = 0x03,
|
||||
IncompleteList128 = 0x06,
|
||||
CompleteList128 = 0x07
|
||||
} UUID_TYPE;
|
||||
|
||||
void ad_iterator_init(ad_context_t *context, uint8_t ad_len, const uint8_t * ad_data){
|
||||
context->data = ad_data;
|
||||
context->length = ad_len;
|
||||
@ -104,15 +98,15 @@ int ad_data_contains_uuid16(uint8_t ad_len, const uint8_t * ad_data, uint16_t uu
|
||||
uint8_t ad_uuid128[16], uuid128_bt[16];
|
||||
|
||||
switch (data_type){
|
||||
case IncompleteList16:
|
||||
case CompleteList16:
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
for (i=0; i<data_len; i+=2){
|
||||
uint16_t uuid = little_endian_read_16(data, i);
|
||||
if ( uuid == uuid16 ) return 1;
|
||||
}
|
||||
break;
|
||||
case IncompleteList128:
|
||||
case CompleteList128:
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
uuid_add_bluetooth_prefix(ad_uuid128, uuid16);
|
||||
reverse_128(ad_uuid128, uuid128_bt);
|
||||
|
||||
@ -142,8 +136,8 @@ int ad_data_contains_uuid128(uint8_t ad_len, const uint8_t * ad_data, const uint
|
||||
|
||||
|
||||
switch (data_type){
|
||||
case IncompleteList16:
|
||||
case CompleteList16:
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
||||
for (i=0; i<data_len; i+=2){
|
||||
uint16_t uuid16 = little_endian_read_16(data, i);
|
||||
uuid_add_bluetooth_prefix(ad_uuid128, uuid16);
|
||||
@ -152,8 +146,8 @@ int ad_data_contains_uuid128(uint8_t ad_len, const uint8_t * ad_data, const uint
|
||||
}
|
||||
|
||||
break;
|
||||
case IncompleteList128:
|
||||
case CompleteList128:
|
||||
case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
||||
for (i=0; i<data_len; i+=16){
|
||||
if (memcmp(uuid128_le, &data[i], 16) == 0) return 1;
|
||||
}
|
||||
|
193
src/ble/att_db.c
193
src/ble/att_db.c
@ -39,9 +39,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bluetooth.h"
|
||||
#include "ble/att_db.h"
|
||||
#include "ble/core.h"
|
||||
#include "bluetooth.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_util.h"
|
||||
|
||||
@ -69,6 +69,8 @@ static att_write_callback_t att_write_callback = NULL;
|
||||
static uint8_t att_prepare_write_error_code = 0;
|
||||
static uint16_t att_prepare_write_error_handle = 0x0000;
|
||||
|
||||
static btstack_linked_list_t service_handlers;
|
||||
|
||||
// new java-style iterator
|
||||
typedef struct att_iterator {
|
||||
// private
|
||||
@ -152,6 +154,30 @@ static int att_find_handle(att_iterator_t *it, uint16_t handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (handler->start_handle > handle) continue;
|
||||
if (handler->end_handle < handle) continue;
|
||||
return handler;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static att_read_callback_t att_read_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->read_callback;
|
||||
return att_read_callback;
|
||||
}
|
||||
|
||||
static att_write_callback_t att_write_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->write_callback;
|
||||
return att_write_callback;
|
||||
}
|
||||
|
||||
// experimental client API
|
||||
uint16_t att_uuid_for_handle(uint16_t attribute_handle){
|
||||
att_iterator_t it;
|
||||
@ -163,8 +189,10 @@ uint16_t att_uuid_for_handle(uint16_t attribute_handle){
|
||||
// end of client API
|
||||
|
||||
static void att_update_value_len(att_iterator_t *it, hci_con_handle_t con_handle){
|
||||
if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0 || !att_read_callback) return;
|
||||
it->value_len = (*att_read_callback)(con_handle, it->handle, 0, NULL, 0);
|
||||
if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0) return;
|
||||
att_read_callback_t callback = att_read_callback_for_handle(it->handle);
|
||||
if (!callback) return;
|
||||
it->value_len = (*callback)(con_handle, it->handle, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -172,8 +200,10 @@ static void att_update_value_len(att_iterator_t *it, hci_con_handle_t con_handle
|
||||
static int att_copy_value(att_iterator_t *it, uint16_t offset, uint8_t * buffer, uint16_t buffer_size, hci_con_handle_t con_handle){
|
||||
|
||||
// DYNAMIC
|
||||
if ((it->flags & ATT_PROPERTY_DYNAMIC) && att_read_callback) {
|
||||
return (*att_read_callback)(con_handle, it->handle, offset, buffer, buffer_size);
|
||||
if (it->flags & ATT_PROPERTY_DYNAMIC){
|
||||
att_read_callback_t callback = att_read_callback_for_handle(it->handle);
|
||||
if (!callback) return 0;
|
||||
return (*callback)(con_handle, it->handle, offset, buffer, buffer_size);
|
||||
}
|
||||
|
||||
// STATIC
|
||||
@ -854,7 +884,8 @@ static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t
|
||||
if (!ok) {
|
||||
return setup_error_invalid_handle(response_buffer, request_type, handle);
|
||||
}
|
||||
if (!att_write_callback) {
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) {
|
||||
return setup_error_write_not_permitted(response_buffer, request_type, handle);
|
||||
}
|
||||
if ((it.flags & ATT_PROPERTY_WRITE) == 0) {
|
||||
@ -868,7 +899,7 @@ static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t
|
||||
if (error_code) {
|
||||
return setup_error(response_buffer, request_type, handle, error_code);
|
||||
}
|
||||
error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
error_code = (*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
if (error_code) {
|
||||
return setup_error(response_buffer, request_type, handle, error_code);
|
||||
}
|
||||
@ -885,7 +916,8 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
uint16_t offset = little_endian_read_16(request_buffer, 3);
|
||||
if (!att_write_callback) {
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) {
|
||||
return setup_error_write_not_permitted(response_buffer, request_type, handle);
|
||||
}
|
||||
att_iterator_t it;
|
||||
@ -905,7 +937,7 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
|
||||
return setup_error(response_buffer, request_type, handle, error_code);
|
||||
}
|
||||
|
||||
error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5);
|
||||
error_code = (*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5);
|
||||
switch (error_code){
|
||||
case 0:
|
||||
break;
|
||||
@ -924,12 +956,24 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
|
||||
return request_len;
|
||||
}
|
||||
|
||||
static void att_notify_write_callbacks(att_connection_t * att_connection, uint16_t transaction_mode){
|
||||
// notify all
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (!handler->write_callback) continue;
|
||||
(*handler->write_callback)(att_connection->con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
if (!att_write_callback) return;
|
||||
(*att_write_callback)(att_connection->con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief transcation queue of prepared writes, e.g., after disconnect
|
||||
*/
|
||||
void att_clear_transaction_queue(att_connection_t * att_connection){
|
||||
if (!att_write_callback) return;
|
||||
(*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0);
|
||||
att_notify_write_callbacks(att_connection, ATT_TRANSACTION_MODE_CANCEL);
|
||||
}
|
||||
|
||||
// MARK: ATT_EXECUTE_WRITE_REQUEST 0x18
|
||||
@ -938,10 +982,6 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
|
||||
uint8_t request_type = ATT_EXECUTE_WRITE_REQUEST;
|
||||
|
||||
if (!att_write_callback) {
|
||||
return setup_error_write_not_permitted(response_buffer, request_type, 0);
|
||||
}
|
||||
if (request_buffer[1]) {
|
||||
// deliver queued errors
|
||||
if (att_prepare_write_error_code){
|
||||
@ -951,7 +991,7 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
|
||||
att_prepare_write_reset();
|
||||
return setup_error(response_buffer, request_type, handle, error_code);
|
||||
}
|
||||
(*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0);
|
||||
att_notify_write_callbacks(att_connection, ATT_TRANSACTION_MODE_EXECUTE);
|
||||
} else {
|
||||
att_clear_transaction_queue(att_connection);
|
||||
}
|
||||
@ -965,15 +1005,17 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
|
||||
static void handle_write_command(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
|
||||
if (!att_write_callback) return;
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) return;
|
||||
|
||||
att_iterator_t it;
|
||||
int ok = att_find_handle(&it, handle);
|
||||
if (!ok) return;
|
||||
if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return;
|
||||
if ((it.flags & ATT_PROPERTY_WRITE_WITHOUT_RESPONSE) == 0) return;
|
||||
if (att_validate_security(att_connection, &it)) return;
|
||||
(*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
(*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
}
|
||||
|
||||
// MARK: helper for ATT_HANDLE_VALUE_NOTIFICATION and ATT_HANDLE_VALUE_INDICATION
|
||||
@ -1068,42 +1110,91 @@ uint16_t att_handle_request(att_connection_t * att_connection,
|
||||
return response_len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_register_service_handler(att_service_handler_t * handler){
|
||||
if (att_service_handler_for_handle(handler->start_handle) ||
|
||||
att_service_handler_for_handle(handler->end_handle)){
|
||||
log_error("att_register_service_handler: handler for range 0x%04x-0x%04x already registered", handler->start_handle, handler->end_handle);
|
||||
return;
|
||||
}
|
||||
btstack_linked_list_add(&service_handlers, (btstack_linked_item_t*) handler);
|
||||
}
|
||||
|
||||
// test profile
|
||||
#include "profile.h"
|
||||
// returns 1 if service found. only primary service.
|
||||
int gatt_server_get_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle){
|
||||
uint16_t in_group = 0;
|
||||
uint16_t prev_handle = 0;
|
||||
|
||||
int main(void){
|
||||
int acl_buffer_size;
|
||||
uint8_t acl_buffer[27];
|
||||
att_set_db(profile_data);
|
||||
att_dump_attributes();
|
||||
uint8_t attribute_value[2];
|
||||
int attribute_len = sizeof(attribute_value);
|
||||
little_endian_store_16(attribute_value, 0, uuid16);
|
||||
|
||||
uint8_t uuid_1[] = { 0x00, 0x18};
|
||||
acl_buffer_size = handle_find_by_type_value_request2(acl_buffer, 19, 0, 0xffff, 0x2800, 2, (uint8_t *) &uuid_1);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
|
||||
uint8_t uuid_3[] = { 0x00, 0x2a};
|
||||
acl_buffer_size = handle_read_by_type_request2(acl_buffer, 19, 0, 0xffff, 2, (uint8_t *) &uuid_3);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
att_iterator_t it;
|
||||
att_iterator_init(&it);
|
||||
while (att_iterator_has_next(&it)){
|
||||
att_iterator_fetch_next(&it);
|
||||
int new_service_started = att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID);
|
||||
|
||||
// close current tag, if within a group and a new service definition starts or we reach end of att db
|
||||
if (in_group &&
|
||||
(it.handle == 0 || new_service_started)){
|
||||
*end_handle = prev_handle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
acl_buffer_size = handle_find_by_type_value_request2(acl_buffer, 19, 0, 0xffff, 0x2800, 2, (uint8_t *) &uuid_1);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
|
||||
uint8_t uuid_4[] = { 0x00, 0x28};
|
||||
acl_buffer_size = handle_read_by_group_type_request2(acl_buffer, 20, 0, 0xffff, 2, (uint8_t *) &uuid_4);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
|
||||
acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 0, 0xffff);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 3, 0xffff);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 5, 0xffff);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
|
||||
acl_buffer_size = handle_read_request2(acl_buffer, 19, 0x0003);
|
||||
log_info_hexdump(acl_buffer, acl_buffer_size);
|
||||
|
||||
// keep track of previous handle
|
||||
prev_handle = it.handle;
|
||||
|
||||
// check if found
|
||||
if (it.handle && new_service_started && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){
|
||||
*start_handle = it.handle;
|
||||
in_group = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// returns 0 if not found
|
||||
uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){
|
||||
att_iterator_t it;
|
||||
att_iterator_init(&it);
|
||||
while (att_iterator_has_next(&it)){
|
||||
att_iterator_fetch_next(&it);
|
||||
if (it.handle && it.handle < start_handle) continue;
|
||||
if (it.handle > end_handle) break; // (1)
|
||||
if (it.handle == 0) break;
|
||||
if (att_iterator_match_uuid16(&it, uuid16)) return it.handle;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns 0 if not found
|
||||
uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){
|
||||
att_iterator_t it;
|
||||
att_iterator_init(&it);
|
||||
int characteristic_found = 0;
|
||||
while (att_iterator_has_next(&it)){
|
||||
att_iterator_fetch_next(&it);
|
||||
if (it.handle && it.handle < start_handle) continue;
|
||||
if (it.handle > end_handle) break; // (1)
|
||||
if (it.handle == 0) break;
|
||||
if (att_iterator_match_uuid16(&it, uuid16)){
|
||||
characteristic_found = 1;
|
||||
continue;
|
||||
}
|
||||
if (att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID)
|
||||
|| att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID)
|
||||
|| att_iterator_match_uuid16(&it, GATT_CHARACTERISTICS_UUID)){
|
||||
if (characteristic_found) break;
|
||||
continue;
|
||||
}
|
||||
if (att_iterator_match_uuid16(&it, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION)){
|
||||
return it.handle;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bluetooth.h"
|
||||
|
||||
#include "btstack_linked_list.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -49,7 +50,7 @@ extern "C" {
|
||||
// custom BTstack error codes
|
||||
#define ATT_ERROR_HCI_DISCONNECT_RECEIVED 0x1f
|
||||
|
||||
// custom BTstack ATT error coders
|
||||
// custom BTstack ATT error codes
|
||||
#define ATT_ERROR_DATA_MISMATCH 0x7e
|
||||
#define ATT_ERROR_TIMEOUT 0x7F
|
||||
|
||||
@ -83,6 +84,16 @@ typedef uint16_t (*att_read_callback_t)(hci_con_handle_t con_handle, uint16_t at
|
||||
// @returns 0 if write was ok, ATT_ERROR_PREPARE_QUEUE_FULL if no space in queue, ATT_ERROR_INVALID_OFFSET if offset is larger than max buffer
|
||||
typedef int (*att_write_callback_t)(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
|
||||
|
||||
|
||||
// Read & Write Callbacks for handle range
|
||||
typedef struct att_service_handler {
|
||||
btstack_linked_item_t * item;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
att_read_callback_t read_callback;
|
||||
att_write_callback_t write_callback;
|
||||
} att_service_handler_t;
|
||||
|
||||
// MARK: ATT Operations
|
||||
|
||||
/*
|
||||
@ -152,9 +163,28 @@ uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection,
|
||||
*/
|
||||
void att_clear_transaction_queue(att_connection_t * att_connection);
|
||||
|
||||
// experimental client API
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_register_service_handler(att_service_handler_t * handler);
|
||||
|
||||
|
||||
// experimental client API
|
||||
uint16_t att_uuid_for_handle(uint16_t attribute_handle);
|
||||
|
||||
|
||||
// experimental GATT Server API
|
||||
|
||||
// returns 1 if service found. only primary service.
|
||||
int gatt_server_get_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle);
|
||||
|
||||
// returns 0 if not found
|
||||
uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16);
|
||||
|
||||
// returns 0 if not found
|
||||
uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -87,11 +87,12 @@ static int att_db_util_assert_space(uint16_t size){
|
||||
if (att_db_size + size <= att_db_max_size) return 1;
|
||||
#ifdef HAVE_MALLOC
|
||||
int new_size = att_db_size + att_db_size / 2;
|
||||
att_db = (uint8_t*) realloc(att_db, new_size);
|
||||
if (!att_db) {
|
||||
uint8_t * new_db = (uint8_t*) realloc(att_db, new_size);
|
||||
if (!new_db) {
|
||||
log_error("att_db: realloc failed");
|
||||
return 0;
|
||||
}
|
||||
att_db = new_db;
|
||||
att_db_max_size = new_size;
|
||||
return 1;
|
||||
#else
|
||||
|
@ -64,6 +64,7 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
|
||||
if (!att_server_handler) return;
|
||||
att_server_handler(packet_type, handle, packet, size);
|
||||
}
|
||||
break;
|
||||
case HCI_EVENT_PACKET:
|
||||
if (packet[0] != L2CAP_EVENT_CAN_SEND_NOW) break;
|
||||
if (att_server_handler && att_server_waiting_for_can_send){
|
||||
|
@ -95,6 +95,8 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static btstack_packet_callback_registration_t sm_event_callback_registration;
|
||||
static btstack_packet_handler_t att_client_packet_handler = NULL;
|
||||
|
||||
static btstack_linked_list_t can_send_now_clients;
|
||||
|
||||
static void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){
|
||||
if (!att_client_packet_handler) return;
|
||||
|
||||
@ -345,12 +347,27 @@ static void att_server_handle_can_send_now(void){
|
||||
|
||||
if (att_server_state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED){
|
||||
int sent = att_server_process_validated_request(att_connection.con_handle);
|
||||
if (sent && att_client_waiting_for_can_send){
|
||||
if (sent && (att_client_waiting_for_can_send || !btstack_linked_list_empty(&can_send_now_clients))){
|
||||
att_dispatch_server_request_can_send_now_event(att_connection.con_handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (!btstack_linked_list_empty(&can_send_now_clients)){
|
||||
// handle first client
|
||||
btstack_context_callback_registration_t * client = (btstack_context_callback_registration_t*) can_send_now_clients;
|
||||
btstack_linked_list_remove(&can_send_now_clients, (btstack_linked_item_t *) client);
|
||||
client->callback(client->context);
|
||||
|
||||
// request again if needed
|
||||
if (!att_dispatch_server_can_send_now(att_connection.con_handle)){
|
||||
if (!btstack_linked_list_empty(&can_send_now_clients) || att_client_waiting_for_can_send){
|
||||
att_dispatch_server_request_can_send_now_event(att_connection.con_handle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (att_client_waiting_for_can_send){
|
||||
att_client_waiting_for_can_send = 0;
|
||||
att_emit_can_send_now_event();
|
||||
@ -441,6 +458,16 @@ void att_server_request_can_send_now_event(hci_con_handle_t con_handle){
|
||||
att_dispatch_server_request_can_send_now_event(att_connection.con_handle);
|
||||
}
|
||||
|
||||
void att_server_register_can_send_now_callback(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
|
||||
// check if can send already
|
||||
if (att_dispatch_server_can_send_now(con_handle)){
|
||||
callback_registration->callback(callback_registration->context);
|
||||
return;
|
||||
}
|
||||
btstack_linked_list_add_tail(&can_send_now_clients, (btstack_linked_item_t*) callback_registration);
|
||||
att_dispatch_server_request_can_send_now_event(con_handle);
|
||||
}
|
||||
|
||||
int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t *value, uint16_t value_len){
|
||||
if (!att_dispatch_server_can_send_now(att_connection.con_handle)) return BTSTACK_ACL_BUFFERS_FULL;
|
||||
|
||||
|
@ -56,8 +56,9 @@ void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_
|
||||
|
||||
/*
|
||||
* @brief register packet handler for ATT server events:
|
||||
* - ATT_EVENT_MTU_EXCHANGE_COMPLETE
|
||||
* - ATT_EVENT_CAN_SEND_NOW
|
||||
* - ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE
|
||||
* - ATT_EVENT_MTU_EXCHANGE_COMPLETE
|
||||
* @param handler
|
||||
*/
|
||||
void att_server_register_packet_handler(btstack_packet_handler_t handler);
|
||||
@ -77,6 +78,14 @@ int att_server_can_send_packet_now(hci_con_handle_t con_handle);
|
||||
*/
|
||||
void att_server_request_can_send_now_event(hci_con_handle_t con_handle);
|
||||
|
||||
/**
|
||||
* @brief Request callback when sending is possible
|
||||
* @note callback might happend during call to this function
|
||||
* @param callback_registration to point to callback function and context information
|
||||
* @param con_handle
|
||||
*/
|
||||
void att_server_register_can_send_now_callback(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle);
|
||||
|
||||
/*
|
||||
* @brief notify client about attribute value change
|
||||
* @param con_handle
|
||||
|
6
src/ble/gatt-service/battery_service.gatt
Normal file
6
src/ble/gatt-service/battery_service.gatt
Normal file
@ -0,0 +1,6 @@
|
||||
// Specification Type org.bluetooth.service.battery_service
|
||||
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml
|
||||
|
||||
// Battery Service 180F
|
||||
PRIMARY_SERVICE, ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, DYNAMIC | READ | NOTIFY,
|
120
src/ble/gatt-service/battery_service_server.c
Normal file
120
src/ble/gatt-service/battery_service_server.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of the GATT Battery Service Server
|
||||
* To use with your application, add '#import <battery_service.gatt' to your .gatt file
|
||||
*/
|
||||
|
||||
#include "btstack_defines.h"
|
||||
#include "ble/att_db.h"
|
||||
#include "ble/att_server.h"
|
||||
#include "btstack_util.h"
|
||||
#include "bluetooth_gatt.h"
|
||||
|
||||
#include "ble/gatt-service/battery_service_server.h"
|
||||
|
||||
static btstack_context_callback_registration_t battery_callback;
|
||||
static att_service_handler_t battery_service;
|
||||
|
||||
static uint8_t battery_value;
|
||||
static uint16_t battery_value_client_configuration;
|
||||
static hci_con_handle_t battery_value_client_configuration_connection;
|
||||
|
||||
static uint16_t battery_value_handle_value;
|
||||
static uint16_t battery_value_handle_client_configuration;
|
||||
|
||||
|
||||
static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
|
||||
if (attribute_handle == battery_value_handle_value){
|
||||
if (buffer) {
|
||||
buffer[0] = battery_value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (attribute_handle == battery_value_handle_client_configuration){
|
||||
if (buffer){
|
||||
little_endian_store_16(buffer, 0, battery_value_client_configuration);
|
||||
battery_value_client_configuration_connection = con_handle;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int battery_service_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
if (attribute_handle == battery_value_handle_client_configuration){
|
||||
battery_value_client_configuration = little_endian_read_16(buffer, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void battery_service_can_send_now(void * context){
|
||||
hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) context;
|
||||
att_server_notify(con_handle, battery_value_handle_value, &battery_value, 1);
|
||||
}
|
||||
|
||||
void battery_service_server_init(uint8_t value){
|
||||
|
||||
battery_value = value;
|
||||
|
||||
// get service handle range
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
int service_found = gatt_server_get_get_handle_range_for_service_with_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE, &start_handle, &end_handle);
|
||||
if (!service_found) return;
|
||||
|
||||
// get characteristic value handle and client configuration handle
|
||||
battery_value_handle_value = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
|
||||
battery_value_handle_client_configuration = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
|
||||
|
||||
// register service with ATT DB
|
||||
battery_service.start_handle = start_handle;
|
||||
battery_service.end_handle = end_handle;
|
||||
battery_service.read_callback = &battery_service_read_callback;
|
||||
battery_service.write_callback = &battery_service_write_callback;
|
||||
att_register_service_handler(&battery_service);
|
||||
}
|
||||
|
||||
void battery_service_server_set_battery_value(uint8_t value){
|
||||
battery_value = value;
|
||||
if (battery_value_client_configuration){
|
||||
battery_callback.callback = &battery_service_can_send_now;
|
||||
battery_callback.context = NULL;
|
||||
att_server_register_can_send_now_callback(&battery_callback, battery_value_client_configuration_connection);
|
||||
}
|
||||
}
|
73
src/ble/gatt-service/battery_service_server.h
Normal file
73
src/ble/gatt-service/battery_service_server.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
#ifndef __BATTERY_SERVICE_SERVER_H
|
||||
#define __BATTERY_SERVICE_SERVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implementation of the GATT Battery Service Server
|
||||
* To use with your application, add '#import <battery_service.gatt' to your .gatt file
|
||||
*/
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief Init Battery Service Server with ATT DB
|
||||
* @param battery_value in range 0-100
|
||||
*/
|
||||
void battery_service_server_init(uint8_t battery_value);
|
||||
|
||||
/**
|
||||
* @brief Update battery value
|
||||
* @note triggers notifications if subscribed
|
||||
* @param battery_value in range 0-100
|
||||
*/
|
||||
void battery_service_server_set_battery_value(uint8_t battery_value);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
14
src/ble/gatt-service/device_information_service.gatt
Normal file
14
src/ble/gatt-service/device_information_service.gatt
Normal file
@ -0,0 +1,14 @@
|
||||
// Specification Type org.bluetooth.service.device_information
|
||||
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.device_information.xml
|
||||
|
||||
// Device Information 180A
|
||||
PRIMARY_SERVICE, ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST, DYNAMIC | READ,
|
||||
CHARACTERISTIC, ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID, DYNAMIC | READ,
|
227
src/ble/gatt-service/device_information_service_server.c
Normal file
227
src/ble/gatt-service/device_information_service_server.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of the Device Information Service Server
|
||||
*
|
||||
* To use with your application, add '#import <device_information_sevice.gatt' to your .gatt file
|
||||
* and call all functions below. All strings and blobs need to stay valid after calling the functions.
|
||||
*
|
||||
* @note: instead of calling all setters, you can create a local copy of the .gatt file and remove
|
||||
* all Characteristics that are not relevant for your application.
|
||||
*/
|
||||
|
||||
|
||||
#include "btstack_defines.h"
|
||||
#include "ble/att_db.h"
|
||||
#include "ble/att_server.h"
|
||||
#include "btstack_util.h"
|
||||
#include "bluetooth_gatt.h"
|
||||
|
||||
#include "ble/gatt-service/device_information_service_server.h"
|
||||
|
||||
typedef enum {
|
||||
MANUFACTURER_NAME = 0,
|
||||
MODEL_NUMBER,
|
||||
SERIAL_NUMBER,
|
||||
HARDWARE_REVISION,
|
||||
FIRMWARE_REVISION,
|
||||
SOFTWARE_REVISION,
|
||||
SYSTEM_ID,
|
||||
IEEE_REGULATORY_CERTIFICATION,
|
||||
PNP_ID,
|
||||
NUM_INFORMATION_FIELDS
|
||||
} device_information_field_id_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t * data;
|
||||
uint16_t len;
|
||||
uint16_t value_handle;
|
||||
} device_information_field_t;
|
||||
|
||||
const uint16_t device_information_characteristic_uuids[] = {
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST,
|
||||
ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID
|
||||
};
|
||||
|
||||
static device_information_field_t device_information_fields[NUM_INFORMATION_FIELDS];
|
||||
|
||||
static uint8_t device_information_system_id[8];
|
||||
static uint8_t device_information_ieee_regulatory_certification[4];
|
||||
static uint8_t device_information_pnp_id[7];
|
||||
|
||||
static att_service_handler_t device_information_service;
|
||||
|
||||
static void set_string(device_information_field_id_t field_id, const char * text){
|
||||
device_information_fields[field_id].data = (uint8_t*) text;
|
||||
device_information_fields[field_id].len = strlen(text);
|
||||
}
|
||||
|
||||
static uint16_t device_information_service_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
|
||||
int i;
|
||||
for (i=0;i<NUM_INFORMATION_FIELDS;i++){
|
||||
if (device_information_fields[i].value_handle != attribute_handle) continue;
|
||||
if (buffer == 0){
|
||||
return device_information_fields[i].len;
|
||||
}
|
||||
int bytes_to_copy = btstack_min(device_information_fields[i].len - offset, buffer_size);
|
||||
memcpy(buffer, &device_information_fields[i].data[offset], bytes_to_copy);
|
||||
return bytes_to_copy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void device_information_service_server_init(void){
|
||||
|
||||
// get service handle range
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
int service_found = gatt_server_get_get_handle_range_for_service_with_uuid16(ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION, &start_handle, &end_handle);
|
||||
if (!service_found) return;
|
||||
|
||||
// get characteristic value handles
|
||||
int i;
|
||||
for (i=0;i<NUM_INFORMATION_FIELDS;i++){
|
||||
device_information_fields[i].value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, device_information_characteristic_uuids[i]);
|
||||
}
|
||||
|
||||
// register service with ATT DB
|
||||
device_information_service.start_handle = start_handle;
|
||||
device_information_service.end_handle = end_handle;
|
||||
device_information_service.read_callback = &device_information_service_read_callback;
|
||||
device_information_service.write_callback = NULL;
|
||||
att_register_service_handler(&device_information_service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Manufacturer Name
|
||||
* @param manufacturer_name
|
||||
*/
|
||||
void device_information_service_server_set_manufacturer_name(const char * manufacturer_name){
|
||||
set_string(MANUFACTURER_NAME, manufacturer_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Model Number
|
||||
* @param model_number
|
||||
*/
|
||||
void device_information_service_server_set_model_number(const char * model_number){
|
||||
set_string(MODEL_NUMBER, model_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Serial Number
|
||||
* @param serial_number
|
||||
*/
|
||||
void device_information_service_server_set_serial_number(const char * serial_number){
|
||||
set_string(SERIAL_NUMBER, serial_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Hardware Revision
|
||||
* @param hardware_revision
|
||||
*/
|
||||
void device_information_service_server_set_hardware_revision(const char * hardware_revision){
|
||||
set_string(HARDWARE_REVISION, hardware_revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Firmware Revision
|
||||
* @param firmware_revision
|
||||
*/
|
||||
void device_information_service_server_set_firmware_revision(const char * firmware_revision){
|
||||
set_string(FIRMWARE_REVISION, firmware_revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Software Revision
|
||||
* @param software_revision
|
||||
*/
|
||||
void device_information_service_server_set_software_revision(const char * software_revision){
|
||||
set_string(SOFTWARE_REVISION, software_revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set System ID
|
||||
* @param manufacturer_identifier uint40
|
||||
* @param organizationally_unique_identifier uint24
|
||||
*/
|
||||
void device_information_service_server_set_system_id(uint64_t manufacturer_identifier, uint32_t organizationally_unique_identifier){
|
||||
device_information_fields[SYSTEM_ID].data = device_information_system_id;
|
||||
device_information_fields[SYSTEM_ID].len = 8;
|
||||
|
||||
little_endian_store_32(device_information_system_id, 0, manufacturer_identifier);
|
||||
device_information_system_id[4] = manufacturer_identifier >> 32;
|
||||
little_endian_store_16(device_information_system_id, 5, organizationally_unique_identifier);
|
||||
device_information_system_id[7] = organizationally_unique_identifier >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set IEEE 11073-20601 regulatory certification data list
|
||||
* @note: format duint16. duint16 is two uint16 values concatenated together.
|
||||
* @param ieee_regulatory_certification
|
||||
*/
|
||||
void device_information_service_server_set_ieee_regulatory_certification(uint16_t value_a, uint16_t value_b){
|
||||
device_information_fields[IEEE_REGULATORY_CERTIFICATION].data = device_information_ieee_regulatory_certification;
|
||||
device_information_fields[IEEE_REGULATORY_CERTIFICATION].len = 4;
|
||||
|
||||
little_endian_store_16(device_information_ieee_regulatory_certification, 0, value_a);
|
||||
little_endian_store_16(device_information_ieee_regulatory_certification, 2, value_b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PNP ID
|
||||
* @param vendor_source_id
|
||||
* @param vendor_id
|
||||
* @param product_id
|
||||
*/
|
||||
void device_information_service_server_set_pnp_id(uint8_t vendor_source_id, uint16_t vendor_id, uint16_t product_id, uint16_t product_version){
|
||||
device_information_fields[PNP_ID].data = device_information_pnp_id;
|
||||
device_information_fields[PNP_ID].len = 7;
|
||||
|
||||
device_information_pnp_id[0] = vendor_source_id;
|
||||
little_endian_store_16(device_information_pnp_id, 1, vendor_source_id);
|
||||
little_endian_store_16(device_information_pnp_id, 3, vendor_id);
|
||||
little_endian_store_16(device_information_pnp_id, 5, product_id);
|
||||
}
|
130
src/ble/gatt-service/device_information_service_server.h
Normal file
130
src/ble/gatt-service/device_information_service_server.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
#ifndef __DEVICE_INFORMATION_SERVICE_SERVER_H
|
||||
#define __DEVICE_INFORMATION_SERVICE_SERVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* Implementation of the Device Information Service Server
|
||||
*
|
||||
* To use with your application, add '#import <device_information_sevice.gatt' to your .gatt file
|
||||
* and call all functions below. All strings and blobs need to stay valid after calling the functions.
|
||||
*
|
||||
* @note: instead of calling all setters, you can create a local copy of the .gatt file and remove
|
||||
* all Characteristics that are not relevant for your application and define all fixed values in the .gatt file
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Init Device Information Service Server with ATT DB
|
||||
* @param battery_value in range 0-100
|
||||
*/
|
||||
void device_information_service_server_init(void);
|
||||
|
||||
/**
|
||||
* @brief Set Manufacturer Name
|
||||
* @param manufacturer_name
|
||||
*/
|
||||
void device_information_service_server_set_manufacturer_name(const char * manufacturer_name);
|
||||
|
||||
/**
|
||||
* @brief Set Model Number
|
||||
* @param model_number
|
||||
*/
|
||||
void device_information_service_server_set_model_number(const char * model_number);
|
||||
|
||||
/**
|
||||
* @brief Set Serial Number
|
||||
* @param serial_number
|
||||
*/
|
||||
void device_information_service_server_set_serial_number(const char * serial_number);
|
||||
|
||||
/**
|
||||
* @brief Set Hardware Revision
|
||||
* @param hardware_revision
|
||||
*/
|
||||
void device_information_service_server_set_hardware_revision(const char * hardware_revision);
|
||||
|
||||
/**
|
||||
* @brief Set Firmware Revision
|
||||
* @param firmware_revision
|
||||
*/
|
||||
void device_information_service_server_set_firmware_revision(const char * firmware_revision);
|
||||
|
||||
/**
|
||||
* @brief Set Software Revision
|
||||
* @param software_revision
|
||||
*/
|
||||
void device_information_service_server_set_software_revision(const char * software_revision);
|
||||
|
||||
/**
|
||||
* @brief Set System ID
|
||||
* @param manufacturer_identifier uint40
|
||||
* @param organizationally_unique_identifier uint24
|
||||
*/
|
||||
void device_information_service_server_set_system_id(uint64_t manufacturer_identifier, uint32_t organizationally_unique_identifier);
|
||||
|
||||
/**
|
||||
* @brief Set IEEE 11073-20601 regulatory certification data list
|
||||
* @note: format duint16. duint16 is two uint16 values concatenated together.
|
||||
* @param value_a
|
||||
* @param value_b
|
||||
*/
|
||||
void device_information_service_server_set_ieee_regulatory_certification(uint16_t value_a, uint16_t value_b);
|
||||
|
||||
/**
|
||||
* @brief Set Software Revision
|
||||
* @param vendor_source_id
|
||||
* @param vendor_id
|
||||
* @param product_id
|
||||
*/
|
||||
void device_information_service_server_set_pnp_id(uint8_t vendor_source_id, uint16_t vendor_id, uint16_t product_id, uint16_t product_version);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
121
src/ble/sm.c
121
src/ble/sm.c
@ -48,6 +48,7 @@
|
||||
#include "btstack_memory.h"
|
||||
#include "gap.h"
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
@ -136,6 +137,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
EC_KEY_GENERATION_IDLE,
|
||||
EC_KEY_GENERATION_ACTIVE,
|
||||
EC_KEY_GENERATION_W4_KEY,
|
||||
EC_KEY_GENERATION_DONE,
|
||||
} ec_key_generation_state_t;
|
||||
|
||||
@ -221,15 +223,18 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
/* to dispatch sm event */
|
||||
static btstack_linked_list_t sm_event_handlers;
|
||||
|
||||
// LE Secure Connections
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
static ec_key_generation_state_t ec_key_generation_state;
|
||||
static uint8_t ec_d[32];
|
||||
static uint8_t ec_qx[32];
|
||||
static uint8_t ec_qy[32];
|
||||
#endif
|
||||
|
||||
// Software ECDH implementation provided by mbedtls
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
// group is always valid
|
||||
static mbedtls_ecp_group mbedtls_ec_group;
|
||||
static ec_key_generation_state_t ec_key_generation_state;
|
||||
static uint8_t ec_qx[32];
|
||||
static uint8_t ec_qy[32];
|
||||
static uint8_t ec_d[32];
|
||||
#ifndef HAVE_MALLOC
|
||||
// COMP Method with Window 2
|
||||
// 1300 bytes with 23 allocations
|
||||
@ -485,7 +490,7 @@ static void sm_aes128_start(sm_key_t key, sm_key_t plaintext, void * context){
|
||||
// ah(k,r) helper
|
||||
// r = padding || r
|
||||
// r - 24 bit value
|
||||
static void sm_ah_r_prime(uint8_t r[3], sm_key_t r_prime){
|
||||
static void sm_ah_r_prime(uint8_t r[3], uint8_t * r_prime){
|
||||
// r'= padding || r
|
||||
memset(r_prime, 0, 16);
|
||||
memcpy(&r_prime[13], r, 3);
|
||||
@ -494,7 +499,7 @@ static void sm_ah_r_prime(uint8_t r[3], sm_key_t r_prime){
|
||||
// d1 helper
|
||||
// d' = padding || r || d
|
||||
// d,r - 16 bit values
|
||||
static void sm_d1_d_prime(uint16_t d, uint16_t r, sm_key_t d1_prime){
|
||||
static void sm_d1_d_prime(uint16_t d, uint16_t r, uint8_t * d1_prime){
|
||||
// d'= padding || r || d
|
||||
memset(d1_prime, 0, 16);
|
||||
big_endian_store_16(d1_prime, 12, r);
|
||||
@ -504,13 +509,13 @@ static void sm_d1_d_prime(uint16_t d, uint16_t r, sm_key_t d1_prime){
|
||||
// dm helper
|
||||
// r’ = padding || r
|
||||
// r - 64 bit value
|
||||
static void sm_dm_r_prime(uint8_t r[8], sm_key_t r_prime){
|
||||
static void sm_dm_r_prime(uint8_t r[8], uint8_t * r_prime){
|
||||
memset(r_prime, 0, 16);
|
||||
memcpy(&r_prime[8], r, 8);
|
||||
}
|
||||
|
||||
// calculate arguments for first AES128 operation in C1 function
|
||||
static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat, uint8_t rat, sm_key_t t1){
|
||||
static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat, uint8_t rat, uint8_t * t1){
|
||||
|
||||
// p1 = pres || preq || rat’ || iat’
|
||||
// "The octet of iat’ becomes the least significant octet of p1 and the most signifi-
|
||||
@ -536,7 +541,7 @@ static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat,
|
||||
}
|
||||
|
||||
// calculate arguments for second AES128 operation in C1 function
|
||||
static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, sm_key_t t3){
|
||||
static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, uint8_t * t3){
|
||||
// p2 = padding || ia || ra
|
||||
// "The least significant octet of ra becomes the least significant octet of p2 and
|
||||
// the most significant octet of padding becomes the most significant octet of p2.
|
||||
@ -557,7 +562,7 @@ static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, sm_key_t t3){
|
||||
log_info_key("t3", t3);
|
||||
}
|
||||
|
||||
static void sm_s1_r_prime(sm_key_t r1, sm_key_t r2, sm_key_t r_prime){
|
||||
static void sm_s1_r_prime(sm_key_t r1, sm_key_t r2, uint8_t * r_prime){
|
||||
log_info_key("r1", r1);
|
||||
log_info_key("r2", r2);
|
||||
memcpy(&r_prime[8], &r2[8], 8);
|
||||
@ -662,6 +667,8 @@ static void sm_setup_event_base(uint8_t * event, int event_size, uint8_t type, h
|
||||
}
|
||||
|
||||
static void sm_dispatch_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
|
||||
// log event
|
||||
hci_dump_packet(packet_type, 1, packet, size);
|
||||
// dispatch to all event handlers
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &sm_event_handlers);
|
||||
@ -685,9 +692,15 @@ static void sm_notify_client_passkey(uint8_t type, hci_con_handle_t con_handle,
|
||||
}
|
||||
|
||||
static void sm_notify_client_index(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address, uint16_t index){
|
||||
uint8_t event[13];
|
||||
// fetch addr and addr type from db
|
||||
bd_addr_t identity_address;
|
||||
int identity_address_type;
|
||||
le_device_db_info(index, &identity_address_type, identity_address, NULL);
|
||||
|
||||
uint8_t event[18];
|
||||
sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
|
||||
little_endian_store_16(event, 11, index);
|
||||
event[11] = identity_address_type;
|
||||
reverse_bd_addr(identity_address, &event[12]);
|
||||
sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
@ -1267,6 +1280,8 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
|
||||
le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
|
||||
}
|
||||
|
||||
sm_notify_client_index(SM_EVENT_IDENTITY_CREATED, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address, le_db_index);
|
||||
|
||||
if (le_db_index >= 0){
|
||||
|
||||
// store local CSRK
|
||||
@ -1322,8 +1337,6 @@ static int sm_passkey_used(stk_generation_method_t method);
|
||||
static int sm_just_works_or_numeric_comparison(stk_generation_method_t method);
|
||||
|
||||
static void sm_log_ec_keypair(void){
|
||||
log_info("Elliptic curve: d");
|
||||
log_info_hexdump(ec_d,32);
|
||||
log_info("Elliptic curve: X");
|
||||
log_info_hexdump(ec_qx,32);
|
||||
log_info("Elliptic curve: Y");
|
||||
@ -1453,10 +1466,14 @@ static void sm_sc_cmac_done(uint8_t * hash){
|
||||
link_key_type = sm_conn->sm_connection_authenticated ?
|
||||
AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256 : UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
|
||||
if (sm_conn->sm_role){
|
||||
#ifdef ENABLE_CLASSIC
|
||||
gap_store_link_key_for_bd_addr(setup->sm_m_address, setup->sm_t, link_key_type);
|
||||
#endif
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
|
||||
} else {
|
||||
#ifdef ENABLE_CLASSIC
|
||||
gap_store_link_key_for_bd_addr(setup->sm_s_address, setup->sm_t, link_key_type);
|
||||
#endif
|
||||
sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
|
||||
}
|
||||
sm_done_for_handle(sm_conn->sm_handle);
|
||||
@ -1798,9 +1815,14 @@ static void sm_run(void){
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
if (ec_key_generation_state == EC_KEY_GENERATION_ACTIVE){
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
sm_random_start(NULL);
|
||||
#else
|
||||
ec_key_generation_state = EC_KEY_GENERATION_W4_KEY;
|
||||
hci_send_cmd(&hci_le_read_local_p256_public_key);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -2728,6 +2750,8 @@ static void sm_handle_random_result(uint8_t * data){
|
||||
mbedtls_ecp_point_free(&P);
|
||||
mbedtls_mpi_free(&d);
|
||||
ec_key_generation_state = EC_KEY_GENERATION_DONE;
|
||||
log_info("Elliptic curve: d");
|
||||
log_info_hexdump(ec_d,32);
|
||||
sm_log_ec_keypair();
|
||||
|
||||
#if 0
|
||||
@ -2866,13 +2890,24 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
le_device_db_set_local_bd_addr(local_bd_addr);
|
||||
|
||||
dkg_state = sm_persistent_irk_ready ? DKG_CALC_DHK : DKG_CALC_IRK;
|
||||
rau_state = RAU_IDLE;
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
if (!sm_have_ec_keypair){
|
||||
setup->sm_passkey_bit = 0;
|
||||
ec_key_generation_state = EC_KEY_GENERATION_ACTIVE;
|
||||
}
|
||||
#endif
|
||||
// trigger Random Address generation if requested before
|
||||
switch (gap_random_adress_type){
|
||||
case GAP_RANDOM_ADDRESS_TYPE_OFF:
|
||||
rau_state = RAU_IDLE;
|
||||
break;
|
||||
case GAP_RANDOM_ADDRESS_TYPE_STATIC:
|
||||
rau_state = RAU_SET_ADDRESS;
|
||||
break;
|
||||
default:
|
||||
rau_state = RAU_GET_RANDOM;
|
||||
break;
|
||||
}
|
||||
sm_run();
|
||||
}
|
||||
break;
|
||||
@ -2892,8 +2927,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_conn->sm_handle = con_handle;
|
||||
sm_conn->sm_role = packet[6];
|
||||
sm_conn->sm_peer_addr_type = packet[7];
|
||||
reverse_bd_addr(&packet[8],
|
||||
sm_conn->sm_peer_address);
|
||||
reverse_bd_addr(&packet[8], sm_conn->sm_peer_address);
|
||||
|
||||
log_info("New sm_conn, role %s", sm_conn->sm_role ? "slave" : "master");
|
||||
|
||||
@ -2960,6 +2994,18 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
case HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE:
|
||||
if (hci_subevent_le_read_local_p256_public_key_complete_get_status(packet)){
|
||||
log_error("Read Local P256 Public Key failed");
|
||||
break;
|
||||
}
|
||||
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(packet, ec_qx);
|
||||
hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(packet, ec_qy);
|
||||
ec_key_generation_state = EC_KEY_GENERATION_DONE;
|
||||
sm_log_ec_keypair();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3059,6 +3105,17 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_handle_random_result(&packet[6]);
|
||||
break;
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_bd_addr)){
|
||||
// Hack for Nordic nRF5 series that doesn't have public address:
|
||||
// - with patches from port/nrf5-zephyr, hci_read_bd_addr returns random static address
|
||||
// - we use this as default for advertisements/connections
|
||||
if (hci_get_manufacturer() == COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA){
|
||||
log_info("nRF5: using (fake) public address as random static address");
|
||||
bd_addr_t addr;
|
||||
reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1], addr);
|
||||
gap_random_address_set(addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -3576,7 +3633,6 @@ void sm_init(void){
|
||||
sm_address_resolution_general_queue = NULL;
|
||||
|
||||
gap_random_adress_update_period = 15 * 60 * 1000L;
|
||||
|
||||
sm_active_connection = 0;
|
||||
|
||||
test_use_fixed_local_csrk = 0;
|
||||
@ -3588,8 +3644,11 @@ void sm_init(void){
|
||||
// and L2CAP PDUs + L2CAP_EVENT_CAN_SEND_NOW
|
||||
l2cap_register_fixed_channel(sm_pdu_handler, L2CAP_CID_SECURITY_MANAGER_PROTOCOL);
|
||||
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
ec_key_generation_state = EC_KEY_GENERATION_IDLE;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
|
||||
#ifndef HAVE_MALLOC
|
||||
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
|
||||
@ -3831,11 +3890,22 @@ int sm_le_device_index(hci_con_handle_t con_handle ){
|
||||
return sm_conn->sm_le_db_index;
|
||||
}
|
||||
|
||||
static int gap_random_address_type_requires_updates(void){
|
||||
if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_OFF) return 0;
|
||||
if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_OFF) return 0;
|
||||
return 1;
|
||||
}
|
||||
static uint8_t own_address_type(void){
|
||||
if (gap_random_adress_type == 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// GAP LE API
|
||||
void gap_random_address_set_mode(gap_random_address_type_t random_address_type){
|
||||
gap_random_address_update_stop();
|
||||
gap_random_adress_type = random_address_type;
|
||||
if (random_address_type == GAP_RANDOM_ADDRESS_TYPE_OFF) return;
|
||||
hci_le_advertisements_set_own_address_type(own_address_type());
|
||||
if (!gap_random_address_type_requires_updates()) return;
|
||||
gap_random_address_update_start();
|
||||
gap_random_address_trigger();
|
||||
}
|
||||
@ -3846,14 +3916,15 @@ gap_random_address_type_t gap_random_address_get_mode(void){
|
||||
|
||||
void gap_random_address_set_update_period(int period_ms){
|
||||
gap_random_adress_update_period = period_ms;
|
||||
if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_OFF) return;
|
||||
if (!gap_random_address_type_requires_updates()) return;
|
||||
gap_random_address_update_stop();
|
||||
gap_random_address_update_start();
|
||||
}
|
||||
|
||||
void gap_random_address_set(bd_addr_t addr){
|
||||
gap_random_address_set_mode(GAP_RANDOM_ADDRESS_TYPE_OFF);
|
||||
gap_random_address_set_mode(GAP_RANDOM_ADDRESS_TYPE_STATIC);
|
||||
memcpy(sm_random_address, addr, 6);
|
||||
if (rau_state == RAU_W4_WORKING) return;
|
||||
rau_state = RAU_SET_ADDRESS;
|
||||
sm_run();
|
||||
}
|
||||
@ -3872,7 +3943,7 @@ void gap_random_address_set(bd_addr_t addr){
|
||||
*/
|
||||
void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
|
||||
uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){
|
||||
hci_le_advertisements_set_params(adv_int_min, adv_int_max, adv_type, gap_random_adress_type,
|
||||
hci_le_advertisements_set_params(adv_int_min, adv_int_max, adv_type, own_address_type(),
|
||||
direct_address_typ, direct_address, channel_map, filter_policy);
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,6 @@ int sm_le_device_index(hci_con_handle_t con_handle );
|
||||
|
||||
/**
|
||||
* @brief Set Elliptic Key Public/Private Keypair
|
||||
* @note Creating a new key pair requires about 4600 bytes additional when used with MBEDTLS EC
|
||||
* @note Using the same key for more than one device is not recommended.
|
||||
* @param qx 32 bytes
|
||||
* @param qy 32 bytes
|
||||
|
@ -64,7 +64,7 @@ size_t mbed_memory_allocated_max;
|
||||
size_t mbed_memory_space_max;
|
||||
size_t mbed_memory_max;
|
||||
size_t mbed_memory_smallest_buffer = 0xfffffff;
|
||||
int mbed_memory_num_allocations;
|
||||
unsigned int mbed_memory_num_allocations;
|
||||
|
||||
#define NUM_SIZES 150
|
||||
int current_individual_allocation[NUM_SIZES];
|
||||
@ -94,7 +94,7 @@ static void dump_allocations(void){
|
||||
mbed_memory_allocated_current, overhead, mbed_memory_allocated_current + overhead,
|
||||
mbed_memory_allocated_max);
|
||||
int i;
|
||||
int total = 0;
|
||||
unsigned int total = 0;
|
||||
printf("- current : [ ");
|
||||
for (i=0;i<sizeof(current_individual_allocation) / sizeof(int);i++){
|
||||
printf("%02u ", current_individual_allocation[i]);
|
||||
|
@ -520,6 +520,9 @@ typedef enum {
|
||||
|
||||
#define HCI_EVENT_LE_META 0x3E
|
||||
|
||||
// last used HCI_EVENT in 2.1 is 0x3d
|
||||
// last used HCI_EVENT in 4.1 is 0x57
|
||||
|
||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
/**
|
||||
@ -536,13 +539,96 @@ typedef enum {
|
||||
* @param master_clock_accuracy
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_COMPLETE 0x01
|
||||
|
||||
// array of advertisements, not handled by event accessor generator
|
||||
#define HCI_SUBEVENT_LE_ADVERTISING_REPORT 0x02
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 0x03
|
||||
|
||||
/**
|
||||
* @format 11H222
|
||||
* @param subevent_code
|
||||
* @param status
|
||||
* @param connection_handle
|
||||
* @param conn_interval
|
||||
* @param conn_latency
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 0x03
|
||||
|
||||
/**
|
||||
* @format 1HD2
|
||||
* @param subevent_code
|
||||
* @param connection_handle
|
||||
* @param random_number
|
||||
* @param encryption_diversifier
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04
|
||||
|
||||
/**
|
||||
* @format 1HD2
|
||||
* @param subevent_code
|
||||
* @param connection_handle
|
||||
* @param random_number
|
||||
* @param encryption_diversifier
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST 0x05
|
||||
|
||||
// last used HCI_EVENT in 2.1 is 0x3d
|
||||
// last used HCI_EVENT in 4.1 is 0x57
|
||||
|
||||
/**
|
||||
* @format 1H2222
|
||||
* @param subevent_code
|
||||
* @param connection_handle
|
||||
* @param interval_min
|
||||
* @param interval_max
|
||||
* @param latency
|
||||
* @param timeout
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST 0x06
|
||||
|
||||
/**
|
||||
* @format 1H2222
|
||||
* @param subevent_code
|
||||
* @param connection_handle
|
||||
* @param max_tx_octets
|
||||
* @param max_tx_time
|
||||
* @param max_rx_octets
|
||||
* @param max_rx_time
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE 0x07
|
||||
|
||||
/**
|
||||
* @format 11QQ
|
||||
* @param subevent_code
|
||||
* @param status
|
||||
* @param dhkey_x x coordinate of P256 public key
|
||||
* @param dhkey_y y coordinate of P256 public key
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE 0x08
|
||||
/**
|
||||
* @format 11QQ
|
||||
* @param subevent_code
|
||||
* @param status
|
||||
* @param dhkey_x x coordinate of Diffie-Hellman key
|
||||
* @param dhkey_y y coordinate of Diffie-Hellman key
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE 0x09
|
||||
|
||||
/**
|
||||
* @format 11H11BBB2221
|
||||
* @param subevent_code
|
||||
* @param status
|
||||
* @param connection_handle
|
||||
* @param role
|
||||
* @param peer_address_type
|
||||
* @param perr_addresss
|
||||
* @param local_resolvable_private_addres
|
||||
* @param peer_resolvable_private_addres
|
||||
* @param conn_interval
|
||||
* @param conn_latency
|
||||
* @param supervision_timeout
|
||||
* @param master_clock_accuracy
|
||||
*/
|
||||
#define HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE 0x0A
|
||||
|
||||
// array of advertisements, not handled by event accessor generator
|
||||
#define HCI_SUBEVENT_LE_DIRECT_ADVERTISING_REPORT 0x0B
|
||||
|
||||
/**
|
||||
* L2CAP Layer
|
||||
@ -1056,6 +1142,7 @@ typedef enum {
|
||||
#define COMPANY_ID_TEXAS_INSTRUMENTS_INC 0x000D
|
||||
#define COMPANY_ID_BROADCOM_CORPORATION 0x000F
|
||||
#define COMPANY_ID_ST_MICROELECTRONICS 0x0030
|
||||
#define COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA 0x0059
|
||||
#define COMPANY_ID_EM_MICROELECTRONICS_MARIN 0x005A
|
||||
|
||||
|
||||
|
51
src/bluetooth_data_types.h
Normal file
51
src/bluetooth_data_types.h
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* bluetooth_data_types.h generated from Bluetooth SIG website for BTstack
|
||||
* https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
|
||||
*/
|
||||
|
||||
#ifndef __BLUETOOTH_DATA_TYPES_H
|
||||
#define __BLUETOOTH_DATA_TYPES_H
|
||||
|
||||
#define BLUETOOTH_DATA_TYPE_FLAGS 0x01 // Flags
|
||||
#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS 0x02 // Incomplete List of 16-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS 0x03 // Complete List of 16-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS 0x04 // Incomplete List of 32-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS 0x05 // Complete List of 32-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS 0x06 // Incomplete List of 128-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS 0x07 // Complete List of 128-bit Service Class UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME 0x08 // Shortened Local Name
|
||||
#define BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME 0x09 // Complete Local Name
|
||||
#define BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL 0x0A // Tx Power Level
|
||||
#define BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE 0x0D // Class of Device
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C 0x0E // Simple Pairing Hash C
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_192 0x0E // Simple Pairing Hash C-192
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F // Simple Pairing Randomizer R
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_192 0x0F // Simple Pairing Randomizer R-192
|
||||
#define BLUETOOTH_DATA_TYPE_DEVICE_ID 0x10 // Device ID
|
||||
#define BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 // Security Manager TK Value
|
||||
#define BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS 0x11 // Security Manager Out of Band Flags
|
||||
#define BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 // Slave Connection Interval Range
|
||||
#define BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS 0x14 // List of 16-bit Service Solicitation UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS 0x1F // List of 32-bit Service Solicitation UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS 0x15 // List of 128-bit Service Solicitation UUIDs
|
||||
#define BLUETOOTH_DATA_TYPE_SERVICE_DATA 0x16 // Service Data
|
||||
#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID 0x16 // Service Data - 16-bit UUID
|
||||
#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_32_BIT_UUID 0x20 // Service Data - 32-bit UUID
|
||||
#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_128_BIT_UUID 0x21 // Service Data - 128-bit UUID
|
||||
#define BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE 0x22 // LE Secure Connections Confirmation Value
|
||||
#define BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE 0x23 // LE Secure Connections Random Value
|
||||
#define BLUETOOTH_DATA_TYPE_URI 0x24 // URI
|
||||
#define BLUETOOTH_DATA_TYPE_INDOOR_POSITIONING 0x25 // Indoor Positioning
|
||||
#define BLUETOOTH_DATA_TYPE_TRANSPORT_DISCOVERY_DATA 0x26 // Transport Discovery Data
|
||||
#define BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS 0x17 // Public Target Address
|
||||
#define BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS 0x18 // Random Target Address
|
||||
#define BLUETOOTH_DATA_TYPE_APPEARANCE 0x19 // Appearance
|
||||
#define BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL 0x1A // Advertising Interval
|
||||
#define BLUETOOTH_DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B // LE Bluetooth Device Address
|
||||
#define BLUETOOTH_DATA_TYPE_LE_ROLE 0x1C // LE Role
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_256 0x1D // Simple Pairing Hash C-256
|
||||
#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256 0x1E // Simple Pairing Randomizer R-256
|
||||
#define BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA 0x3D // 3D Information Data
|
||||
#define BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF // Manufacturer Specific Data
|
||||
|
||||
#endif
|
259
src/bluetooth_gatt.h
Normal file
259
src/bluetooth_gatt.h
Normal file
@ -0,0 +1,259 @@
|
||||
|
||||
/**
|
||||
* bluetooth_gatt.h generated from Bluetooth SIG website for BTstack
|
||||
*/
|
||||
|
||||
#ifndef __BLUETOOTH_GATT_H
|
||||
#define __BLUETOOTH_GATT_H
|
||||
|
||||
/**
|
||||
* Assigned numbers from https://www.bluetooth.com/specifications/gatt/declarations
|
||||
*/
|
||||
#define ORG_BLUETOOTH_ATTRIBUTE_GATT_PRIMARY_SERVICE_DECLARATION 0x2800 // GATT Primary Service Declaration
|
||||
#define ORG_BLUETOOTH_ATTRIBUTE_GATT_SECONDARY_SERVICE_DECLARATION 0x2801 // GATT Secondary Service Declaration
|
||||
#define ORG_BLUETOOTH_ATTRIBUTE_GATT_CHARACTERISTIC_DECLARATION 0x2803 // GATT Characteristic Declaration
|
||||
#define ORG_BLUETOOTH_ATTRIBUTE_GATT_INCLUDE_DECLARATION 0x2802 // GATT Include Declaration
|
||||
|
||||
/**
|
||||
* Assigned numbers from https://www.bluetooth.com/specifications/gatt/services
|
||||
*/
|
||||
#define ORG_BLUETOOTH_SERVICE_LOCATION_AND_NAVIGATION 0x1819 // Location and Navigation
|
||||
#define ORG_BLUETOOTH_SERVICE_LINK_LOSS 0x1803 // Link Loss
|
||||
#define ORG_BLUETOOTH_SERVICE_OBJECT_TRANSFER 0x1825 // Object Transfer
|
||||
#define ORG_BLUETOOTH_SERVICE_NEXT_DST_CHANGE 0x1807 // Next DST Change Service
|
||||
#define ORG_BLUETOOTH_SERVICE_IMMEDIATE_ALERT 0x1802 // Immediate Alert
|
||||
#define ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE 0x1812 // Human Interface Device
|
||||
#define ORG_BLUETOOTH_SERVICE_INTERNET_PROTOCOL_SUPPORT 0x1820 // Internet Protocol Support
|
||||
#define ORG_BLUETOOTH_SERVICE_INDOOR_POSITIONING 0x1821 // Indoor Positioning
|
||||
#define ORG_BLUETOOTH_SERVICE_PHONE_ALERT_STATUS 0x180E // Phone Alert Status Service
|
||||
#define ORG_BLUETOOTH_SERVICE_TX_POWER 0x1804 // Tx Power
|
||||
#define ORG_BLUETOOTH_SERVICE_TRANSPORT_DISCOVERY 0x1824 // Transport Discovery
|
||||
#define ORG_BLUETOOTH_SERVICE_WEIGHT_SCALE 0x181D // Weight Scale
|
||||
#define ORG_BLUETOOTH_SERVICE_USER_DATA 0x181C // User Data
|
||||
#define ORG_BLUETOOTH_SERVICE_REFERENCE_TIME_UPDATE 0x1806 // Reference Time Update Service
|
||||
#define ORG_BLUETOOTH_SERVICE_PULSE_OXIMETER 0x1822 // Pulse Oximeter
|
||||
#define ORG_BLUETOOTH_SERVICE_SCAN_PARAMETERS 0x1813 // Scan Parameters
|
||||
#define ORG_BLUETOOTH_SERVICE_RUNNING_SPEED_AND_CADENCE 0x1814 // Running Speed and Cadence
|
||||
#define ORG_BLUETOOTH_SERVICE_HTTP_PROXY 0x1823 // HTTP Proxy
|
||||
#define ORG_BLUETOOTH_SERVICE_BOND_MANAGEMENT 0x181E // Bond Management
|
||||
#define ORG_BLUETOOTH_SERVICE_BODY_COMPOSITION 0x181B // Body Composition
|
||||
#define ORG_BLUETOOTH_SERVICE_CURRENT_TIME 0x1805 // Current Time Service
|
||||
#define ORG_BLUETOOTH_SERVICE_CONTINUOUS_GLUCOSE_MONITORING 0x181F // Continuous Glucose Monitoring
|
||||
#define ORG_BLUETOOTH_SERVICE_AUTOMATION_IO 0x1815 // Automation IO
|
||||
#define ORG_BLUETOOTH_SERVICE_ALERT_NOTIFICATION 0x1811 // Alert Notification Service
|
||||
#define ORG_BLUETOOTH_SERVICE_BLOOD_PRESSURE 0x1810 // Blood Pressure
|
||||
#define ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE 0x180F // Battery Service
|
||||
#define ORG_BLUETOOTH_SERVICE_CYCLING_POWER 0x1818 // Cycling Power
|
||||
#define ORG_BLUETOOTH_SERVICE_GLUCOSE 0x1808 // Glucose
|
||||
#define ORG_BLUETOOTH_SERVICE_GENERIC_ATTRIBUTE 0x1801 // Generic Attribute
|
||||
#define ORG_BLUETOOTH_SERVICE_HEART_RATE 0x180D // Heart Rate
|
||||
#define ORG_BLUETOOTH_SERVICE_HEALTH_THERMOMETER 0x1809 // Health Thermometer
|
||||
#define ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION 0x180A // Device Information
|
||||
#define ORG_BLUETOOTH_SERVICE_CYCLING_SPEED_AND_CADENCE 0x1816 // Cycling Speed and Cadence
|
||||
#define ORG_BLUETOOTH_SERVICE_GENERIC_ACCESS 0x1800 // Generic Access
|
||||
#define ORG_BLUETOOTH_SERVICE_ENVIRONMENTAL_SENSING 0x181A // Environmental Sensing
|
||||
|
||||
/**
|
||||
* Assigned numbers from https://www.bluetooth.com/specifications/gatt/characteristics
|
||||
*/
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OTS_FEATURE 0x2ABD // OTS Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_TYPE 0x2ABF // Object Type
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS 0x2A04 // Peripheral Preferred Connection Parameters
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PLX_CONTINUOUS_MEASUREMENT 0x2A5F // PLX Continuous Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_PERIPHERAL_PRIVACY_FLAG 0x2A02 // Peripheral Privacy Flag
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_SIZE 0x2AC0 // Object Size
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_LIST_CONTROL_POINT 0x2AC6 // Object List Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_LAST_MODIFIED 0x2AC2 // Object Last-Modified
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_LIST_FILTER 0x2AC7 // Object List Filter
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_PROPERTIES 0x2AC4 // Object Properties
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_NAME 0x2ABE // Object Name
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RAINFALL 0x2A78 // Rainfall
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE 0x2A4E // Protocol Mode
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_RECONNECTION_ADDRESS 0x2A03 // Reconnection Address
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_REFERENCE_TIME_INFORMATION 0x2A14 // Reference Time Information
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RECORD_ACCESS_CONTROL_POINT 0x2A52 // Record Access Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PRESSURE 0x2A6D // Pressure
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PLX_SPOT_CHECK_MEASUREMENT 0x2A5E // PLX Spot-Check Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PLX_FEATURES 0x2A60 // PLX Features
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID 0x2A50 // PnP ID
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_POSITION_QUALITY 0x2A69 // Position Quality
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_POLLEN_CONCENTRATION 0x2A75 // Pollen Concentration
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_ID 0x2AC3 // Object ID
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LOCATION_AND_SPEED 0x2A67 // Location and Speed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LOCAL_TIME_INFORMATION 0x2A0F // Local Time Information
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LOCATION_NAME 0x2AB5 // Location Name
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MAGNETIC_DECLINATION 0x2A2C // Magnetic Declination
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LONGITUDE 0x2AAF // Longitude
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LOCAL_NORTH_COORDINATE 0x2AB0 // Local North Coordinate
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LATITUDE 0x2AAE // Latitude
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LAST_NAME 0x2A90 // Last Name
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LN_CONTROL_POINT 0x2A6B // LN Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LOCAL_EAST_COORDINATE 0x2AB1 // Local East Coordinate
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LN_FEATURE 0x2A6A // LN Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_NEW_ALERT 0x2A46 // New Alert
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_NAVIGATION 0x2A68 // Navigation
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_ACTION_CONTROL_POINT 0x2AC5 // Object Action Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_FIRST_CREATED 0x2AC1 // Object First-Created
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_OBJECT_CHANGED 0x2AC8 // Object Changed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING 0x2A24 // Model Number String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MAGNETIC_FLUX_DENSITY_3D 0x2AA1 // Magnetic Flux Density - 3D
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MAGNETIC_FLUX_DENSITY_2D 0x2AA0 // Magnetic Flux Density - 2D
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING 0x2A29 // Manufacturer Name String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MEASUREMENT_INTERVAL 0x2A21 // Measurement Interval
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_MAXIMUM_RECOMMENDED_HEART_RATE 0x2A91 // Maximum Recommended Heart Rate
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TRUE_WIND_SPEED 0x2A70 // True Wind Speed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TRUE_WIND_DIRECTION 0x2A71 // True Wind Direction
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TWO_ZONE_HEART_RATE_LIMIT 0x2A95 // Two Zone Heart Rate Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_UNCERTAINTY 0x2AB4 // Uncertainty
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TX_POWER_LEVEL 0x2A07 // Tx Power Level
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_ZONE 0x2A0E // Time Zone
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_SOURCE 0x2A13 // Time Source
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_ACCURACY 0x2A12 // Time Accuracy
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_UPDATE_CONTROL_POINT 0x2A16 // Time Update Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_WITH_DST 0x2A11 // Time with DST
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TIME_UPDATE_STATE 0x2A17 // Time Update State
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_WEIGHT 0x2A98 // Weight
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_WAIST_CIRCUMFERENCE 0x2A97 // Waist Circumference
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_WEIGHT_MEASUREMENT 0x2A9D // Weight Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_WIND_CHILL 0x2A79 // Wind Chill
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_WEIGHT_SCALE_FEATURE 0x2A9E // Weight Scale Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_VO2_MAX 0x2A96 // VO2 Max
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_URI 0x2AB6 // URI
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_UNREAD_ALERT_STATUS 0x2A45 // Unread Alert Status
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_USER_CONTROL_POINT 0x2A9F // User Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_UV_INDEX 0x2A76 // UV Index
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_USER_INDEX 0x2A9A // User Index
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_THREE_ZONE_HEART_RATE_LIMITS 0x2A94 // Three Zone Heart Rate Limits
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SC_CONTROL_POINT 0x2A55 // SC Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RSC_MEASUREMENT 0x2A53 // RSC Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SCAN_INTERVAL_WINDOW 0x2A4F // Scan Interval Window
|
||||
#define ORG_BLUEOOTH_CHARACTERISTIC_SENSOR_LOCATION 0x2A5D // Sensor Location
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SCAN_REFRESH 0x2A31 // Scan Refresh
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RSC_FEATURE 0x2A54 // RSC Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP 0x2A4B // Report Map
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_REPORT 0x2A4D // Report
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RESTING_HEART_RATE 0x2A92 // Resting Heart Rate
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RINGER_SETTING 0x2A41 // Ringer Setting
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_RINGER_CONTROL_POINT 0x2A40 // Ringer Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TDS_CONTROL_POINT 0x2ABC // TDS Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID 0x2A23 // System ID
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE 0x2A6E // Temperature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE_TYPE 0x2A1D // Temperature Type
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_TEMPERATURE_MEASUREMENT 0x2A1C // Temperature Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SUPPORTED_UNREAD_ALERT_CATEGORY 0x2A48 // Supported Unread Alert Category
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GATT_SERVICE_CHANGED 0x2A05 // Service Changed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING 0x2A25 // Serial Number String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING 0x2A28 // Software Revision String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SUPPORTED_NEW_ALERT_CATEGORY 0x2A47 // Supported New Alert Category
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_SPORT_TYPE_FOR_AEROBIC_AND_ANAEROBIC_THRESHOLDS 0x2A93 // Sport Type for Aerobic and Anaerobic Thresholds
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_CENTRAL_ADDRESS_RESOLUTION_SUPPORT 0x2AA6 // Central Address Resolution
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT 0x2A33 // Boot Mouse Input Report
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_FEATURE 0x2AA8 // CGM Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_RUN_TIME 0x2AAB // CGM Session Run Time
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_MEASUREMENT 0x2AA7 // CGM Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT 0x2A32 // Boot Keyboard Output Report
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BODY_SENSOR_LOCATION 0x2A38 // Body Sensor Location
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BODY_COMPOSITION_MEASUREMENT 0x2A9C // Body Composition Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BOND_MANAGEMENT_CONTROL_POINT 0x2AA4 // Bond Management Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT 0x2A22 // Boot Keyboard Input Report
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BOND_MANAGEMENT_FEATURE 0x2AA5 // Bond Management Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CYCLING_POWER_FEATURE 0x2A65 // Cycling Power Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CYCLING_POWER_CONTROL_POINT 0x2A66 // Cycling Power Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CYCLING_POWER_MEASUREMENT 0x2A63 // Cycling Power Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DATABASE_CHANGE_INCREMENT 0x2A99 // Database Change Increment
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CYCLING_POWER_VECTOR 0x2A64 // Cycling Power Vector
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CURRENT_TIME 0x2A2B // Current Time
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_SPECIFIC_OPS_CONTROL_POINT 0x2AAC // CGM Specific Ops Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_START_TIME 0x2AAA // CGM Session Start Time
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CGM_STATUS 0x2AA9 // CGM Status
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CSC_MEASUREMENT 0x2A5B // CSC Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_CSC_FEATURE 0x2A5C // CSC Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BODY_COMPOSITION_FEATURE 0x2A9B // Body Composition Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALERT_LEVEL 0x2A06 // Alert Level
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALERT_CATEGORY_ID_BIT_MASK 0x2A42 // Alert Category ID Bit Mask
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALERT_NOTIFICATION_CONTROL_POINT 0x2A44 // Alert Notification Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALTITUDE 0x2AB3 // Altitude
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALERT_STATUS 0x2A3F // Alert Status
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ALERT_CATEGORY_ID 0x2A43 // Alert Category ID
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_AEROBIC_HEART_RATE_UPPER_LIMIT 0x2A84 // Aerobic Heart Rate Upper Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_AEROBIC_THRESHOLD 0x2A7F // Aerobic Threshold
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_AGGREGATE 0x2A5A // Aggregate
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_AGE 0x2A80 // Age
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BAROMETRIC_PRESSURE_TREND 0x2AA3 // Barometric Pressure Trend
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_APPEARANCE 0x2A01 // Appearance
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL 0x2A19 // Battery Level
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_MEASUREMENT 0x2A35 // Blood Pressure Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_FEATURE 0x2A49 // Blood Pressure Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_APPARENT_WIND_SPEED 0x2A72 // Apparent Wind Speed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ANAEROBIC_HEART_RATE_UPPER_LIMIT 0x2A82 // Anaerobic Heart Rate Upper Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ANAEROBIC_HEART_RATE_LOWER_LIMIT 0x2A81 // Anaerobic Heart Rate Lower Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ANAEROBIC_THRESHOLD 0x2A83 // Anaerobic Threshold
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_APPARENT_WIND_DIRECTION 0x2A73 // Apparent Wind Direction
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ANALOG 0x2A58 // Analog
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT 0x2A4C // HID Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HEIGHT 0x2A8E // Height
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION 0x2A4A // HID Information
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HTTP_CONTROL_POINT 0x2ABA // HTTP Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HIP_CIRCUMFERENCE 0x2A8F // Hip Circumference
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HEAT_INDEX 0x2A7A // Heat Index
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING 0x2A27 // Hardware Revision String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GUST_FACTOR 0x2A74 // Gust Factor
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HEART_RATE_CONTROL_POINT 0x2A39 // Heart Rate Control Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HEART_RATE_MEASUREMENT 0x2A37 // Heart Rate Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HEART_RATE_MAX 0x2A8D // Heart Rate Max
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_INTERMEDIATE_CUFF_PRESSURE 0x2A36 // Intermediate Cuff Pressure
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_INDOOR_POSITIONING_CONFIGURATION 0x2AAD // Indoor Positioning Configuration
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_INTERMEDIATE_TEMPERATURE 0x2A1E // Intermediate Temperature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_LANGUAGE 0x2AA2 // Language
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_IRRADIANCE 0x2A77 // Irradiance
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST 0x2A2A // IEEE 11073-20601 Regulatory Certification Data List
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HTTP_HEADERS 0x2AB7 // HTTP Headers
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HTTP_ENTITY_BODY 0x2AB9 // HTTP Entity Body
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HTTP_STATUS_CODE 0x2AB8 // HTTP Status Code
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HUMIDITY 0x2A6F // Humidity
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_HTTPS_SECURITY 0x2ABB // HTTPS Security
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GLUCOSE_MEASUREMENT_CONTEXT 0x2A34 // Glucose Measurement Context
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DEW_POINT 0x2A7B // Dew Point
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GAP_DEVICE_NAME 0x2A00 // Device Name
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DIGITAL 0x2A56 // Digital
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_ELEVATION 0x2A6C // Elevation
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DST_OFFSET 0x2A0D // DST Offset
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DESCRIPTOR_VALUE_CHANGED 0x2A7D // Descriptor Value Changed
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DATE_OF_THRESHOLD_ASSESSMENT 0x2A86 // Date of Threshold Assessment
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DATE_OF_BIRTH 0x2A85 // Date of Birth
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DATE_TIME 0x2A08 // Date Time
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DAY_OF_WEEK 0x2A09 // Day of Week
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_DAY_DATE_TIME 0x2A0A // Day Date Time
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FLOOR_NUMBER 0x2AB2 // Floor Number
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FIVE_ZONE_HEART_RATE_LIMITS 0x2A8B // Five Zone Heart Rate Limits
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GENDER 0x2A8C // Gender
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GLUCOSE_MEASUREMENT 0x2A18 // Glucose Measurement
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_GLUCOSE_FEATURE 0x2A51 // Glucose Feature
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FIRST_NAME 0x2A8A // First Name
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_EXACT_TIME_256 0x2A0C // Exact Time 256
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_EMAIL_ADDRESS 0x2A87 // Email Address
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FAT_BURN_HEART_RATE_LOWER_LIMIT 0x2A88 // Fat Burn Heart Rate Lower Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING 0x2A26 // Firmware Revision String
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FAT_BURN_HEART_RATE_UPPER_LIMIT 0x2A89 // Fat Burn Heart Rate Upper Limit
|
||||
#define ORG_BLUETOOTH_CHARACTERISTIC_FITNESS_MACHINE_CONTROL_POINT 0xEE1D // Fitness Machine Control Point
|
||||
|
||||
/**
|
||||
* Assigned numbers from https://www.bluetooth.com/specifications/gatt/descriptors
|
||||
*/
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_REPORT_REFERENCE 0x2908 // Report Reference
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_NUMBER_OF_DIGITALS 0x2909 // Number of Digitals
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_EXTERNAL_REPORT_REFERENCE 0x2907 // External Report Reference
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_SERVER_CHARACTERISTIC_CONFIGURATION 0x2903 // Server Characteristic Configuration
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_VALUE_TRIGGER_SETTING 0x290A // Value Trigger Setting
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_VALID_RANGE 0x2906 // Valid Range
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_TIME_TRIGGER_SETTING 0x290E // Time Trigger Setting
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_ES_TRIGGER_SETTING 0x290D // Environmental Sensing Trigger Setting
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_CHARACTERISTIC_PRESENTATION_FORMAT 0x2904 // Characteristic Presentation Format
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_CHARACTERISTIC_EXTENDED_PROPERTIES 0x2900 // Characteristic Extended Properties
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_CHARACTERISTIC_AGGREGATE_FORMAT 0x2905 // Characteristic Aggregate Format
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_CHARACTERISTIC_USER_DESCRIPTION 0x2901 // Characteristic User Description
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_ES_MEASUREMENT 0x290C // Environmental Sensing Measurement
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_ES_CONFIGURATION 0x290B // Environmental Sensing Configuration
|
||||
#define ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION 0x2902 // Client Characteristic Configuration
|
||||
|
||||
#endif
|
@ -47,6 +47,8 @@
|
||||
#include "btstack_config.h"
|
||||
|
||||
#include "bluetooth.h"
|
||||
#include "bluetooth_data_types.h"
|
||||
#include "bluetooth_gatt.h"
|
||||
#include "ad_parser.h"
|
||||
#include "btstack_control.h"
|
||||
#include "btstack_debug.h"
|
||||
|
@ -57,13 +57,20 @@
|
||||
// Avoid complaints of unused arguments when log levels are disabled.
|
||||
static inline void __log_unused(const char *format, ...) {}
|
||||
|
||||
// allow to provide port specific printf
|
||||
#ifndef BTSTACK_PRINTF
|
||||
#ifdef __AVR__
|
||||
#define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log_P(log_level, PSTR(format), ## __VA_ARGS__)
|
||||
#define BTSTACK_PRINTF(format, ...) printf_P(PSTR(format), ## __VA_ARGS__)
|
||||
#else
|
||||
#define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log(log_level, format, ## __VA_ARGS__)
|
||||
#define BTSTACK_PRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __AVR__
|
||||
#define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log_P(log_level, PSTR(format), ## __VA_ARGS__)
|
||||
#else
|
||||
#define HCI_DUMP_LOG(log_level, format, ...) hci_dump_log(log_level, format, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LOG_DEBUG
|
||||
#ifdef ENABLE_LOG_INTO_HCI_DUMP
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include <stdint.h>
|
||||
#include "btstack_linked_list.h"
|
||||
|
||||
|
||||
// UNUSED macro
|
||||
#define UNUSED(x) (void)(sizeof(x))
|
||||
|
||||
// TYPES
|
||||
|
||||
// packet handler
|
||||
@ -57,6 +61,13 @@ typedef struct {
|
||||
btstack_packet_handler_t callback;
|
||||
} btstack_packet_callback_registration_t;
|
||||
|
||||
// context callback supporting multiple registrations
|
||||
typedef struct {
|
||||
btstack_linked_item_t * item;
|
||||
void (*callback)(void * context);
|
||||
void * context;
|
||||
} btstack_context_callback_registration_t;
|
||||
|
||||
/**
|
||||
* @brief 128 bit key used with AES128 in Security Manager
|
||||
*/
|
||||
@ -119,6 +130,7 @@ typedef uint8_t sm_key_t[16];
|
||||
#define L2CAP_SERVICE_ALREADY_REGISTERED 0x69
|
||||
#define L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU 0x6A
|
||||
#define L2CAP_SERVICE_DOES_NOT_EXIST 0x6B
|
||||
#define L2CAP_LOCAL_CID_DOES_NOT_EXIST 0x6C
|
||||
|
||||
#define RFCOMM_MULTIPLEXER_STOPPED 0x70
|
||||
#define RFCOMM_CHANNEL_ALREADY_REGISTERED 0x71
|
||||
@ -368,7 +380,7 @@ typedef uint8_t sm_key_t[16];
|
||||
// L2CAP EVENTS
|
||||
|
||||
/**
|
||||
* @format 1BH222222
|
||||
* @format 1BH2222221
|
||||
* @param status
|
||||
* @param address
|
||||
* @param handle
|
||||
@ -378,6 +390,7 @@ typedef uint8_t sm_key_t[16];
|
||||
* @param local_mtu
|
||||
* @param remote_mtu
|
||||
* @param flush_timeout
|
||||
* @param incoming
|
||||
*/
|
||||
#define L2CAP_EVENT_CHANNEL_OPENED 0x70
|
||||
|
||||
@ -425,16 +438,65 @@ typedef uint8_t sm_key_t[16];
|
||||
*/
|
||||
#define L2CAP_EVENT_CAN_SEND_NOW 0x78
|
||||
|
||||
// LE Data Channels
|
||||
|
||||
/**
|
||||
* @format 1BH2222
|
||||
* @param address_type
|
||||
* @param address
|
||||
* @param handle
|
||||
* @param psm
|
||||
* @param local_cid
|
||||
* @param remote_cid
|
||||
* @param remote_mtu
|
||||
*/
|
||||
#define L2CAP_EVENT_LE_INCOMING_CONNECTION 0x79
|
||||
|
||||
/**
|
||||
* @format 11BH122222
|
||||
* @param status
|
||||
* @param address_type
|
||||
* @param address
|
||||
* @param handle
|
||||
* @param incoming
|
||||
* @param psm
|
||||
* @param local_cid
|
||||
* @param remote_cid
|
||||
* @param local_mtu
|
||||
* @param remote_mtu
|
||||
*/
|
||||
#define L2CAP_EVENT_LE_CHANNEL_OPENED 0x7a
|
||||
|
||||
/*
|
||||
* @format 2
|
||||
* @param local_cid
|
||||
*/
|
||||
#define L2CAP_EVENT_LE_CHANNEL_CLOSED 0x7b
|
||||
|
||||
/*
|
||||
* @format 2
|
||||
* @param local_cid
|
||||
*/
|
||||
#define L2CAP_EVENT_LE_CAN_SEND_NOW 0x7c
|
||||
|
||||
/*
|
||||
* @format 2
|
||||
* @param local_cid
|
||||
*/
|
||||
#define L2CAP_EVENT_LE_PACKET_SENT 0x7d
|
||||
|
||||
|
||||
// RFCOMM EVENTS
|
||||
|
||||
/**
|
||||
* @format 1B2122
|
||||
* @format 1B21221
|
||||
* @param status
|
||||
* @param bd_addr
|
||||
* @param con_handle
|
||||
* @param server_channel
|
||||
* @param rfcomm_cid
|
||||
* @param max_frame_size
|
||||
* @param incoming
|
||||
*/
|
||||
#define RFCOMM_EVENT_CHANNEL_OPENED 0x80
|
||||
|
||||
@ -769,11 +831,17 @@ typedef uint8_t sm_key_t[16];
|
||||
#define SM_EVENT_IDENTITY_RESOLVING_FAILED 0xD9
|
||||
|
||||
/**
|
||||
* @format H1B2
|
||||
* @brief Identify resolving succeeded
|
||||
*
|
||||
* @format H1B1B
|
||||
* @param handle
|
||||
* @param addr_type
|
||||
* @param address
|
||||
* @param le_device_db_index
|
||||
* @param identity_addr_type
|
||||
* @param identity_address
|
||||
*
|
||||
* @note le_device_db_index was removed, please use provided identity information directly
|
||||
*
|
||||
*/
|
||||
#define SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED 0xDA
|
||||
|
||||
@ -801,6 +869,17 @@ typedef uint8_t sm_key_t[16];
|
||||
*/
|
||||
#define SM_EVENT_KEYPRESS_NOTIFICATION 0xDD
|
||||
|
||||
/**
|
||||
* @brief Emitted during pairing to inform app about address used as identity
|
||||
*
|
||||
* @format H1B1B
|
||||
* @param handle
|
||||
* @param addr_type
|
||||
* @param address
|
||||
* @param identity_addr_type
|
||||
* @param identity_address
|
||||
*/
|
||||
#define SM_EVENT_IDENTITY_CREATED 0xDE
|
||||
|
||||
// GAP
|
||||
|
||||
|
@ -1034,6 +1034,15 @@ static inline uint16_t l2cap_event_channel_opened_get_remote_mtu(const uint8_t *
|
||||
static inline uint16_t l2cap_event_channel_opened_get_flush_timeout(const uint8_t * event){
|
||||
return little_endian_read_16(event, 21);
|
||||
}
|
||||
/**
|
||||
* @brief Get field incoming from event L2CAP_EVENT_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return incoming
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t l2cap_event_channel_opened_get_incoming(const uint8_t * event){
|
||||
return event[23];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_CHANNEL_CLOSED
|
||||
@ -1157,6 +1166,191 @@ static inline uint16_t l2cap_event_can_send_now_get_local_cid(const uint8_t * ev
|
||||
return little_endian_read_16(event, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field address_type from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return address_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t l2cap_event_le_incoming_connection_get_address_type(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/**
|
||||
* @brief Get field address from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @param Pointer to storage for address
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void l2cap_event_le_incoming_connection_get_address(const uint8_t * event, bd_addr_t address){
|
||||
reverse_bd_addr(&event[3], address);
|
||||
}
|
||||
/**
|
||||
* @brief Get field handle from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t l2cap_event_le_incoming_connection_get_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 9);
|
||||
}
|
||||
/**
|
||||
* @brief Get field psm from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return psm
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_incoming_connection_get_psm(const uint8_t * event){
|
||||
return little_endian_read_16(event, 11);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return local_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_incoming_connection_get_local_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 13);
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return remote_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_incoming_connection_get_remote_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 15);
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_mtu from event L2CAP_EVENT_LE_INCOMING_CONNECTION
|
||||
* @param event packet
|
||||
* @return remote_mtu
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_incoming_connection_get_remote_mtu(const uint8_t * event){
|
||||
return little_endian_read_16(event, 17);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t l2cap_event_le_channel_opened_get_status(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/**
|
||||
* @brief Get field address_type from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return address_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t l2cap_event_le_channel_opened_get_address_type(const uint8_t * event){
|
||||
return event[3];
|
||||
}
|
||||
/**
|
||||
* @brief Get field address from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @param Pointer to storage for address
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void l2cap_event_le_channel_opened_get_address(const uint8_t * event, bd_addr_t address){
|
||||
reverse_bd_addr(&event[4], address);
|
||||
}
|
||||
/**
|
||||
* @brief Get field handle from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t l2cap_event_le_channel_opened_get_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 10);
|
||||
}
|
||||
/**
|
||||
* @brief Get field incoming from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return incoming
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t l2cap_event_le_channel_opened_get_incoming(const uint8_t * event){
|
||||
return event[12];
|
||||
}
|
||||
/**
|
||||
* @brief Get field psm from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return psm
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_opened_get_psm(const uint8_t * event){
|
||||
return little_endian_read_16(event, 13);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return local_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_opened_get_local_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 15);
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return remote_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_opened_get_remote_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 17);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return local_mtu
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_opened_get_local_mtu(const uint8_t * event){
|
||||
return little_endian_read_16(event, 19);
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return remote_mtu
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_opened_get_remote_mtu(const uint8_t * event){
|
||||
return little_endian_read_16(event, 21);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_CLOSED
|
||||
* @param event packet
|
||||
* @return local_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_channel_closed_get_local_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_LE_CAN_SEND_NOW
|
||||
* @param event packet
|
||||
* @return local_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_can_send_now_get_local_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field local_cid from event L2CAP_EVENT_LE_PACKET_SENT
|
||||
* @param event packet
|
||||
* @return local_cid
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t l2cap_event_le_packet_sent_get_local_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event RFCOMM_EVENT_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
@ -1211,6 +1405,15 @@ static inline uint16_t rfcomm_event_channel_opened_get_rfcomm_cid(const uint8_t
|
||||
static inline uint16_t rfcomm_event_channel_opened_get_max_frame_size(const uint8_t * event){
|
||||
return little_endian_read_16(event, 14);
|
||||
}
|
||||
/**
|
||||
* @brief Get field incoming from event RFCOMM_EVENT_CHANNEL_OPENED
|
||||
* @param event packet
|
||||
* @return incoming
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t rfcomm_event_channel_opened_get_incoming(const uint8_t * event){
|
||||
return event[16];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field rfcomm_cid from event RFCOMM_EVENT_CHANNEL_CLOSED
|
||||
@ -2396,13 +2599,22 @@ static inline void sm_event_identity_resolving_succeeded_get_address(const uint8
|
||||
reverse_bd_addr(&event[5], address);
|
||||
}
|
||||
/**
|
||||
* @brief Get field le_device_db_index from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED
|
||||
* @brief Get field identity_addr_type from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED
|
||||
* @param event packet
|
||||
* @return le_device_db_index
|
||||
* @note: btstack_type 2
|
||||
* @return identity_addr_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint16_t sm_event_identity_resolving_succeeded_get_le_device_db_index(const uint8_t * event){
|
||||
return little_endian_read_16(event, 11);
|
||||
static inline uint8_t sm_event_identity_resolving_succeeded_get_identity_addr_type(const uint8_t * event){
|
||||
return event[11];
|
||||
}
|
||||
/**
|
||||
* @brief Get field identity_address from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED
|
||||
* @param event packet
|
||||
* @param Pointer to storage for identity_address
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void sm_event_identity_resolving_succeeded_get_identity_address(const uint8_t * event, bd_addr_t identity_address){
|
||||
reverse_bd_addr(&event[12], identity_address);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2496,6 +2708,54 @@ static inline uint8_t sm_event_keypress_notification_get_action(const uint8_t *
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
/**
|
||||
* @brief Get field handle from event SM_EVENT_IDENTITY_CREATED
|
||||
* @param event packet
|
||||
* @return handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t sm_event_identity_created_get_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 2);
|
||||
}
|
||||
/**
|
||||
* @brief Get field addr_type from event SM_EVENT_IDENTITY_CREATED
|
||||
* @param event packet
|
||||
* @return addr_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t sm_event_identity_created_get_addr_type(const uint8_t * event){
|
||||
return event[4];
|
||||
}
|
||||
/**
|
||||
* @brief Get field address from event SM_EVENT_IDENTITY_CREATED
|
||||
* @param event packet
|
||||
* @param Pointer to storage for address
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void sm_event_identity_created_get_address(const uint8_t * event, bd_addr_t address){
|
||||
reverse_bd_addr(&event[5], address);
|
||||
}
|
||||
/**
|
||||
* @brief Get field identity_addr_type from event SM_EVENT_IDENTITY_CREATED
|
||||
* @param event packet
|
||||
* @return identity_addr_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t sm_event_identity_created_get_identity_addr_type(const uint8_t * event){
|
||||
return event[11];
|
||||
}
|
||||
/**
|
||||
* @brief Get field identity_address from event SM_EVENT_IDENTITY_CREATED
|
||||
* @param event packet
|
||||
* @param Pointer to storage for identity_address
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void sm_event_identity_created_get_identity_address(const uint8_t * event, bd_addr_t identity_address){
|
||||
reverse_bd_addr(&event[12], identity_address);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get field handle from event GAP_EVENT_SECURITY_LEVEL
|
||||
* @param event packet
|
||||
@ -2671,6 +2931,347 @@ static inline uint8_t hci_subevent_le_connection_complete_get_master_clock_accur
|
||||
return event[20];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_connection_update_complete_get_status(const uint8_t * event){
|
||||
return event[3];
|
||||
}
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t hci_subevent_le_connection_update_complete_get_connection_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 4);
|
||||
}
|
||||
/**
|
||||
* @brief Get field conn_interval from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE
|
||||
* @param event packet
|
||||
* @return conn_interval
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_connection_update_complete_get_conn_interval(const uint8_t * event){
|
||||
return little_endian_read_16(event, 6);
|
||||
}
|
||||
/**
|
||||
* @brief Get field conn_latency from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE
|
||||
* @param event packet
|
||||
* @return conn_latency
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_connection_update_complete_get_conn_latency(const uint8_t * event){
|
||||
return little_endian_read_16(event, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
// static inline hci_con_handle_t hci_subevent_le_read_remote_used_features_complete_get_connection_handle(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
/**
|
||||
* @brief Get field random_number from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE
|
||||
* @param event packet
|
||||
* @return random_number
|
||||
* @note: btstack_type D
|
||||
*/
|
||||
// static inline const uint8_t * hci_subevent_le_read_remote_used_features_complete_get_random_number(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
/**
|
||||
* @brief Get field encryption_diversifier from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE
|
||||
* @param event packet
|
||||
* @return encryption_diversifier
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
// static inline uint16_t hci_subevent_le_read_remote_used_features_complete_get_encryption_diversifier(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
// static inline hci_con_handle_t hci_subevent_le_long_term_key_request_get_connection_handle(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
/**
|
||||
* @brief Get field random_number from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST
|
||||
* @param event packet
|
||||
* @return random_number
|
||||
* @note: btstack_type D
|
||||
*/
|
||||
// static inline const uint8_t * hci_subevent_le_long_term_key_request_get_random_number(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
/**
|
||||
* @brief Get field encryption_diversifier from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST
|
||||
* @param event packet
|
||||
* @return encryption_diversifier
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
// static inline uint16_t hci_subevent_le_long_term_key_request_get_encryption_diversifier(const uint8_t * event){
|
||||
// not implemented yet
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t hci_subevent_le_remote_connection_parameter_request_get_connection_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field interval_min from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST
|
||||
* @param event packet
|
||||
* @return interval_min
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_interval_min(const uint8_t * event){
|
||||
return little_endian_read_16(event, 5);
|
||||
}
|
||||
/**
|
||||
* @brief Get field interval_max from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST
|
||||
* @param event packet
|
||||
* @return interval_max
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_interval_max(const uint8_t * event){
|
||||
return little_endian_read_16(event, 7);
|
||||
}
|
||||
/**
|
||||
* @brief Get field latency from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST
|
||||
* @param event packet
|
||||
* @return latency
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_latency(const uint8_t * event){
|
||||
return little_endian_read_16(event, 9);
|
||||
}
|
||||
/**
|
||||
* @brief Get field timeout from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST
|
||||
* @param event packet
|
||||
* @return timeout
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_timeout(const uint8_t * event){
|
||||
return little_endian_read_16(event, 11);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t hci_subevent_le_data_length_change_get_connection_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_tx_octets from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE
|
||||
* @param event packet
|
||||
* @return max_tx_octets
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_data_length_change_get_max_tx_octets(const uint8_t * event){
|
||||
return little_endian_read_16(event, 5);
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_tx_time from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE
|
||||
* @param event packet
|
||||
* @return max_tx_time
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_data_length_change_get_max_tx_time(const uint8_t * event){
|
||||
return little_endian_read_16(event, 7);
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_rx_octets from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE
|
||||
* @param event packet
|
||||
* @return max_rx_octets
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_data_length_change_get_max_rx_octets(const uint8_t * event){
|
||||
return little_endian_read_16(event, 9);
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_rx_time from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE
|
||||
* @param event packet
|
||||
* @return max_rx_time
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_data_length_change_get_max_rx_time(const uint8_t * event){
|
||||
return little_endian_read_16(event, 11);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_read_local_p256_public_key_complete_get_status(const uint8_t * event){
|
||||
return event[3];
|
||||
}
|
||||
/**
|
||||
* @brief Get field dhkey_x from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for dhkey_x
|
||||
* @note: btstack_type Q
|
||||
*/
|
||||
static inline void hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(const uint8_t * event, uint8_t * dhkey_x){
|
||||
reverse_bytes(&event[4], dhkey_x, 32);
|
||||
}
|
||||
/**
|
||||
* @brief Get field dhkey_y from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for dhkey_y
|
||||
* @note: btstack_type Q
|
||||
*/
|
||||
static inline void hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(const uint8_t * event, uint8_t * dhkey_y){
|
||||
reverse_bytes(&event[36], dhkey_y, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_generate_dhkey_complete_get_status(const uint8_t * event){
|
||||
return event[3];
|
||||
}
|
||||
/**
|
||||
* @brief Get field dhkey_x from event HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for dhkey_x
|
||||
* @note: btstack_type Q
|
||||
*/
|
||||
static inline void hci_subevent_le_generate_dhkey_complete_get_dhkey_x(const uint8_t * event, uint8_t * dhkey_x){
|
||||
reverse_bytes(&event[4], dhkey_x, 32);
|
||||
}
|
||||
/**
|
||||
* @brief Get field dhkey_y from event HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for dhkey_y
|
||||
* @note: btstack_type Q
|
||||
*/
|
||||
static inline void hci_subevent_le_generate_dhkey_complete_get_dhkey_y(const uint8_t * event, uint8_t * dhkey_y){
|
||||
reverse_bytes(&event[36], dhkey_y, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_status(const uint8_t * event){
|
||||
return event[3];
|
||||
}
|
||||
/**
|
||||
* @brief Get field connection_handle from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return connection_handle
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t hci_subevent_le_enhanced_connection_complete_get_connection_handle(const uint8_t * event){
|
||||
return little_endian_read_16(event, 4);
|
||||
}
|
||||
/**
|
||||
* @brief Get field role from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return role
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_role(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field peer_address_type from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return peer_address_type
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_peer_address_type(const uint8_t * event){
|
||||
return event[7];
|
||||
}
|
||||
/**
|
||||
* @brief Get field perr_addresss from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for perr_addresss
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void hci_subevent_le_enhanced_connection_complete_get_perr_addresss(const uint8_t * event, bd_addr_t perr_addresss){
|
||||
reverse_bd_addr(&event[8], perr_addresss);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_resolvable_private_addres from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for local_resolvable_private_addres
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void hci_subevent_le_enhanced_connection_complete_get_local_resolvable_private_addres(const uint8_t * event, bd_addr_t local_resolvable_private_addres){
|
||||
reverse_bd_addr(&event[14], local_resolvable_private_addres);
|
||||
}
|
||||
/**
|
||||
* @brief Get field peer_resolvable_private_addres from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @param Pointer to storage for peer_resolvable_private_addres
|
||||
* @note: btstack_type B
|
||||
*/
|
||||
static inline void hci_subevent_le_enhanced_connection_complete_get_peer_resolvable_private_addres(const uint8_t * event, bd_addr_t peer_resolvable_private_addres){
|
||||
reverse_bd_addr(&event[20], peer_resolvable_private_addres);
|
||||
}
|
||||
/**
|
||||
* @brief Get field conn_interval from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return conn_interval
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_conn_interval(const uint8_t * event){
|
||||
return little_endian_read_16(event, 26);
|
||||
}
|
||||
/**
|
||||
* @brief Get field conn_latency from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return conn_latency
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_conn_latency(const uint8_t * event){
|
||||
return little_endian_read_16(event, 28);
|
||||
}
|
||||
/**
|
||||
* @brief Get field supervision_timeout from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return supervision_timeout
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(const uint8_t * event){
|
||||
return little_endian_read_16(event, 30);
|
||||
}
|
||||
/**
|
||||
* @brief Get field master_clock_accuracy from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
* @return master_clock_accuracy
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_master_clock_accuracy(const uint8_t * event){
|
||||
return event[32];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field status from event HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE
|
||||
* @param event packet
|
||||
|
@ -95,11 +95,6 @@ void btstack_linked_list_add_tail(btstack_linked_list_t * list, btstack_linked_i
|
||||
it->next = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove data_source from run loop
|
||||
*
|
||||
* @note: assumes that btstack_data_source_t.next is first element in data_source
|
||||
*/
|
||||
int btstack_linked_list_remove(btstack_linked_list_t * list, btstack_linked_item_t *item){ // <-- remove item from list
|
||||
if (!item) return -1;
|
||||
btstack_linked_item_t *it;
|
||||
@ -124,6 +119,20 @@ int btstack_linked_list_remove(btstack_linked_list_t * list, btstack_linked_ite
|
||||
return counter;
|
||||
}
|
||||
|
||||
// get first element
|
||||
btstack_linked_item_t * btstack_linked_list_get_first_item(btstack_linked_list_t * list){
|
||||
return * list;
|
||||
}
|
||||
|
||||
// pop (get + remove) first element
|
||||
btstack_linked_item_t * btstack_linked_list_pop(btstack_linked_list_t * list){
|
||||
btstack_linked_item_t * item = *list;
|
||||
if (!item) return NULL;
|
||||
*list = item->next;
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Linked List Iterator implementation
|
||||
//
|
||||
|
@ -64,9 +64,13 @@ int btstack_linked_list_empty(btstack_linked_list_t * list);
|
||||
// add item to list as first element
|
||||
void btstack_linked_list_add(btstack_linked_list_t * list, btstack_linked_item_t *item);
|
||||
// add item to list as last element
|
||||
void btstack_linked_list_add_tail(btstack_linked_list_t * list, btstack_linked_item_t *item);
|
||||
void btstack_linked_list_add_tail(btstack_linked_list_t * list, btstack_linked_item_t *item);
|
||||
// pop (get + remove) first element
|
||||
btstack_linked_item_t * btstack_linked_list_pop(btstack_linked_list_t * list);
|
||||
// remove item from list
|
||||
int btstack_linked_list_remove(btstack_linked_list_t * list, btstack_linked_item_t *item);
|
||||
// get first element
|
||||
btstack_linked_item_t * btstack_linked_list_get_first_item(btstack_linked_list_t * list);
|
||||
// find the last item in the list
|
||||
btstack_linked_item_t * btstack_linked_list_get_last_item(btstack_linked_list_t * list);
|
||||
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compare two Bluetooth addresses
|
||||
* @param a
|
||||
@ -156,6 +155,14 @@ char char_for_nibble(int nibble){
|
||||
return '?';
|
||||
}
|
||||
|
||||
static inline char char_for_high_nibble(int value){
|
||||
return char_for_nibble((value >> 4) & 0x0f);
|
||||
}
|
||||
|
||||
static inline char char_for_low_nibble(int value){
|
||||
return char_for_nibble(value & 0x0f);
|
||||
}
|
||||
|
||||
int nibble_for_char(char c){
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
@ -175,30 +182,29 @@ void printf_hexdump(const void *data, int size){
|
||||
void log_info_hexdump(const void *data, int size){
|
||||
#ifdef ENABLE_LOG_INFO
|
||||
|
||||
const int items_per_line = 16;
|
||||
const int bytes_per_byte = 6; // strlen('0x12, ')
|
||||
const uint8_t low = 0x0F;
|
||||
const uint8_t high = 0xF0;
|
||||
#define ITEMS_PER_LINE 16
|
||||
// template '0x12, '
|
||||
#define BYTES_PER_BYTE 6
|
||||
|
||||
char buffer[bytes_per_byte*items_per_line+1];
|
||||
char buffer[BYTES_PER_BYTE*ITEMS_PER_LINE+1];
|
||||
int i, j;
|
||||
j = 0;
|
||||
for (i=0; i<size;i++){
|
||||
|
||||
// help static analyzer proof that j stays within bounds
|
||||
if (j > bytes_per_byte * (items_per_line-1)){
|
||||
if (j > BYTES_PER_BYTE * (ITEMS_PER_LINE-1)){
|
||||
j = 0;
|
||||
}
|
||||
|
||||
uint8_t byte = ((uint8_t *)data)[i];
|
||||
buffer[j++] = '0';
|
||||
buffer[j++] = 'x';
|
||||
buffer[j++] = char_for_nibble((byte & high) >> 4);
|
||||
buffer[j++] = char_for_nibble(byte & low);
|
||||
buffer[j++] = char_for_high_nibble(byte);
|
||||
buffer[j++] = char_for_low_nibble(byte);
|
||||
buffer[j++] = ',';
|
||||
buffer[j++] = ' ';
|
||||
|
||||
if (j >= bytes_per_byte * items_per_line ){
|
||||
if (j >= BYTES_PER_BYTE * ITEMS_PER_LINE ){
|
||||
buffer[j] = 0;
|
||||
log_info("%s", buffer);
|
||||
j = 0;
|
||||
@ -214,14 +220,12 @@ void log_info_hexdump(const void *data, int size){
|
||||
void log_info_key(const char * name, sm_key_t key){
|
||||
#ifdef ENABLE_LOG_INFO
|
||||
char buffer[16*2+1];
|
||||
const uint8_t low = 0x0F;
|
||||
const uint8_t high = 0xF0;
|
||||
int i;
|
||||
int j = 0;
|
||||
for (i=0; i<16;i++){
|
||||
uint8_t byte = key[i];
|
||||
buffer[j++] = char_for_nibble((byte & high) >> 4);
|
||||
buffer[j++] = char_for_nibble(byte & low);
|
||||
buffer[j++] = char_for_high_nibble(byte);
|
||||
buffer[j++] = char_for_low_nibble(byte);
|
||||
}
|
||||
buffer[j] = 0;
|
||||
log_info("%-6s %s", name, buffer);
|
||||
@ -247,13 +251,12 @@ static char uuid128_to_str_buffer[32+4+1];
|
||||
char * uuid128_to_str(uint8_t * uuid){
|
||||
int i;
|
||||
int j = 0;
|
||||
const uint8_t low = 0x0F;
|
||||
const uint8_t high = 0xF0;
|
||||
// after 4, 6, 8, and 10 bytes = XYXYXYXY-XYXY-XYXY-XYXY-XYXYXYXYXYXY, there's a dash
|
||||
const int dash_locations = (1<<3) | (1<<5) | (1<<7) | (1<<9);
|
||||
for (i=0;i<16;i++){
|
||||
uuid128_to_str_buffer[j++] = char_for_nibble((uuid[i] & high) >> 4);
|
||||
uuid128_to_str_buffer[j++] = char_for_nibble(uuid[i] & low);
|
||||
uint8_t byte = uuid[i];
|
||||
uuid128_to_str_buffer[j++] = char_for_high_nibble(byte);
|
||||
uuid128_to_str_buffer[j++] = char_for_low_nibble(byte);
|
||||
if (dash_locations & (1<<i)){
|
||||
uuid128_to_str_buffer[j++] = '-';
|
||||
}
|
||||
@ -269,8 +272,9 @@ char * bd_addr_to_str(bd_addr_t addr){
|
||||
char * p = bd_addr_to_str_buffer;
|
||||
int i;
|
||||
for (i = 0; i < 6 ; i++) {
|
||||
*p++ = char_for_nibble((addr[i] >> 4) & 0x0F);
|
||||
*p++ = char_for_nibble((addr[i] >> 0) & 0x0F);
|
||||
uint8_t byte = addr[i];
|
||||
*p++ = char_for_high_nibble(byte);
|
||||
*p++ = char_for_low_nibble(byte);
|
||||
*p++ = ':';
|
||||
}
|
||||
*--p = 0;
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack_cvsd_plc.h"
|
||||
#include "btstack_debug.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user