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:
Milanka Ringwald 2016-11-14 15:54:38 +01:00
commit 25234a7e05
135 changed files with 7300 additions and 1503 deletions

View File

@ -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
-------------- | ------
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-ez430-rf2560-develop) | [EZ430-RF256x Bluetooth Evaluation Tool for MSP430](http://www.ti.com/tool/ez430-rf256x)
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=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)
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=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
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=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
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-pic32-harmony-develop) | [Microchip's PIC32 Bluetooth Audio Development Kit](http://www.microchip.com/Developmenttools/ProductDetails.aspx?PartNO=DV320032)
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-wiced-develop) | [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
-------------- | ------
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-posix-h4-develop)| posix: Unix-based system talking to Bluetooth module via serial port
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-libusb-develop)| libusb: Unix-based system talking via USB Bluetooth dongle
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-daemon-develop)| daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=java-develop)| java: Java wrapper for daemon
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-ios-develop)| iOS: daemon for iOS jailbreak devices, C client-server API
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-mtk-develop)| mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API
![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-wiced-develop) | 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

View File

@ -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

View 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.
![Host Controller to Host connection](picts/host_chipset_connection.png){#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

View 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.

View File

@ -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}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -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

View File

@ -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*.

View File

@ -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

View File

@ -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]

View 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

View 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

View 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

View 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

View File

@ -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:

View File

@ -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);

View File

@ -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");

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -0,0 +1,5 @@
menuconfig BTSTACK
bool "BTstack support"
default n
help
This option enables the BTstack Bluetooth stack.

View File

@ -0,0 +1,5 @@
KERNEL_TYPE = nano
CONF_FILE ?= nrf5.conf
BOARD ?= nrf52_pca10040
include ${ZEPHYR_BASE}/Makefile.inc

View 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

View File

@ -0,0 +1,2 @@
obj-y += encoder/srce/
obj-y += decoder/srce/

View 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

View 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

View File

@ -0,0 +1,4 @@
obj-y += \
battery_service_server.o \
ccflags-y += -I${ZEPHYR_BASE}/subsys/btstack

View 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

View 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

View 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)

View File

@ -0,0 +1,4 @@
#!/bin/sh
nrfjprog --eraseall -f nrf51
nrfjprog --program outdir/nrf51_pca10028/zephyr.hex -f nrf51
nrfjprog --reset -f nrf51

View File

@ -0,0 +1,4 @@
#!/bin/sh
nrfjprog --eraseall -f nrf52
nrfjprog --program outdir/nrf52_pca10040/zephyr.hex -f nrf52
nrfjprog --reset -f nrf52

View 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;

View 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
View 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){};
}

View 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

View 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

View 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

View File

@ -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

View File

@ -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"/>

View File

@ -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>

View File

@ -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>

View File

@ -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")

View File

@ -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;

View File

@ -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)

View File

@ -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

View 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;
}

View 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

View File

@ -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
*/

View File

@ -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

View File

@ -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.

View 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 \

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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){

View File

@ -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;

View File

@ -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

View 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,

View 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);
}
}

View 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

View 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,

View 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);
}

View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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]);

View File

@ -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

View 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
View 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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
//

View File

@ -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);

View File

@ -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;

View File

@ -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