mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-09 07:13:43 +00:00
Merge branch 'develop' into a2dp
This commit is contained in:
commit
d3d88e8bb5
3
3rd-party/mbedtls/library/ecp.c
vendored
3
3rd-party/mbedtls/library/ecp.c
vendored
@ -1446,6 +1446,9 @@ static int ecp_mul_naive( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
(void) f_rng;
|
||||
(void) p_rng;
|
||||
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -35,11 +35,13 @@ GATT, SM of the Bluetooth 4.2 LE Central and Peripheral roles (QD ID 25340).
|
||||
|
||||
## Supported Protocols and Profiles
|
||||
|
||||
Protocols: L2CAP, RFCOMM, SDP, BNEP, ATT, SM
|
||||
Protocols: L2CAP, RFCOMM, SDP, BNEP, ATT, SM (incl. LE Secure Connections).
|
||||
|
||||
Profiles: GAP, IOP, HFP, HSP, SPP, PAN, GATT
|
||||
Profiles: GAP, IOP, HFP, HSP, SPP, PAN, GATT.
|
||||
|
||||
Coming next: A2DP, AVRCP, HID, HOGP, BLE, and more.
|
||||
Coming next: A2DP, AVRCP, HID, HOGP, BLE Mesh, and more.
|
||||
|
||||
For information on MFi/iAP2 support, please <a href="mailto:contact@bluekitchen-gmbh.com">contact us</a>.
|
||||
|
||||
## Evaluation Platforms
|
||||
|
||||
|
@ -31,9 +31,9 @@ Broadcom, whose Bluetooth + Wifi division has been acquired by the Cypress Semic
|
||||
|
||||
CSR, which has been acquired by Qualcomm, provides all relevant information on their Support website after signing an NDA.
|
||||
|
||||
Chipset | Type | HCI Transport | BD_ADDR (1) | SCO over HCI (2) | LE DLE | Multiple LE Roles (3)| BTstack folder | Comment
|
||||
Chipset | Type | HCI Transport | BD_ADDR (1) | SCO over HCI (2) | LE DLE | Multiple LE Roles | BTstack folder | Comment
|
||||
-------------------- |-----------| ---------------|--------------|------------------|--------|----------------------|----------------|---------
|
||||
Broadcom UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | Maybe | bcm | Max UART baudrate 3 mbps
|
||||
Broadcom UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | Maybe (3) | bcm | Max UART baudrate 3 mbps
|
||||
Broadcom USB Dongles | Dual mode | USB | Yes | No (didn't work) | No | No | bcm |
|
||||
CSR UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | No | csr |
|
||||
CSR USB Dongles | Dual mode | USB | Mostly | Yes | No | No | csr |
|
||||
@ -43,13 +43,13 @@ EM 9304 | LE | SPI, H4 | ? | n.a.
|
||||
Nordic nRF | LE | H4 | fixed random | n.a. | Yes | Yes | | Requires custom HCI firmware
|
||||
STM STLC2500D | Classic | H4 | No | No (didn't try) | n.a | n.a. | stlc2500d | Custom deep sleep management not supported
|
||||
Toshiba TC35661 | Dual mode | H4 | No | No (didn't try) | No | No | tc3566 | HCI version not tested. See below
|
||||
TI CC256x, WL183x | Dual mode | H4, H5, eHCILL | Yes | Yes | No | No | cc256x | Also WL185x, WL187x, and WL189x
|
||||
TI CC256x, WL183x | Dual mode | H4, H5, eHCILL | Yes | Yes | No | Yes for CC256XC | cc256x | Also WL185x, WL187x, and WL189x
|
||||
|
||||
**Notes**:
|
||||
|
||||
1. BD_ADDR: Not all Bluetooth chipset come with a fixed valid MAC Address. Better Broadcom and CSR dongles come with a MAC address from the dongle manufacturer, but cheaper ones might come with identical addresses.
|
||||
2. SCO over HCI: 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.
|
||||
2. Multiple LE Roles: Apple uses Broadcom Bluetooth+Wifi in their iOS devices and newer iOS versions support multipe concurrent LE roles,
|
||||
3. Multiple LE Roles: Apple uses Broadcom Bluetooth+Wifi in their iOS devices and newer iOS versions support multipe concurrent LE roles,
|
||||
so at least some Broadcom models support multiple concurrent LE roles.
|
||||
|
||||
## Broadcom
|
||||
@ -178,39 +178,39 @@ STMicroelectronics offers the Bluetooth V2.1 + EDR chipset STLC2500D that suppor
|
||||
|
||||
## 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 Texas Instruments CC256x series is currently in its fourth iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT (CC2567) model. 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.
|
||||
|
||||
The latest generation CC256xC chipsets support multiple LE roles in parallel.
|
||||
|
||||
The different CC256x chipset can be identified by the LMP Subversion returned by the *hci_read_local_version_information* command. TI also uses a numeric way (AKA) to identify their chipsets. The table shows the LMP Subversion and AKA number for the main CC256x series.
|
||||
|
||||
Chipset | LMP Subversion | AKA
|
||||
--------|----------------|-------
|
||||
CC2560 | 0x191f | 6.2.31
|
||||
CC2560A, CC2564 | 0x1B0F | 6.6.15
|
||||
CC256xB | 0x1B90 | 6.7.16
|
||||
CC256xC | 0x9a1a | 6.12.26
|
||||
|
||||
**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). The chipset confirms the change with a command complete event after which the local UART is set to the new speed. Oddly enough, the CC256x chipsets ignore the incoming CTS line during this particular command complete response. If the MCU gets UART overrun errors in this situation, a work around could be to set a timer for 100 ms and ignore all incoming data (i.e. the command complete event) during that period. Then, after the timeout, the UART can be set to the new speed safely.
|
||||
|
||||
**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.
|
||||
|
||||
**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.
|
||||
**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. For newer revisions, TI provides a main.bts and a ble_add_on.bts that need to be combined.
|
||||
|
||||
The Makefile at *chipset/cc256x/Makefile* is able to automatically download and convert the requested file. It does this by:
|
||||
The Makefile at *chipset/cc256x/Makefile.inc* 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 the Python script:
|
||||
|
||||
<!-- -->
|
||||
|
||||
./convert_bts_init_scripts.py
|
||||
./convert_bts_init_scripts.py main.bts [ble_add_on.bts] output_file.c
|
||||
|
||||
**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_chiopset_t* instance and passed to *hci_init* function.
|
||||
**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_chipset_t* instance and passed to *hci_init* function. *btstack_chipset_cc256x_lmp_subversion* provides the LMP Subversion for the selected init script.
|
||||
|
||||
SCO Data can be routed over HCI, so HFP Wide-Band Speech is supported.
|
||||
|
||||
|
@ -1,114 +1,190 @@
|
||||
#
|
||||
# Makefile to download and convert .bts files from
|
||||
# Makefile to download and convert TI's CC256x Service Pack .bts files from
|
||||
# http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
#
|
||||
BASE_URL = https://git.ti.com/ti-bt/service-packs/blobs/raw/a027ae390d8790e56e1c78136c78fe6537470e91
|
||||
# Service Packs for CC256xB v1.5 and CC256xC v1.0 downloaded from BlueKitchen company website
|
||||
# https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/p/560523/2056007#2056007
|
||||
|
||||
TI_GIT_REPO_URL = https://git.ti.com/ti-bt/service-packs/blobs/raw/a027ae390d8790e56e1c78136c78fe6537470e91
|
||||
BLUEKITCHEN_URL = https://bluekitchen-gmbh.com/files/
|
||||
CONVERSION_SCRIPT=$(BTSTACK_ROOT)/chipset/cc256x/convert_bts_init_scripts.py
|
||||
|
||||
# first generation CC2560 - TIInit_6.2.31.bts part of .zip archive
|
||||
|
||||
# First generation CC2560 - AKA TIInit_6.2.31.bts
|
||||
|
||||
# v2.44 - file part of .zip archive
|
||||
|
||||
CC2560_BT_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/d/da/CC2560_BT_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/d/da/CC2560_BT_SP_BTS.zip
|
||||
|
||||
bluetooth_init_cc2560_2.44.bts: CC2560_BT_SP_BTS.zip
|
||||
unzip CC2560_BT_SP_BTS.zip
|
||||
mv CC2560_BT_SP_BTS/bluetooth_init_cc2560_2.44.bts .
|
||||
rm -rf CC2560_BT_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2560_BT_SP_BTS.zip CC2560_BT_SP_BTS/bluetooth_init_cc2560_2.44.bts
|
||||
|
||||
# Second generation CC2560A and CC2564 - AKA TIInit_6.6.15.bts
|
||||
|
||||
# second generation CC2560A and CC2564 - TIInit_6.6.15.bts part of .zip archive
|
||||
# v2.14 - files part of .zip archive
|
||||
|
||||
CC2560A_BT_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/e/e7/CC2560A_BT_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/e/e7/CC2560A_BT_SP_BTS.zip
|
||||
|
||||
CC2564_BT_BLE_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/1/1e/CC2564_BT_BLE_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/1/1e/CC2564_BT_BLE_SP_BTS.zip
|
||||
|
||||
bluetooth_init_cc2560A_2.14.bts: CC2560A_BT_SP_BTS.zip
|
||||
unzip CC2560A_BT_SP_BTS.zip
|
||||
mv CC2560A_BT_SP_BTS/bluetooth_init_cc2560a_2.14.bts .
|
||||
rm -rf CC2560A_BT_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2560A_BT_SP_BTS.zip CC2560A_BT_SP_BTS/bluetooth_init_cc2560A_2.14.bts
|
||||
|
||||
bluetooth_init_cc2564_2.14.bts: CC2564_BT_BLE_SP_BTS.zip
|
||||
unzip CC2564_BT_BLE_SP_BTS.zip
|
||||
mv CC2564_BT_BLE_SP_BTS/bluetooth_init_cc2564_2.14.bts .
|
||||
rm -rf CC2564_BT_BLE_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2564_BT_BLE_SP_BTS.zip CC2564_BT_BLE_SP_BTS/bluetooth_init_cc2564_2.14.bts
|
||||
|
||||
# Third generation CC256xB - AKA TIInit_6.6.16.bts
|
||||
|
||||
# third generation
|
||||
|
||||
# versioned files for v1.2
|
||||
# v1.2 - versioned files TI Git Repo
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts:
|
||||
curl -O $(BASE_URL)/bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts:
|
||||
curl -O $(BASE_URL)/bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts
|
||||
|
||||
BLE_init_cc2564B_1.2.bts:
|
||||
curl -O $(BASE_URL)/BLE_init_cc2564B_1.2.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/BLE_init_cc2564B_1.2.bts
|
||||
|
||||
# unversioned files for v1.4
|
||||
# v1.4 - versioned files TI Git Repo
|
||||
TIInit_6.7.16_bt_spec_4.1.bts:
|
||||
curl -O https://git.ti.com/ti-bt/service-packs/blobs/raw/54f5c151dacc608b19ab2ce4c30e27a3983048b2/initscripts/TIInit_6.7.16_bt_spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O https://git.ti.com/ti-bt/service-packs/blobs/raw/54f5c151dacc608b19ab2ce4c30e27a3983048b2/initscripts/TIInit_6.7.16_bt_spec_4.1.bts
|
||||
|
||||
TIInit_6.7.16_ble_add-on.bts:
|
||||
curl -O https://git.ti.com/ti-bt/service-packs/blobs/raw/89c8db14929f10d75627b132690432cd71f5f54f/initscripts/TIInit_6.7.16_ble_add-on.bts
|
||||
TIInit_6.7.16_ble_add-on.bts:
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O https://git.ti.com/ti-bt/service-packs/blobs/raw/89c8db14929f10d75627b132690432cd71f5f54f/initscripts/TIInit_6.7.16_ble_add-on.bts
|
||||
|
||||
# v1.5 - unversioned files from BlueKitchen website, original: http://www.ti.com/tool/cc256xb-bt-sp
|
||||
cc256x_bt_sp_v1.5.zip:
|
||||
echo "Downloading $@"
|
||||
@curl -sS -O $(BLUEKITCHEN_URL)/cc256x_bt_sp_v1.5.zip
|
||||
|
||||
initscripts-TIInit_6.7.16_bt_spec_4.1.bts: cc256x_bt_sp_v1.5.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256x_bt_sp_v1.5.zip CC256X_BT_SP/v1.5/initscripts-TIInit_6.7.16_bt_spec_4.1.bts
|
||||
|
||||
initscripts-TIInit_6.7.16_ble_add-on.bts: cc256x_bt_sp_v1.5.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256x_bt_sp_v1.5.zip CC256X_BT_SP/v1.5/initscripts-TIInit_6.7.16_ble_add-on.bts
|
||||
|
||||
|
||||
# Fourth generation CC256xC - TIInit_6.12.26.bts
|
||||
|
||||
# v1.0 - unversioned files from BlueKitchen website, original: http://www.ti.com/tool/cc256xc-bt-sp
|
||||
cc256xc_bt_sp_v1.0.zip:
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(BLUEKITCHEN_URL)/cc256xc_bt_sp_v1.0.zip
|
||||
|
||||
initscripts-TIInit_6.12.26.bts: cc256xc_bt_sp_v1.0.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256xc_bt_sp_v1.0.zip CC256XC_BT_SP/v1.0/initscripts-TIInit_6.12.26.bts
|
||||
|
||||
initscripts-TIInit_6.12.26_ble_add-on.bts: cc256xc_bt_sp_v1.0.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256xc_bt_sp_v1.0.zip CC256XC_BT_SP/v1.0/initscripts-TIInit_6.12.26_ble_add-on.bts
|
||||
|
||||
|
||||
# Various scripts for WL chipsets
|
||||
|
||||
# WL chipset
|
||||
TIInit_11.8.32.bts:
|
||||
curl -O $(BASE_URL)/TIInit_11.8.32.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_11.8.32.bts
|
||||
|
||||
TIInit_12.10.28.bts:
|
||||
curl -O $(BASE_URL)/TIInit_12.10.28.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_12.10.28.bts
|
||||
|
||||
TIInit_12.8.32.bts:
|
||||
curl -O $(BASE_URL)/TIInit_12.8.32.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_12.8.32.bts
|
||||
|
||||
|
||||
|
||||
# convert to .c files based on main file and option add-on
|
||||
|
||||
# convert to .c files
|
||||
bluetooth_init_cc2560_2.44.c: bluetooth_init_cc2560_2.44.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560A_2.14.c: bluetooth_init_cc2560A_2.14.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564_2.14.c: bluetooth_init_cc2564_2.14.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c: bluetooth_init_cc2560B_1.2_BT_Spec_4.0.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c: bluetooth_init_cc2564B_1.2_BT_Spec_4.0.bts BLE_init_cc2564B_1.2.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.1.c: bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.1.c: bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts BLE_init_cc2564B_1.2.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.4_BT_Spec_4.1.c: TIInit_6.7.16_bt_spec_4.1.bts
|
||||
cp TIInit_6.7.16_bt_spec_4.1.bts bluetooth_init_cc2560B_1.4_BT_Spec_4.1.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c: TIInit_6.7.16_bt_spec_4.1.bts TIInit_6.7.16_ble_add-on.bts
|
||||
cp TIInit_6.7.16_bt_spec_4.1.bts bluetooth_init_cc2564B_1.4_BT_Spec_4.1.bts
|
||||
cp TIInit_6.7.16_ble_add-on.bts BLE_init_cc2564B_1.4.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.5_BT_Spec_4.1.c: initscripts-TIInit_6.7.16_bt_spec_4.1.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.5_BT_Spec_4.1.c: initscripts-TIInit_6.7.16_bt_spec_4.1.bts initscripts-TIInit_6.7.16_ble_add-on.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560C_1.0.c: initscripts-TIInit_6.12.26.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564C_1.0.c: initscripts-TIInit_6.12.26.bts initscripts-TIInit_6.12.26_ble_add-on.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_11.8.32.c: TIInit_11.8.32.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_12.10.28.c: TIInit_12.10.28.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_12.8.32.c: TIInit_12.8.32.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
all-scripts: bluetooth_init_cc2560_2.44.c bluetooth_init_cc2560A_2.14.c bluetooth_init_cc2564_2.14.bts bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c bluetooth_init_cc2560B_1.2_BT_Spec_4.1.c bluetooth_init_cc2564B_1.2_BT_Spec_4.1.c TIInit_11.8.32.c TIInit_12.10.28.c TIInit_12.8.32.c
|
||||
all-scripts: \
|
||||
bluetooth_init_cc2560_2.44.c \
|
||||
bluetooth_init_cc2560A_2.14.c \
|
||||
bluetooth_init_cc2564_2.14.bts \
|
||||
bluetooth_init_cc2560B_1.4_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2560B_1.5_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2564B_1.5_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2560C_1.0.c \
|
||||
bluetooth_init_cc2564C_1.0.c \
|
||||
TIInit_11.8.32.c \
|
||||
TIInit_12.10.28.c \
|
||||
TIInit_12.8.32.c \
|
||||
|
||||
clean-scripts:
|
||||
rm -fr CC256*.zip bluetooth_init_cc256*.bts bluetooth_init_cc256*.c TIInit_*.bts TIInit_*.c BLE_init_cc256*.bts BLE_init_cc256*.c
|
||||
rm -fr cc256x*.zip CC256*.zip bluetooth_init_cc256*.c TIInit*.c *.bts BLE_init_cc256*.c
|
||||
|
||||
|
||||
|
@ -88,10 +88,60 @@ static int16_t init_power_in_dB = 13; // 13 dBm
|
||||
// support for SCO over HCI
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
static int init_send_route_sco_over_hci = 0;
|
||||
// Follow recommendation from https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/t/397004
|
||||
// route SCO over HCI (connection type=1, tx buffer size = 120, tx buffer max latency= 720, accept packets with CRC Error
|
||||
static const uint8_t hci_route_sco_over_hci[] = {
|
||||
#if 1
|
||||
// Follow recommendation from https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/t/397004
|
||||
// route SCO over HCI (connection type=1, tx buffer size = 120, tx buffer max latency= 720, accept packets with CRC Error
|
||||
0x10, 0xfe, 0x05, 0x01, 0x78, 0xd0, 0x02, 0x01,
|
||||
#else
|
||||
// Configure SCO via I2S interface - 256 kbps
|
||||
// Send_HCI_VS_Write_CODEC_Config 0xFD06,
|
||||
0x06, 0xfd,
|
||||
// len
|
||||
34,
|
||||
//3072, - clock rate 3072000 hz
|
||||
0x00, 0x01,
|
||||
// 0x00 - clock direction: output = master
|
||||
0x00,
|
||||
// 8000, framesync frequency in hz
|
||||
0x40, 0x1f, 0x00, 0x00,
|
||||
// 0x0001, framesync duty cycle
|
||||
0x01, 0x00,
|
||||
// 1, framesync edge
|
||||
1,
|
||||
// 0x00, framesync polarity
|
||||
0x00,
|
||||
// 0x00, RESERVED
|
||||
0x00,
|
||||
// 16, channel 1 out size
|
||||
8, 0,
|
||||
// 0x0001, channel 1 out offset
|
||||
0x01, 0x00,
|
||||
// 1, channel 1 out edge
|
||||
1,
|
||||
// 16, channel 1 in size
|
||||
8, 0,
|
||||
// 0x0001, channel 1 in offset
|
||||
0x01, 0x00,
|
||||
// 0, channel 1 in edge
|
||||
0,
|
||||
// 0x00, RESERVED
|
||||
0x00,
|
||||
// 16, channel 2 out size
|
||||
8, 0,
|
||||
// 17, channel 2 out offset
|
||||
9, 0,
|
||||
// 0x01, channel 2 out edge
|
||||
0x01,
|
||||
// 16, channel 2 in size
|
||||
8, 0,
|
||||
// 17, channel 2 in offset
|
||||
9, 0,
|
||||
// 0x00, channel 2 in edge
|
||||
0x00,
|
||||
// 0x0001, RESERVED
|
||||
0x00
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -50,9 +50,21 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#include "btstack_chipset.h"
|
||||
|
||||
/**
|
||||
* Configure output power before HCI POWER_ON
|
||||
*/
|
||||
void btstack_chipset_cc256x_set_power(int16_t power_in_dB);
|
||||
|
||||
/**
|
||||
* Get chipset instance for CC256x series
|
||||
*/
|
||||
const btstack_chipset_t * btstack_chipset_cc256x_instance(void);
|
||||
|
||||
/**
|
||||
* Get LMP Subversion of compile-time init script
|
||||
*/
|
||||
uint16_t btstack_chipset_cc256x_lmp_subversion(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -9,16 +9,19 @@ import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
print('''
|
||||
CC256x init script conversion tool for use with BTstack, v0.1
|
||||
usage = '''
|
||||
CC256x init script conversion tool for use with BTstack, v0.2
|
||||
Copyright 2012-2014 BlueKitchen GmbH
|
||||
''')
|
||||
|
||||
usage = '''This script prepares init scripts for TI's
|
||||
CC256x chipsets for use with BTstack .
|
||||
Usage:
|
||||
$ ./convert_bts_init_scripts.py main.bts [ble-add-on.bts] output.c
|
||||
|
||||
Please download the Service Pack for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
Then, unzip it and copy the *.bts file into this folder and start the script again.
|
||||
Please specify the main .bts script and optionally the BLE Add-on to generate the init script .c file.
|
||||
|
||||
The Makefile include chipset/cc256x/Makefile.inc automates the process of downloading and converting .bts files.
|
||||
|
||||
If this is not an option, you can download the Service Packs for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
Then, unzip it and copy the *.bts file into this folder before start the script again.
|
||||
'''
|
||||
|
||||
fartext = '''
|
||||
@ -30,6 +33,14 @@ __attribute__((__progmem__))
|
||||
#endif
|
||||
'''
|
||||
|
||||
get_lmp_subversion = '''
|
||||
const uint16_t {prefix}_init_script_lmp_subversion = {lmp_subversion};
|
||||
|
||||
uint16_t btstack_chipset_cc256x_lmp_subversion(void){{
|
||||
return {prefix}_init_script_lmp_subversion;
|
||||
}}
|
||||
'''
|
||||
|
||||
data_indent = ' '
|
||||
|
||||
def read_little_endian_16(f):
|
||||
@ -96,15 +107,15 @@ def append_calibration_sequence(additions, str_list, data_indent):
|
||||
str_list.append("0x01, 0x80, 0xfd, 0x06, 0x3c, 0xf0, 0x5f, 0x00, 0x00, 0x00,\n\n")
|
||||
return 20
|
||||
|
||||
def convert_bts(main_bts_file, bts_add_on):
|
||||
|
||||
def convert_bts(output_file, main_bts_file, bts_add_on, aka, lmp_subversion):
|
||||
array_name = 'cc256x'
|
||||
c_file = main_bts_file.replace('bts', 'c')
|
||||
|
||||
input_files = [ main_bts_file ]
|
||||
if bts_add_on != "":
|
||||
input_files.append(bts_add_on)
|
||||
|
||||
with open(c_file, 'w') as fout:
|
||||
with open(output_file, 'w') as fout:
|
||||
|
||||
# assert script contains templates for configuration by BTstack
|
||||
have_eHCILL = False
|
||||
@ -113,7 +124,7 @@ def convert_bts(main_bts_file, bts_add_on):
|
||||
have_power_vector_edr3 = False;
|
||||
have_class2_single_power = False;
|
||||
|
||||
print("Creating {0}".format(c_file))
|
||||
print("Creating {0}".format(output_file))
|
||||
|
||||
part_size = 0
|
||||
|
||||
@ -223,18 +234,25 @@ def convert_bts(main_bts_file, bts_add_on):
|
||||
|
||||
fout.write( '// init script created from\n')
|
||||
fout.write( '// - {0}\n'.format(main_bts_file))
|
||||
if aka != "":
|
||||
fout.write( '// - AKA TIInit_{0}.bts\n'.format(aka))
|
||||
if bts_add_on != "":
|
||||
fout.write( '// - {0}\n'.format(bts_add_on))
|
||||
fout.write( '#include <stdint.h>\n')
|
||||
|
||||
fout.write( '#include "btstack_chipset_cc256x.h"\n')
|
||||
fout.write( '\n')
|
||||
# if aka != "":
|
||||
# fout.write( 'const char * {0}_init_script_aka = "{1}";\n'.format(array_name, aka))
|
||||
if lmp_subversion != 0:
|
||||
fout.write( get_lmp_subversion.format(prefix = array_name, lmp_subversion = "0x%04x" % lmp_subversion))
|
||||
part = 0
|
||||
size = 0
|
||||
for part_size in part_sizes:
|
||||
part += 1
|
||||
size += part_size
|
||||
print("- part", part, "size", part_size)
|
||||
print("- part %u, size %u" % (part,part_size))
|
||||
|
||||
print('- total size', size)
|
||||
print('- total size %u' % size)
|
||||
|
||||
print("\n".join(additions))
|
||||
|
||||
@ -266,61 +284,61 @@ def convert_bts(main_bts_file, bts_add_on):
|
||||
fout.write('const uint32_t {0}_init_script_size = {1};\n\n'.format(array_name,size));
|
||||
# fout.write('void main() {0} printf("size {1}\\n", {2}_init_script_size); {3}'.format('{', '%u', array_name,'}'));
|
||||
|
||||
# get list of *.bts files
|
||||
files = glob.glob('*.bts')
|
||||
if not files:
|
||||
# check usage: 2-3 param
|
||||
if len(sys.argv) < 3 or len(sys.argv) > 4:
|
||||
print(usage)
|
||||
sys.exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
# convert each of them
|
||||
for name in files:
|
||||
name_lower = name.lower()
|
||||
# skip BLE and AVRP add-ons
|
||||
if name_lower.startswith('ble_init_cc'):
|
||||
print("Skipping BLE add-on", name)
|
||||
continue
|
||||
if name_lower.startswith('avpr_init_cc'):
|
||||
print("Skipping AVPR add-on", name)
|
||||
continue
|
||||
if re.match("tiinit_.*_ble_add-on.bts", name_lower):
|
||||
print("Skipping BLE add-on", name)
|
||||
continue
|
||||
if re.match("initscripts_tiinit_.*_ble_add-on.bts", name_lower):
|
||||
print("Skipping BLE add-on", name)
|
||||
continue
|
||||
if re.match("initscripts_tiinit_.*_avpr_add-on.bts", name_lower):
|
||||
print("Skipping AVPR add-on", name)
|
||||
continue
|
||||
main_bts = sys.argv[1]
|
||||
add_on = ""
|
||||
if len(sys.argv) == 4:
|
||||
add_on = sys.argv[2]
|
||||
output_file = sys.argv[-1]
|
||||
|
||||
print "check", name
|
||||
|
||||
# check for BLE add-on
|
||||
add_on = ""
|
||||
name_parts = re.match('bluetooth_init_(.....+_...)_.*.bts', name)
|
||||
if name_parts:
|
||||
potential_add_on = 'BLE_init_%s.bts' % name_parts.group(1)
|
||||
if os.path.isfile(potential_add_on):
|
||||
add_on = potential_add_on
|
||||
print("Found", add_on, "add-on for", name)
|
||||
# get AKA from file names that include model name
|
||||
aka = ""
|
||||
lmp_subversion = 0
|
||||
name_lower = main_bts.lower()
|
||||
if 'cc2560_' in name_lower:
|
||||
aka = "6.2.31"
|
||||
if 'cc2560a_' in name_lower or 'cc2564_' in name_lower:
|
||||
aka = "6.6.15"
|
||||
if 'cc2560b_' in name_lower or 'cc2564b_' in name_lower:
|
||||
aka = "6.7.16"
|
||||
if 'cc2564c_' in name_lower:
|
||||
aka = "6.12.26"
|
||||
|
||||
name_parts = re.match('TIInit_(\d*\.\d*\.\d*)_.*.bts', name)
|
||||
if name_parts:
|
||||
potential_add_on = 'TIInit_%s_ble_add-on.bts' % name_parts.group(1)
|
||||
if os.path.isfile(potential_add_on):
|
||||
add_on = potential_add_on
|
||||
print("Found", add_on, "add-on for", name)
|
||||
# use AKA from .bts file that it
|
||||
name_parts = re.match('.*TIInit_(\d*\.\d*\.\d*).*.bts', main_bts)
|
||||
if name_parts:
|
||||
aka = name_parts.group(1)
|
||||
|
||||
name_parts = re.match('initscripts_TIInit_(\d*\.\d*\.\d*)_.*.bts', name)
|
||||
if name_parts:
|
||||
potential_add_on = 'initscripts_TIInit_%s_ble_add-on.bts' % name_parts.group(1)
|
||||
if os.path.isfile(potential_add_on):
|
||||
add_on = potential_add_on
|
||||
print("Found", add_on, "add-on for", name)
|
||||
# get lmp subversion from AKA
|
||||
lmp_subversion_for_aka = {
|
||||
'6.2.31' : 0x191f,
|
||||
'6.6.15' : 0x1B0F,
|
||||
'6.7.16' : 0x1B90,
|
||||
'6.12.26' : 0x9a1a
|
||||
}
|
||||
|
||||
convert_bts(name, add_on)
|
||||
if aka in lmp_subversion_for_aka:
|
||||
lmp_subversion = lmp_subversion_for_aka[aka]
|
||||
|
||||
# print summary
|
||||
|
||||
print ("Main file: %s"% main_bts)
|
||||
if add_on != "":
|
||||
print ("Add-on file: %s" % add_on)
|
||||
if aka != "":
|
||||
print ("- AKA TIInit_%s.bts" % aka)
|
||||
|
||||
if lmp_subversion:
|
||||
print ("- LMP Subversion: 0x%04x" % lmp_subversion)
|
||||
else:
|
||||
print ("- LMP Subversion: Unknown")
|
||||
|
||||
convert_bts(output_file, main_bts, add_on, aka, lmp_subversion)
|
||||
print
|
||||
|
||||
# done
|
||||
print('\nConversion(s) successful!\n')
|
||||
|
||||
|
||||
|
||||
|
@ -76,6 +76,7 @@ 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
|
||||
ENABLE_LE_SIGNED_WRITE | Enable LE Signed Writes in ATT/GATT
|
||||
|
||||
### Memory configuration directives {#sec:memoryConfigurationHowTo}
|
||||
|
||||
|
@ -160,15 +160,21 @@ def createIndex(btstackfolder, apis, githubfolder):
|
||||
functions[ref_function.group(1)] = codeReference(ref_function.group(1), githubfolder, api_tuple[0], linenr)
|
||||
continue
|
||||
|
||||
function = re.match('(.*?)\(.*\(*.*;\n', line)
|
||||
function = re.match('(.*?)\s*\(.*\(*.*;\n', line)
|
||||
if function:
|
||||
parts = function.group(1).split(" ");
|
||||
name = parts[len(parts)-1]
|
||||
if len(name) == 0:
|
||||
print(parts);
|
||||
sys.exit(10)
|
||||
functions[name] = codeReference( name, githubfolder, api_tuple[0], linenr)
|
||||
continue
|
||||
|
||||
function = re.match('.(.*?)\(.*\(*.*', line)
|
||||
function = re.match('.(.*?)\s*\(.*\(*.*', line)
|
||||
if function:
|
||||
if len(name) == 0:
|
||||
print(parts);
|
||||
sys.exit(10)
|
||||
parts = function.group(1).split(" ");
|
||||
name = parts[len(parts)-1]
|
||||
multiline_function_def = 1
|
||||
|
@ -224,9 +224,15 @@ hfp_hf_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} ${SBC_DECODE
|
||||
clean:
|
||||
rm -f ${EXAMPLES}
|
||||
rm -f *.o *.out *.hex *.exe
|
||||
rm -f ancs_client_demo.h profile.h spp_and_le_counter.h
|
||||
rm -f ancs_client_demo.h profile.h spp_and_le_counter.h le_counter.h le_streamer.h
|
||||
rm -rf *.dSYM
|
||||
rm -rf ${BTSTACK_ROOT}/ble/*.o
|
||||
rm -rf ${BTSTACK_ROOT}/src/*.o
|
||||
|
||||
rm -rf ${BTSTACK_ROOT}/src/ble/*.o
|
||||
rm -rf ${BTSTACK_ROOT}/src/ble/gatt-service/*.o
|
||||
rm -rf ${BTSTACK_ROOT}/example/*.o
|
||||
rm -rf ${BTSTACK_ROOT}/example/ancs_client_demo.h
|
||||
rm -rf ${BTSTACK_ROOT}/example/profile.h
|
||||
rm -rf ${BTSTACK_ROOT}/example/spp_and_le_counter.h
|
||||
rm -rf ${BTSTACK_ROOT}/example/le_counter.h
|
||||
rm -rf ${BTSTACK_ROOT}/example/le_streamer.h
|
||||
|
||||
|
@ -85,6 +85,9 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static btstack_packet_callback_registration_t sm_event_callback_registration;
|
||||
|
||||
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
@ -101,6 +104,10 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
|
||||
}
|
||||
|
||||
static void ancs_callback(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
const char * attribute_name;
|
||||
if (hci_event_packet_get_type(packet) != HCI_EVENT_ANCS_META) return;
|
||||
switch (hci_event_ancs_meta_get_subevent_code(packet)){
|
||||
@ -123,6 +130,9 @@ static void ancs_callback(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
UNUSED(argc);
|
||||
(void)argv;
|
||||
|
||||
printf("BTstack ANCS Client starting up...\n");
|
||||
|
||||
// register for HCI events
|
||||
|
@ -47,6 +47,9 @@ static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xD1, 0x15};
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
@ -65,6 +68,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
@ -129,6 +129,9 @@ static void continue_remote_names(void){
|
||||
*/
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t addr;
|
||||
int i;
|
||||
int numResponses;
|
||||
@ -272,6 +275,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
/* LISTING_START(MainConfiguration): Setup packet handler for GAP inquiry */
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
@ -231,6 +231,9 @@ static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
|
||||
/* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
|
@ -140,6 +140,10 @@ static void dump_service(gatt_client_service_t * service){
|
||||
|
||||
|
||||
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
int status;
|
||||
uint8_t battery_level;
|
||||
|
||||
@ -236,6 +240,9 @@ static void fill_advertising_report_from_packet(advertising_report_t * adv_repor
|
||||
}
|
||||
|
||||
static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
|
||||
uint8_t event = hci_event_packet_get_type(packet);
|
||||
@ -284,7 +291,7 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
||||
|
||||
if (cmdline_addr_found){
|
||||
printf("\nDisconnected %s\n", bd_addr_to_str(cmdline_addr));
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nDisconnected %s\n", bd_addr_to_str(report.address));
|
||||
@ -297,14 +304,17 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
static void usage(const char *name){
|
||||
fprintf(stderr, "\nUsage: %s [-a|--address aa:bb:cc:dd:ee:ff]\n", name);
|
||||
fprintf(stderr, "If no argument is provided, GATT browser will start scanning and connect to the first found device.\nTo connect to a specific device use argument [-a].\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
int arg = 1;
|
||||
cmdline_addr_found = 0;
|
||||
|
||||
@ -319,6 +329,10 @@ int btstack_main(int argc, const char * argv[]){
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
#endif
|
||||
|
||||
hci_event_callback_registration.callback = &hci_event_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
@ -164,6 +164,9 @@ static void fill_advertising_report_from_packet(advertising_report_t * report, u
|
||||
|
||||
/* LISTING_START(GATTBrowserHCIPacketHandler): Connecting and disconnecting from the GATT client */
|
||||
static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
advertising_report_t report;
|
||||
|
||||
@ -198,7 +201,6 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
|
||||
break;
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
printf("\nGATT browser - DISCONNECTED\n");
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -221,6 +223,10 @@ static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *pac
|
||||
static int search_services = 1;
|
||||
|
||||
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
gatt_client_service_t service;
|
||||
gatt_client_characteristic_t characteristic;
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
@ -259,14 +265,17 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
|
||||
}
|
||||
/* LISTING_END */
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
static void usage(const char *name){
|
||||
fprintf(stderr, "\nUsage: %s [-a|--address aa:bb:cc:dd:ee:ff]\n", name);
|
||||
fprintf(stderr, "If no argument is provided, GATT browser will start scanning and connect to the first found device.\nTo connect to a specific device use argument [-a].\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
int arg = 1;
|
||||
cmdline_addr_found = 0;
|
||||
|
||||
@ -280,6 +289,10 @@ int btstack_main(int argc, const char * argv[]){
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
#endif
|
||||
|
||||
gatt_client_setup();
|
||||
|
||||
|
@ -65,14 +65,8 @@ uint8_t hfp_service_buffer[150];
|
||||
const uint8_t rfcomm_channel_nr = 1;
|
||||
const char hfp_ag_service_name[] = "BTstack HFP AG Test";
|
||||
|
||||
// PTS
|
||||
// static bd_addr_t device_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46};
|
||||
// BT-201
|
||||
// static bd_addr_t device_addr = {0x00, 0x07, 0xB0, 0x83, 0x02, 0x5E};
|
||||
// CC256x
|
||||
// bd_addr_t device_addr = { 0xD0, 0x39, 0x72, 0xCD, 0x83, 0x45};
|
||||
// Mini Jambox
|
||||
bd_addr_t device_addr = { 0x00, 0x15, 0x83, 0x5F, 0x9D, 0x46};
|
||||
static bd_addr_t device_addr;
|
||||
static const char * device_addr_string = "00:15:83:5F:9D:46";
|
||||
|
||||
// static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC};
|
||||
static uint8_t codecs[] = {HFP_CODEC_CVSD};
|
||||
@ -208,6 +202,8 @@ static void continue_remote_names(void){
|
||||
}
|
||||
|
||||
static void inquiry_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t addr;
|
||||
int i;
|
||||
int numResponses;
|
||||
@ -335,6 +331,9 @@ static void show_usage(void){
|
||||
}
|
||||
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
cmd = btstack_stdin_read();
|
||||
switch (cmd){
|
||||
case 'a':
|
||||
@ -555,6 +554,8 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
#endif
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
|
||||
UNUSED(channel);
|
||||
|
||||
switch (packet_type){
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (event[0]){
|
||||
@ -684,6 +685,8 @@ static hfp_phone_number_t subscriber_number = {
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
sco_demo_init();
|
||||
|
||||
@ -729,6 +732,9 @@ int btstack_main(int argc, const char * argv[]){
|
||||
printf("SDP service record size: %u\n", de_get_len( hfp_service_buffer));
|
||||
sdp_register_service(hfp_service_buffer);
|
||||
|
||||
// parse humand readable Bluetooth address
|
||||
sscanf_bd_addr(device_addr_string, device_addr);
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
btstack_stdin_setup(stdin_process);
|
||||
#endif
|
||||
|
@ -152,6 +152,8 @@ static void show_usage(void){
|
||||
}
|
||||
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
cmd = btstack_stdin_read();
|
||||
|
||||
@ -433,7 +435,8 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
#endif
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
|
||||
|
||||
UNUSED(channel);
|
||||
|
||||
switch (packet_type){
|
||||
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
@ -552,6 +555,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
/* LISTING_START(MainConfiguration): Setup HFP Hands-Free unit */
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
sco_demo_init();
|
||||
|
||||
|
@ -121,6 +121,8 @@ static void show_usage(void){
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
char buffer = btstack_stdin_read();
|
||||
|
||||
@ -178,6 +180,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
#endif
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
|
||||
UNUSED(channel);
|
||||
|
||||
switch (packet_type){
|
||||
|
||||
@ -273,6 +276,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
/* LISTING_START(MainConfiguration): Setup HSP Audio Gateway */
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
sco_demo_init();
|
||||
|
||||
|
@ -121,6 +121,8 @@ static void show_usage(void){
|
||||
|
||||
#ifdef HAVE_POSIX_STDIN
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
char buffer = btstack_stdin_read();
|
||||
|
||||
@ -178,6 +180,8 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
#endif
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){
|
||||
UNUSED(channel);
|
||||
|
||||
switch (packet_type){
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
sco_demo_receive(event, event_size);
|
||||
@ -275,6 +279,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
||||
/* LISTING_START(MainConfiguration): Setup HSP Headset */
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
sco_demo_init();
|
||||
|
||||
|
@ -176,6 +176,9 @@ static void heartbeat_handler(struct btstack_timer_source *ts){
|
||||
|
||||
/* LISTING_START(packetHandler): Packet Handler */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
@ -207,6 +210,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
// - if buffer != NULL, copy data and return number bytes copied
|
||||
// @param offset defines start of attribute value
|
||||
static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
|
||||
UNUSED(connection_handle);
|
||||
|
||||
if (att_handle == ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){
|
||||
if (buffer){
|
||||
memcpy(buffer, &counter_string[offset], buffer_size);
|
||||
@ -230,6 +235,10 @@ static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t a
|
||||
|
||||
/* LISTING_START(attWrite): ATT Write */
|
||||
static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
UNUSED(transaction_mode);
|
||||
UNUSED(offset);
|
||||
UNUSED(buffer_size);
|
||||
|
||||
if (att_handle != ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_CLIENT_CONFIGURATION_HANDLE) return 0;
|
||||
le_notification_enabled = little_endian_read_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
|
||||
con_handle = connection_handle;
|
||||
|
@ -135,7 +135,7 @@ static void test_reset(void){
|
||||
}
|
||||
|
||||
static void test_track_sent(int bytes_sent){
|
||||
test_data_sent += test_data_len;
|
||||
test_data_sent += bytes_sent;
|
||||
// evaluate
|
||||
uint32_t now = btstack_run_loop_get_time_ms();
|
||||
uint32_t time_passed = now - test_data_start;
|
||||
@ -160,6 +160,9 @@ static void test_track_sent(int bytes_sent){
|
||||
|
||||
/* LISTING_START(packetHandler): Packet Handler */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
int mtu;
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
@ -229,6 +232,9 @@ static void streamer(void){
|
||||
|
||||
/* LISTING_START(attWrite): ATT Write */
|
||||
static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
UNUSED(con_handle);
|
||||
UNUSED(offset);
|
||||
|
||||
// printf("att_write_callback att_handle %04x, transaction mode %u\n", att_handle, transaction_mode);
|
||||
if (transaction_mode != ATT_TRANSACTION_MODE_NONE) return 0;
|
||||
switch(att_handle){
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_defines.h"
|
||||
#include "hal_led.h"
|
||||
|
||||
#define HEARTBEAT_PERIOD_MS 1000
|
||||
@ -65,7 +66,9 @@ static btstack_timer_source_t heartbeat;
|
||||
*/
|
||||
|
||||
/* LISTING_START(LEDToggler): Periodic counter */
|
||||
static void heartbeat_handler(btstack_timer_source_t *ts){
|
||||
static void heartbeat_handler(btstack_timer_source_t *ts){
|
||||
UNUSED(ts);
|
||||
|
||||
// increment counter
|
||||
char lineBuffer[30];
|
||||
sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter);
|
||||
@ -89,6 +92,8 @@ static void heartbeat_handler(btstack_timer_source_t *ts){
|
||||
/* LISTING_START(MainConfiguration): Setup heartbeat timer */
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
// set one-shot timer
|
||||
heartbeat.process = &heartbeat_handler;
|
||||
|
@ -269,6 +269,9 @@ static int tap_alloc(char *dev, bd_addr_t bd_addr)
|
||||
/* LISTING_START(processTapData): Process incoming network packets */
|
||||
static void process_tap_dev_data(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type)
|
||||
{
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
ssize_t len;
|
||||
len = read(ds->fd, network_buffer, sizeof(network_buffer));
|
||||
if (len <= 0){
|
||||
@ -317,6 +320,10 @@ static char * get_string_from_data_element(uint8_t * element){
|
||||
*/
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
|
||||
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
des_iterator_t des_list_it;
|
||||
des_iterator_t prot_it;
|
||||
char *str;
|
||||
@ -424,6 +431,8 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
/* LISTING_PAUSE */
|
||||
UNUSED(channel);
|
||||
|
||||
int rc;
|
||||
uint8_t event;
|
||||
bd_addr_t event_addr;
|
||||
@ -561,6 +570,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
|
||||
printf("Client HCI init done\n");
|
||||
|
||||
panu_setup();
|
||||
|
@ -57,6 +57,8 @@
|
||||
#define SCO_DEMO_MODE_SINE 0
|
||||
#define SCO_DEMO_MODE_ASCII 1
|
||||
#define SCO_DEMO_MODE_COUNTER 2
|
||||
#define SCO_DEMO_MODE_55 3
|
||||
#define SCO_DEMO_MODE_00 4
|
||||
|
||||
|
||||
// SCO demo configuration
|
||||
@ -76,6 +78,7 @@
|
||||
#define USE_PORTAUDIO
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_PORTAUDIO
|
||||
#include <portaudio.h>
|
||||
#include "btstack_ring_buffer.h"
|
||||
@ -105,12 +108,13 @@ static uint8_t ring_buffer_storage[2*MSBC_PREBUFFER_BYTES];
|
||||
static btstack_ring_buffer_t ring_buffer;
|
||||
#endif
|
||||
|
||||
|
||||
static int dump_data = 1;
|
||||
static int count_sent = 0;
|
||||
static int count_received = 0;
|
||||
static uint8_t negotiated_codec = 0;
|
||||
static int num_audio_frames = 0;
|
||||
#if SCO_DEMO_MODE != SCO_DEMO_MODE_55
|
||||
static int phase = 0;
|
||||
#endif
|
||||
|
||||
FILE * msbc_file_in;
|
||||
FILE * msbc_file_out;
|
||||
@ -141,7 +145,6 @@ static const int16_t sine_int16[] = {
|
||||
-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++){
|
||||
@ -160,6 +163,7 @@ static void sco_demo_sine_wave_int16(int num_samples, int16_t * data){
|
||||
}
|
||||
}
|
||||
}
|
||||
static int num_audio_frames = 0;
|
||||
|
||||
static void sco_demo_fill_audio_frame(void){
|
||||
if (!hfp_msbc_can_encode_audio_frame_now()) return;
|
||||
@ -169,7 +173,6 @@ static void sco_demo_fill_audio_frame(void){
|
||||
hfp_msbc_encode_audio_frame(sample_buffer);
|
||||
num_audio_frames++;
|
||||
}
|
||||
|
||||
#ifdef SCO_WAV_FILENAME
|
||||
static btstack_sbc_decoder_state_t decoder_state;
|
||||
static btstack_cvsd_plc_state_t cvsd_plc_state;
|
||||
@ -205,6 +208,9 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||
#endif
|
||||
|
||||
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
|
||||
UNUSED(context);
|
||||
UNUSED(sample_rate);
|
||||
|
||||
// printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels);
|
||||
#ifdef USE_PORTAUDIO
|
||||
if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= MSBC_PREBUFFER_BYTES){
|
||||
@ -218,6 +224,8 @@ static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, i
|
||||
}
|
||||
btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
|
||||
// printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer));
|
||||
#else
|
||||
UNUSED(num_channels);
|
||||
#endif
|
||||
|
||||
if (!num_samples_to_write) return;
|
||||
@ -343,6 +351,7 @@ static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){
|
||||
|
||||
// memcpy(audio_frame_out, (int8_t*)(packet+3), 24);
|
||||
btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out);
|
||||
// int8_t * audio_frame_out = (int8_t*)&packet[3];
|
||||
|
||||
wav_writer_write_int8(samples_to_write, audio_frame_out);
|
||||
num_samples_to_write -= samples_to_write;
|
||||
@ -459,7 +468,8 @@ void sco_demo_init(void){
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sco_report(void){
|
||||
void sco_report(void);
|
||||
void sco_report(void){
|
||||
printf("SCO: sent %u, received %u\n", count_sent, count_received);
|
||||
}
|
||||
|
||||
@ -494,16 +504,32 @@ void sco_demo_send(hci_con_handle_t sco_handle){
|
||||
} else {
|
||||
sco_demo_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3));
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
|
||||
memset(&sco_packet[3], phase++, audio_samples_per_packet);
|
||||
if (phase > 'z') phase = 'a';
|
||||
#else
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
|
||||
int j;
|
||||
for (j=0;j<audio_samples_per_packet;j++){
|
||||
sco_packet[3+j] = phase++;
|
||||
}
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_55
|
||||
int j;
|
||||
for (j=0;j<audio_samples_per_packet;j++){
|
||||
// sco_packet[3+j] = j & 1 ? 0x35 : 0x53;
|
||||
sco_packet[3+j] = 0x55;
|
||||
}
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_00
|
||||
int j;
|
||||
for (j=0;j<audio_samples_per_packet;j++){
|
||||
sco_packet[3+j] = 0x00;
|
||||
}
|
||||
// additional hack
|
||||
// big_endian_store_16(sco_packet, 5, phase++);
|
||||
(void) phase;
|
||||
#endif
|
||||
|
||||
hci_send_sco_packet_buffer(sco_packet_length);
|
||||
@ -512,19 +538,41 @@ void sco_demo_send(hci_con_handle_t sco_handle){
|
||||
hci_request_sco_can_send_now_event();
|
||||
|
||||
count_sent++;
|
||||
#if SCO_DEMO_MODE != SCO_DEMO_MODE_55
|
||||
if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process received data
|
||||
*/
|
||||
#define ANSI_COLOR_RED "\x1b[31m"
|
||||
#define ANSI_COLOR_GREEN "\x1b[32m"
|
||||
#define ANSI_COLOR_YELLOW "\x1b[33m"
|
||||
#define ANSI_COLOR_BLUE "\x1b[34m"
|
||||
#define ANSI_COLOR_MAGENTA "\x1b[35m"
|
||||
#define ANSI_COLOR_CYAN "\x1b[36m"
|
||||
#define ANSI_COLOR_RESET "\x1b[0m"
|
||||
|
||||
void sco_demo_receive(uint8_t * packet, uint16_t size){
|
||||
|
||||
dump_data = 1;
|
||||
|
||||
count_received++;
|
||||
// if ((count_received % SCO_REPORT_PERIOD) == 0) sco_report();
|
||||
static uint32_t packets = 0;
|
||||
static uint32_t crc_errors = 0;
|
||||
static uint32_t data_received = 0;
|
||||
static uint32_t byte_errors = 0;
|
||||
|
||||
data_received += size - 3;
|
||||
packets++;
|
||||
if (data_received > 100000){
|
||||
printf("Summary: data %07u, packets %04u, packet with crc errors %0u, byte errors %04u\n", data_received, packets, crc_errors, byte_errors);
|
||||
crc_errors = 0;
|
||||
byte_errors = 0;
|
||||
data_received = 0;
|
||||
packets = 0;
|
||||
}
|
||||
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
|
||||
#ifdef SCO_WAV_FILENAME
|
||||
@ -538,23 +586,59 @@ void sco_demo_receive(uint8_t * packet, uint16_t size){
|
||||
#endif
|
||||
|
||||
if (packet[1] & 0x30){
|
||||
printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4);
|
||||
log_info("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4);
|
||||
printf_hexdump(&packet[3], size-3);
|
||||
|
||||
crc_errors++;
|
||||
// printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4);
|
||||
// printf_hexdump(&packet[3], size-3);
|
||||
return;
|
||||
}
|
||||
if (dump_data){
|
||||
printf("data: ");
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
|
||||
printf("data: ");
|
||||
int i;
|
||||
for (i=3;i<size;i++){
|
||||
printf("%c", packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
dump_data = 0;
|
||||
#else
|
||||
printf_hexdump(&packet[3], size-3);
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
|
||||
// colored hexdump with expected
|
||||
static uint8_t expected_byte = 0;
|
||||
int i;
|
||||
printf("data: ");
|
||||
for (i=3;i<size;i++){
|
||||
if (packet[i] != expected_byte){
|
||||
printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]);
|
||||
} else {
|
||||
printf("%02x ", packet[i]);
|
||||
}
|
||||
expected_byte = packet[i]+1;
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
#if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE_00
|
||||
int i;
|
||||
int contains_error = 0;
|
||||
for (i=3;i<size;i++){
|
||||
if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){
|
||||
contains_error = 1;
|
||||
byte_errors++;
|
||||
}
|
||||
}
|
||||
if (contains_error){
|
||||
printf("data: ");
|
||||
for (i=0;i<3;i++){
|
||||
printf("%02x ", packet[i]);
|
||||
}
|
||||
for (i=3;i<size;i++){
|
||||
if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){
|
||||
printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]);
|
||||
} else {
|
||||
printf("%02x ", packet[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +112,9 @@ static void sdp_client_init(void){
|
||||
|
||||
/* LISTING_START(SDPQueryUUID): Querying the a list of service records on a remote device. */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
uint8_t event = hci_event_packet_get_type(packet);
|
||||
|
||||
@ -161,6 +164,10 @@ static char * get_string_from_data_element(uint8_t * element){
|
||||
|
||||
/* LISTING_START(HandleSDPQUeryResult): Extracting BNEP Protcol UUID and L2CAP PSM */
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
/* LISTING_PAUSE */
|
||||
des_iterator_t des_list_it;
|
||||
des_iterator_t prot_it;
|
||||
@ -266,6 +273,9 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("Client HCI init done\r\n");
|
||||
|
||||
sdp_client_init();
|
||||
|
@ -107,6 +107,9 @@ static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
|
||||
|
||||
/* LISTING_START(SDPQueryUUID): Querying a list of service records on a remote device. */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
uint8_t event = hci_event_packet_get_type(packet);
|
||||
|
||||
@ -144,6 +147,10 @@ static void assertBuffer(int size){
|
||||
|
||||
/* LISTING_START(HandleSDPQUeryResult): Handling query result chunks. */
|
||||
static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
// handle new record
|
||||
@ -162,7 +169,6 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel
|
||||
break;
|
||||
case SDP_EVENT_QUERY_COMPLETE:
|
||||
printf("General query done with status %d.\n\n", sdp_event_query_complete_get_status(packet));
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -170,7 +176,9 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("Client HCI init done\r\n");
|
||||
|
||||
sdp_client_init();
|
||||
|
@ -71,6 +71,9 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
uint8_t event = hci_event_packet_get_type(packet);
|
||||
|
||||
@ -110,6 +113,10 @@ static void report_found_services(void){
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
store_found_service(sdp_event_query_rfcomm_service_get_name(packet),
|
||||
@ -124,6 +131,9 @@ static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uin
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("Client HCI init done\r\n");
|
||||
|
||||
// register for HCI events
|
||||
|
@ -129,6 +129,9 @@ static void sm_pairing_central_setup(void){
|
||||
/* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
hci_con_handle_t con_handle;
|
||||
|
||||
|
@ -147,6 +147,9 @@ 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){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t addr;
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
|
@ -99,6 +99,8 @@ uint8_t adv_data_len = sizeof(adv_data);
|
||||
*/
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
uint8_t rfcomm_channel_nr;
|
||||
uint16_t mtu;
|
||||
@ -180,6 +182,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
// - if buffer != NULL, copy data and return number bytes copied
|
||||
// @param offset defines start of attribute value
|
||||
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){
|
||||
UNUSED(con_handle);
|
||||
|
||||
if (att_handle == ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){
|
||||
if (buffer){
|
||||
memcpy(buffer, &counter_string[offset], buffer_size);
|
||||
|
@ -170,6 +170,8 @@ static void one_shot_timer_setup(void){
|
||||
|
||||
/* LISTING_START(SppServerPacketHandler): SPP Server - Heartbeat Counter over RFCOMM */
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
|
||||
/* LISTING_PAUSE */
|
||||
bd_addr_t event_addr;
|
||||
uint8_t rfcomm_channel_nr;
|
||||
@ -244,6 +246,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
one_shot_timer_setup();
|
||||
spp_service_setup();
|
||||
|
||||
|
@ -107,7 +107,7 @@ static void test_reset(void){
|
||||
}
|
||||
|
||||
static void test_track_sent(int bytes_sent){
|
||||
test_data_sent += test_data_len;
|
||||
test_data_sent += bytes_sent;
|
||||
// evaluate
|
||||
uint32_t now = btstack_run_loop_get_time_ms();
|
||||
uint32_t time_passed = now - test_data_start;
|
||||
@ -150,6 +150,9 @@ static void send_packet(void){
|
||||
}
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
uint8_t event = hci_event_packet_get_type(packet);
|
||||
switch (event) {
|
||||
@ -204,6 +207,10 @@ static void handle_found_service(const char * name, uint8_t port){
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
handle_found_service(sdp_event_query_rfcomm_service_get_name(packet),
|
||||
@ -226,6 +233,8 @@ static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uin
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
create_test_data();
|
||||
|
||||
|
@ -117,11 +117,40 @@ static void btstack_run_loop_embedded_set_timer(btstack_timer_source_t *ts, uint
|
||||
#endif
|
||||
}
|
||||
|
||||
// under the assumption that a tick value is +/- 2^30 away from now, calculate the upper bits of the tick value
|
||||
static int btstack_run_loop_embedded_reconstruct_higher_bits(uint32_t now, uint32_t ticks){
|
||||
int32_t delta = ticks - now;
|
||||
if (delta >= 0){
|
||||
if (ticks >= now) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (ticks < now) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add timer to run_loop (keep list sorted)
|
||||
*/
|
||||
static void btstack_run_loop_embedded_add_timer(btstack_timer_source_t *ts){
|
||||
#ifdef TIMER_SUPPORT
|
||||
|
||||
#ifdef HAVE_EMBEDDED_TICK
|
||||
uint32_t now = system_ticks;
|
||||
#endif
|
||||
#ifdef HAVE_EMBEDDED_TIME_MS
|
||||
uint32_t now = hal_time_ms();
|
||||
#endif
|
||||
|
||||
uint32_t new_low = ts->timeout;
|
||||
int new_high = btstack_run_loop_embedded_reconstruct_higher_bits(now, new_low);
|
||||
|
||||
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
|
||||
@ -129,7 +158,9 @@ static void btstack_run_loop_embedded_add_timer(btstack_timer_source_t *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) {
|
||||
uint32_t next_low = ((btstack_timer_source_t *) it->next)->timeout;
|
||||
int next_high = btstack_run_loop_embedded_reconstruct_higher_bits(now, next_low);
|
||||
if (new_high < next_high || ((new_high == next_high) && (new_low < next_low))){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -185,17 +216,21 @@ void btstack_run_loop_embedded_execute_once(void) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TIMER_SUPPORT
|
||||
|
||||
#ifdef HAVE_EMBEDDED_TICK
|
||||
uint32_t now = system_ticks;
|
||||
#endif
|
||||
#ifdef HAVE_EMBEDDED_TIME_MS
|
||||
uint32_t now = hal_time_ms();
|
||||
#endif
|
||||
#ifdef TIMER_SUPPORT
|
||||
|
||||
// process timers
|
||||
while (timers) {
|
||||
btstack_timer_source_t *ts = (btstack_timer_source_t *) timers;
|
||||
if (ts->timeout > now) break;
|
||||
uint32_t timeout_low = ts->timeout;
|
||||
int timeout_high = btstack_run_loop_embedded_reconstruct_higher_bits(now, timeout_low);
|
||||
if (timeout_high > 0 || ((timeout_high == 0) && (timeout_low > now))) break;
|
||||
btstack_run_loop_remove_timer(ts);
|
||||
ts->process(ts);
|
||||
}
|
||||
|
@ -69,8 +69,9 @@
|
||||
#define HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
|
||||
#endif
|
||||
|
||||
#define ASYNC_BUFFERS 3
|
||||
#define ISOC_BUFFERS 10
|
||||
#define ACL_IN_BUFFER_COUNT 3
|
||||
#define EVENT_IN_BUFFER_COUNT 3
|
||||
#define SCO_IN_BUFFER_COUNT 10
|
||||
|
||||
#define ASYNC_POLLING_INTERVAL_MS 1
|
||||
|
||||
@ -98,8 +99,8 @@
|
||||
|
||||
// Outgoing SCO packet queue
|
||||
// simplified ring buffer implementation
|
||||
#define SCO_RING_BUFFER_COUNT (8)
|
||||
#define SCO_RING_BUFFER_SIZE (SCO_RING_BUFFER_COUNT * SCO_PACKET_SIZE)
|
||||
#define SCO_OUT_BUFFER_COUNT (8)
|
||||
#define SCO_OUT_BUFFER_SIZE (SCO_OUT_BUFFER_COUNT * SCO_PACKET_SIZE)
|
||||
|
||||
// seems to be the max depth for USB 3
|
||||
#define USB_MAX_PATH_LEN 7
|
||||
@ -138,8 +139,8 @@ static libusb_device_handle * handle;
|
||||
|
||||
static struct libusb_transfer *command_out_transfer;
|
||||
static struct libusb_transfer *acl_out_transfer;
|
||||
static struct libusb_transfer *event_in_transfer[ASYNC_BUFFERS];
|
||||
static struct libusb_transfer *acl_in_transfer[ASYNC_BUFFERS];
|
||||
static struct libusb_transfer *event_in_transfer[EVENT_IN_BUFFER_COUNT];
|
||||
static struct libusb_transfer *acl_in_transfer[ACL_IN_BUFFER_COUNT];
|
||||
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
|
||||
@ -152,23 +153,23 @@ static H2_SCO_STATE sco_state;
|
||||
static uint8_t sco_buffer[255+3 + SCO_PACKET_SIZE];
|
||||
static uint16_t sco_read_pos;
|
||||
static uint16_t sco_bytes_to_read;
|
||||
static struct libusb_transfer *sco_in_transfer[ISOC_BUFFERS];
|
||||
static uint8_t hci_sco_in_buffer[ISOC_BUFFERS][SCO_PACKET_SIZE];
|
||||
static struct libusb_transfer *sco_in_transfer[SCO_IN_BUFFER_COUNT];
|
||||
static uint8_t hci_sco_in_buffer[SCO_IN_BUFFER_COUNT][SCO_PACKET_SIZE];
|
||||
|
||||
// outgoing SCO
|
||||
static uint8_t sco_ring_buffer[SCO_RING_BUFFER_SIZE];
|
||||
static uint8_t sco_out_ring_buffer[SCO_OUT_BUFFER_SIZE];
|
||||
static int sco_ring_write; // packet idx
|
||||
static int sco_ring_transfers_active;
|
||||
static struct libusb_transfer *sco_ring_transfers[SCO_RING_BUFFER_COUNT];
|
||||
static int sco_ring_transfers_in_flight[SCO_RING_BUFFER_COUNT];
|
||||
static int sco_out_transfers_active;
|
||||
static struct libusb_transfer *sco_out_transfers[SCO_OUT_BUFFER_COUNT];
|
||||
static int sco_out_transfers_in_flight[SCO_OUT_BUFFER_COUNT];
|
||||
#endif
|
||||
|
||||
// outgoing buffer for HCI Command packets
|
||||
static uint8_t hci_cmd_buffer[3 + 256 + LIBUSB_CONTROL_SETUP_SIZE];
|
||||
|
||||
// incoming buffer for HCI Events and ACL Packets
|
||||
static uint8_t hci_event_in_buffer[ASYNC_BUFFERS][HCI_ACL_BUFFER_SIZE]; // bigger than largest packet
|
||||
static uint8_t hci_acl_in_buffer[ASYNC_BUFFERS][HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE];
|
||||
static uint8_t hci_event_in_buffer[EVENT_IN_BUFFER_COUNT][HCI_ACL_BUFFER_SIZE]; // bigger than largest packet
|
||||
static uint8_t hci_acl_in_buffer[ACL_IN_BUFFER_COUNT][HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE];
|
||||
|
||||
// For (ab)use as a linked list of received packets
|
||||
static struct libusb_transfer *handle_packet;
|
||||
@ -197,10 +198,10 @@ static uint8_t usb_path[USB_MAX_PATH_LEN];
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
static void sco_ring_init(void){
|
||||
sco_ring_write = 0;
|
||||
sco_ring_transfers_active = 0;
|
||||
sco_out_transfers_active = 0;
|
||||
}
|
||||
static int sco_ring_have_space(void){
|
||||
return sco_ring_transfers_active < SCO_RING_BUFFER_COUNT;
|
||||
return sco_out_transfers_active < SCO_OUT_BUFFER_COUNT;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -235,15 +236,19 @@ static void queue_transfer(struct libusb_transfer *transfer){
|
||||
}
|
||||
|
||||
LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
|
||||
// identify and free transfers as part of shutdown
|
||||
|
||||
int c;
|
||||
|
||||
// identify and free transfers as part of shutdown
|
||||
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) {
|
||||
for (c=0;c<ASYNC_BUFFERS;c++){
|
||||
for (c=0;c<EVENT_IN_BUFFER_COUNT;c++){
|
||||
if (transfer == event_in_transfer[c]){
|
||||
libusb_free_transfer(transfer);
|
||||
event_in_transfer[c] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (c=0;c<ACL_IN_BUFFER_COUNT;c++){
|
||||
if (transfer == acl_in_transfer[c]){
|
||||
libusb_free_transfer(transfer);
|
||||
acl_in_transfer[c] = 0;
|
||||
@ -251,7 +256,7 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
for (c=0;c<ISOC_BUFFERS;c++){
|
||||
for (c=0;c<SCO_IN_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_in_transfer[c]){
|
||||
libusb_free_transfer(transfer);
|
||||
sco_in_transfer[c] = 0;
|
||||
@ -259,11 +264,11 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
|
||||
}
|
||||
}
|
||||
|
||||
for (c=0;c<SCO_RING_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_ring_transfers[c]){
|
||||
sco_ring_transfers_in_flight[c] = 0;
|
||||
for (c=0;c<SCO_OUT_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_out_transfers[c]){
|
||||
sco_out_transfers_in_flight[c] = 0;
|
||||
libusb_free_transfer(transfer);
|
||||
sco_ring_transfers[c] = 0;
|
||||
sco_out_transfers[c] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -272,12 +277,14 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
|
||||
return;
|
||||
}
|
||||
|
||||
for (c=0;c<SCO_RING_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_ring_transfers[c]){
|
||||
sco_ring_transfers_in_flight[c] = 0;
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
// mark SCO OUT transfer as done
|
||||
for (c=0;c<SCO_OUT_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_out_transfers[c]){
|
||||
sco_out_transfers_in_flight[c] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int r;
|
||||
// log_info("begin async_callback endpoint %x, status %x, actual length %u", transfer->endpoint, transfer->status, transfer->actual_length );
|
||||
@ -316,11 +323,11 @@ static int usb_send_sco_packet(uint8_t *packet, int size){
|
||||
|
||||
// store packet in free slot
|
||||
int tranfer_index = sco_ring_write;
|
||||
uint8_t * data = &sco_ring_buffer[tranfer_index * SCO_PACKET_SIZE];
|
||||
uint8_t * data = &sco_out_ring_buffer[tranfer_index * SCO_PACKET_SIZE];
|
||||
memcpy(data, packet, size);
|
||||
|
||||
// setup transfer
|
||||
struct libusb_transfer * sco_transfer = sco_ring_transfers[tranfer_index];
|
||||
struct libusb_transfer * sco_transfer = sco_out_transfers[tranfer_index];
|
||||
libusb_fill_iso_transfer(sco_transfer, handle, sco_out_addr, data, size, NUM_ISO_PACKETS, async_callback, NULL, 0);
|
||||
libusb_set_iso_packet_lengths(sco_transfer, ISO_PACKET_SIZE);
|
||||
r = libusb_submit_transfer(sco_transfer);
|
||||
@ -331,13 +338,13 @@ static int usb_send_sco_packet(uint8_t *packet, int size){
|
||||
|
||||
// mark slot as full
|
||||
sco_ring_write++;
|
||||
if (sco_ring_write == SCO_RING_BUFFER_COUNT){
|
||||
if (sco_ring_write == SCO_OUT_BUFFER_COUNT){
|
||||
sco_ring_write = 0;
|
||||
}
|
||||
sco_ring_transfers_active++;
|
||||
sco_ring_transfers_in_flight[tranfer_index] = 1;
|
||||
sco_out_transfers_active++;
|
||||
sco_out_transfers_in_flight[tranfer_index] = 1;
|
||||
|
||||
// log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_ring_transfers_active);
|
||||
// log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_out_transfers_active);
|
||||
|
||||
// notify upper stack that provided buffer can be used again
|
||||
uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
|
||||
@ -444,8 +451,8 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){
|
||||
packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
|
||||
}
|
||||
// decrease tab
|
||||
sco_ring_transfers_active--;
|
||||
// log_info("H2: sco out complete, num active num active %u", sco_ring_transfers_active);
|
||||
sco_out_transfers_active--;
|
||||
// log_info("H2: sco out complete, num active num active %u", sco_out_transfers_active);
|
||||
#endif
|
||||
} else {
|
||||
log_info("usb_process_ds endpoint unknown %x", transfer->endpoint);
|
||||
@ -470,6 +477,10 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){
|
||||
}
|
||||
|
||||
static void usb_process_ds(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
|
||||
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return;
|
||||
|
||||
// log_info("begin usb_process_ds");
|
||||
@ -497,6 +508,9 @@ static void usb_process_ds(btstack_data_source_t *ds, btstack_data_source_callba
|
||||
}
|
||||
|
||||
static void usb_process_ts(btstack_timer_source_t *timer) {
|
||||
|
||||
UNUSED(timer);
|
||||
|
||||
// log_info("in usb_process_ts");
|
||||
|
||||
// timer is deactive, when timer callback gets called
|
||||
@ -864,10 +878,16 @@ static int usb_open(void){
|
||||
|
||||
// allocate transfer handlers
|
||||
int c;
|
||||
for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
|
||||
event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events
|
||||
if (!event_in_transfer[c]) {
|
||||
usb_close();
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
}
|
||||
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
|
||||
acl_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
|
||||
if ( !event_in_transfer[c] || !acl_in_transfer[c]) {
|
||||
if (!acl_in_transfer[c]) {
|
||||
usb_close();
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
@ -883,7 +903,7 @@ static int usb_open(void){
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
|
||||
// incoming
|
||||
for (c = 0 ; c < ISOC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
|
||||
sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in
|
||||
log_info("Alloc iso transfer");
|
||||
if (!sco_in_transfer[c]) {
|
||||
@ -904,13 +924,13 @@ static int usb_open(void){
|
||||
}
|
||||
|
||||
// outgoing
|
||||
for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){
|
||||
sco_ring_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts
|
||||
sco_ring_transfers_in_flight[c] = 0;
|
||||
for (c=0; c < SCO_OUT_BUFFER_COUNT ; c++){
|
||||
sco_out_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts
|
||||
sco_out_transfers_in_flight[c] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
|
||||
// configure event_in handlers
|
||||
libusb_fill_interrupt_transfer(event_in_transfer[c], handle, event_in_addr,
|
||||
hci_event_in_buffer[c], HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
|
||||
@ -920,7 +940,9 @@ static int usb_open(void){
|
||||
usb_close();
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
|
||||
// configure acl_in handlers
|
||||
libusb_fill_bulk_transfer(acl_in_transfer[c], handle, acl_in_addr,
|
||||
hci_acl_in_buffer[c] + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
|
||||
@ -1001,24 +1023,24 @@ static int usb_close(void){
|
||||
case LIB_USB_INTERFACE_CLAIMED:
|
||||
// Cancel all transfers, ignore warnings for this
|
||||
libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR);
|
||||
for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
|
||||
libusb_cancel_transfer(event_in_transfer[c]);
|
||||
}
|
||||
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
|
||||
libusb_cancel_transfer(acl_in_transfer[c]);
|
||||
}
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
for (c = 0 ; c < ISOC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
|
||||
libusb_cancel_transfer(sco_in_transfer[c]);
|
||||
log_info("libusb_cancel_transfer sco_in_transfer[%d]", c);
|
||||
}
|
||||
|
||||
for (c = 0; c < SCO_RING_BUFFER_COUNT ; c++){
|
||||
if (sco_ring_transfers_in_flight[c]) {
|
||||
log_info("libusb_cancel_transfer sco_ring_transfers[%d]", c);
|
||||
libusb_cancel_transfer(sco_ring_transfers[c]);
|
||||
for (c = 0; c < SCO_OUT_BUFFER_COUNT ; c++){
|
||||
if (sco_out_transfers_in_flight[c]) {
|
||||
log_info("libusb_cancel_transfer sco_out_transfers[%d]", c);
|
||||
libusb_cancel_transfer(sco_out_transfers[c]);
|
||||
} else {
|
||||
log_info("libusb_free_transfer sco_ring_transfers[%d]", c);
|
||||
libusb_free_transfer(sco_ring_transfers[c]);
|
||||
sco_ring_transfers[c] = 0;
|
||||
log_info("libusb_free_transfer sco_out_transfers[%d]", c);
|
||||
libusb_free_transfer(sco_out_transfers[c]);
|
||||
sco_out_transfers[c] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1032,17 +1054,27 @@ static int usb_close(void){
|
||||
libusb_handle_events_timeout(NULL, &tv);
|
||||
// check if all done
|
||||
completed = 1;
|
||||
for (c=0;c<ASYNC_BUFFERS;c++){
|
||||
if (event_in_transfer[c] || acl_in_transfer[c]) {
|
||||
for (c=0;c<EVENT_IN_BUFFER_COUNT;c++){
|
||||
if (event_in_transfer[c]) {
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!completed) continue;
|
||||
|
||||
for (c=0;c<ACL_IN_BUFFER_COUNT;c++){
|
||||
if (acl_in_transfer[c]) {
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
if (!completed) continue;
|
||||
|
||||
// Cancel all synchronous transfer
|
||||
for (c = 0 ; c < ISOC_BUFFERS ; c++) {
|
||||
for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
|
||||
if (sco_in_transfer[c]){
|
||||
completed = 0;
|
||||
break;
|
||||
@ -1051,8 +1083,8 @@ static int usb_close(void){
|
||||
|
||||
if (!completed) continue;
|
||||
|
||||
for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){
|
||||
if (sco_ring_transfers[c]){
|
||||
for (c=0; c < SCO_OUT_BUFFER_COUNT ; c++){
|
||||
if (sco_out_transfers[c]){
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
@ -1171,6 +1203,9 @@ static void usb_register_packet_handler(void (*handler)(uint8_t packet_type, uin
|
||||
}
|
||||
|
||||
static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(packet);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
// get usb singleton
|
||||
|
@ -10,10 +10,11 @@
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE 200
|
||||
|
@ -134,6 +134,8 @@ echo >> btstack_config.h
|
||||
|
||||
echo "// BTstack features that can be enabled" >> btstack_config.h
|
||||
echo "#define ENABLE_BLE" >> btstack_config.h
|
||||
# echo "#define ENABLE_LE_PERIPHERAL" >> btstack_config.h
|
||||
echo "#define ENABLE_LE_CENTRAL" >> btstack_config.h
|
||||
echo "#define ENABLE_CLASSIC" >> btstack_config.h
|
||||
echo "#define ENABLE_LOG_ERROR" >> btstack_config.h
|
||||
echo "#define ENABLE_LOG_INFO " >> btstack_config.h
|
||||
|
@ -93,7 +93,7 @@ LCD_OBJ = $(LCD:.c=.o)
|
||||
|
||||
# create firmware image from common objects and example source file
|
||||
|
||||
all: led_counter.hex gap_inquiry.hex
|
||||
all: led_counter.hex
|
||||
|
||||
# fetch and convert init scripts
|
||||
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
@ -101,6 +101,7 @@ include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
# compiling requires a 20-bit mspgcc version
|
||||
# spp_and_le_counter.hex spp_accel.hex spp_flowcontrol.hex spp_counter.hex
|
||||
# sdp_rfcomm_query.hex sdp_general_query.hex
|
||||
# gap_inquiry.hex
|
||||
|
||||
# compiling ant-test requires special ant init script
|
||||
# ant-test.hex
|
||||
|
@ -11,6 +11,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
// #define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
// #define ENABLE_LOG_ERROR
|
||||
// #define ENABLE_LOG_INFO
|
||||
|
@ -77,9 +77,32 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
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");
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
// assert manufacturer is TI
|
||||
if (manufacturer != COMPANY_ID_TEXAS_INSTRUMENTS_INC){
|
||||
printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
|
||||
break;
|
||||
}
|
||||
// assert correct init script is used based on expected lmp_subversion
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// main
|
||||
|
@ -1,10 +1,6 @@
|
||||
# lipoplastic setup for armv6 + arm64 compilation
|
||||
TARGET := iphone:clang
|
||||
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 = armv6
|
||||
ARCHS = armv7
|
||||
|
||||
TOOL_NAME = PatchBlueTool
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
# lipoplastic setup for armv6 + arm64 compilation
|
||||
TARGET := iphone:clang
|
||||
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 = armv6 arm64
|
||||
ARCHS = armv7 arm64
|
||||
BTSTACK_ROOT=../../..
|
||||
|
||||
BUNDLE_NAME = BTstack
|
||||
|
@ -26,9 +26,10 @@ While it's possible to use Xcode, I highly recommend to use theos to create apps
|
||||
## Compile Instructions for BTstack package
|
||||
|
||||
Install the following tools:
|
||||
* Xcode 6.4 as /Applications/Xcode.app
|
||||
* Xcode 4.4.1 as /Applications/Xcode-4.4.1.app/
|
||||
* [rpetrich's theos fork](https://github.com/rpetrich/theos) with "lippoplastic" support
|
||||
* Xcode
|
||||
* [csu-ios libraries](https://github.com/mringwal/csu-ios) for deployment targets < 6.0 (BTstack compiles againt iOS 3.0 by default)
|
||||
* [rpetrich's](https://github.com/rpetrich/theos) or [new official](https://github.com/theos/theos) theos fork with "lippoplastic" support
|
||||
|
||||
|
||||
Set the $THEOS environment variable to the location of the theos checkout, e.g. like:
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
# lipoplastic setup for armv6 + arm64 compilation
|
||||
TARGET := iphone:clang
|
||||
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 = armv6 arm64
|
||||
ARCHS = armv7 arm64
|
||||
|
||||
TWEAK_NAME = SpringBoardAccess
|
||||
SpringBoardAccess_FILES = Tweak.xm
|
||||
|
@ -1,11 +1,6 @@
|
||||
|
||||
# lipoplastic setup for armv6 + arm64 compilation
|
||||
TARGET := iphone:clang
|
||||
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 = armv6 arm64
|
||||
ARCHS = armv7
|
||||
|
||||
BTSTACK_ROOT=../../..
|
||||
# VPATH += $(BTSTACK_ROOT)/platform/daemon/example
|
||||
|
@ -1,10 +1,7 @@
|
||||
# lipoplastic setup for armv6 + arm64 compilation
|
||||
TARGET := iphone:clang
|
||||
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 = armv6 arm64
|
||||
ARCHS = armv7 arm64
|
||||
|
||||
BTSTACK_ROOT=../../..
|
||||
|
||||
|
@ -8,7 +8,7 @@ COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c le_device_db_fs.c
|
||||
include ${BTSTACK_ROOT}/example/Makefile.inc
|
||||
|
||||
# CC = gcc-fsf-4.9
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror -Wunused-parameter
|
||||
# CFLAGS += -Werror
|
||||
|
||||
CFLAGS += -I${BTSTACK_ROOT}/platform/posix \
|
||||
|
@ -14,6 +14,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
|
@ -65,6 +65,8 @@ int btstack_main(int argc, const char * argv[]);
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(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;
|
||||
@ -72,7 +74,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
|
||||
UNUSED(param);
|
||||
|
||||
#ifndef _WIN32
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
|
@ -93,7 +93,7 @@ LCD_OBJ = $(LCD:.c=.o)
|
||||
|
||||
# create firmware image from common objects and example source file
|
||||
|
||||
all: led_counter.hex gap_inquiry.hex
|
||||
all: led_counter.hex
|
||||
|
||||
# fetch and convert init scripts
|
||||
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
@ -107,6 +107,7 @@ include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
# spp_flowcontrol.hex
|
||||
# sdp_rfcomm_query.hex
|
||||
# sdp_general_query.hex
|
||||
# gap_inquiry.hex
|
||||
|
||||
# compiling ant-test requires special ant init script
|
||||
# ant-test.hex
|
||||
|
@ -11,6 +11,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
// #define ENABLE_LE_CENTRAL
|
||||
// #define ENABLE_LOG_INTO_HCI_DUMP
|
||||
// #define ENABLE_LOG_ERROR
|
||||
// #define ENABLE_LOG_INFO
|
||||
|
@ -96,9 +96,32 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
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");
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
// assert manufacturer is TI
|
||||
if (manufacturer != COMPANY_ID_TEXAS_INSTRUMENTS_INC){
|
||||
printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
|
||||
break;
|
||||
}
|
||||
// assert correct init script is used based on expected lmp_subversion
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_setup(void){
|
||||
|
@ -97,7 +97,8 @@ BLE_OBJ = $(BLE:.c=.o)
|
||||
# create firmware image from common objects and example source file
|
||||
|
||||
all: led_counter.hex spp_counter.hex gap_inquiry.hex spp_flowcontrol.hex \
|
||||
sdp_rfcomm_query.hex sdp_general_query.hex ble_server.hex
|
||||
sdp_rfcomm_query.hex sdp_general_query.hex
|
||||
# ble_server.hex
|
||||
|
||||
# fetch and convert init scripts
|
||||
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
|
@ -11,6 +11,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
// #define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
// #define ENABLE_LOG_ERROR
|
||||
// #define ENABLE_LOG_INFO
|
||||
|
@ -100,9 +100,32 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
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");
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
// assert manufacturer is TI
|
||||
if (manufacturer != COMPANY_ID_TEXAS_INSTRUMENTS_INC){
|
||||
printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
|
||||
break;
|
||||
}
|
||||
// assert correct init script is used based on expected lmp_subversion
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_setup(void){
|
||||
|
@ -13,6 +13,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_ERROR
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
|
@ -69,6 +69,7 @@
|
||||
int is_bcm;
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
static void local_version_information_handler(uint8_t * packet);
|
||||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
@ -97,6 +98,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -135,17 +139,17 @@ static void use_fast_uart(void){
|
||||
#endif
|
||||
}
|
||||
|
||||
static void local_version_information_callback(uint8_t * packet){
|
||||
static void local_version_information_handler(uint8_t * packet){
|
||||
printf("Local version information:\n");
|
||||
uint16_t hci_version = little_endian_read_16(packet, 4);
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 6);
|
||||
uint16_t lmp_version = little_endian_read_16(packet, 8);
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Revision 0x%04x\n", lmp_subversion);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Subversion 0x%04x\n", lmp_subversion);
|
||||
printf("- Manufacturer 0x%04x\n", manufacturer);
|
||||
switch (manufacturer){
|
||||
case COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
@ -155,6 +159,12 @@ static void local_version_information_callback(uint8_t * packet){
|
||||
break;
|
||||
case COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
#ifdef ENABLE_EHCILL
|
||||
@ -162,6 +172,7 @@ static void local_version_information_callback(uint8_t * packet){
|
||||
#else
|
||||
printf("eHCILL disable.\n");
|
||||
#endif
|
||||
|
||||
break;
|
||||
case COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom - using BCM driver.\n");
|
||||
@ -198,7 +209,8 @@ int main(int argc, const char * argv[]){
|
||||
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||
|
||||
// pick serial port
|
||||
config.device_name = "/dev/tty.usbserial-A9OVNX5P";
|
||||
config.device_name = "/dev/tty.usbserial-A900K2WS"; // DFROBOT
|
||||
// config.device_name = "/dev/tty.usbserial-A50285BI"; // BOOST-CC2564MODA New
|
||||
|
||||
// init HCI
|
||||
const btstack_uart_block_t * uart_driver = btstack_uart_block_posix_instance();
|
||||
@ -211,9 +223,6 @@ int main(int argc, const char * argv[]){
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
||||
// setup dynamic chipset driver setup
|
||||
hci_set_local_version_information_callback(&local_version_information_callback);
|
||||
|
||||
// handle CTRL-c
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_CLASSIC
|
||||
// #define ENABLE_LOG_INFO
|
||||
// #define ENABLE_LOG_ERROR
|
||||
|
@ -416,9 +416,32 @@ static const hci_transport_config_uart_t config = {
|
||||
|
||||
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");
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
// assert manufacturer is TI
|
||||
if (manufacturer != COMPANY_ID_TEXAS_INSTRUMENTS_INC){
|
||||
printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
|
||||
break;
|
||||
}
|
||||
// assert correct init script is used based on expected lmp_subversion
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -12,6 +12,8 @@
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
// #define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
// #define ENABLE_LOG_INFO
|
||||
|
@ -181,6 +181,10 @@ static void ancs_chunk_parser_handle_byte(uint8_t data){
|
||||
|
||||
static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
int connection_encrypted;
|
||||
|
||||
// handle connect / disconncet events first
|
||||
|
@ -323,6 +323,8 @@ static uint8_t att_validate_security(att_connection_t * att_connection, att_iter
|
||||
static uint16_t handle_exchange_mtu_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer){
|
||||
|
||||
UNUSED(request_len);
|
||||
|
||||
uint16_t client_rx_mtu = little_endian_read_16(request_buffer, 1);
|
||||
|
||||
// find min(local max mtu, remote mtu) and use as mtu for this connection
|
||||
@ -346,6 +348,8 @@ static uint16_t handle_exchange_mtu_request(att_connection_t * att_connection, u
|
||||
static uint16_t handle_find_information_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size,
|
||||
uint16_t start_handle, uint16_t end_handle){
|
||||
|
||||
UNUSED(att_connection);
|
||||
|
||||
log_info("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X", start_handle, end_handle);
|
||||
uint8_t request_type = ATT_FIND_INFORMATION_REQUEST;
|
||||
|
||||
@ -404,6 +408,7 @@ static uint16_t handle_find_information_request2(att_connection_t * att_connecti
|
||||
|
||||
static uint16_t handle_find_information_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
UNUSED(request_len);
|
||||
return handle_find_information_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3));
|
||||
}
|
||||
|
||||
@ -423,6 +428,8 @@ static uint16_t handle_find_by_type_value_request2(att_connection_t * att_connec
|
||||
uint16_t start_handle, uint16_t end_handle,
|
||||
uint16_t attribute_type, uint16_t attribute_len, uint8_t* attribute_value){
|
||||
|
||||
UNUSED(att_connection);
|
||||
|
||||
log_info("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type);
|
||||
log_info_hexdump(attribute_value, attribute_len);
|
||||
uint8_t request_type = ATT_FIND_BY_TYPE_VALUE_REQUEST;
|
||||
@ -635,6 +642,7 @@ static uint16_t handle_read_request2(att_connection_t * att_connection, uint8_t
|
||||
|
||||
static uint16_t handle_read_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
UNUSED(request_len);
|
||||
return handle_read_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1));
|
||||
}
|
||||
|
||||
@ -684,6 +692,7 @@ static uint16_t handle_read_blob_request2(att_connection_t * att_connection, uin
|
||||
|
||||
static uint16_t handle_read_blob_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
UNUSED(request_len);
|
||||
return handle_read_blob_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3));
|
||||
}
|
||||
|
||||
@ -773,6 +782,8 @@ static uint16_t handle_read_by_group_type_request2(att_connection_t * att_connec
|
||||
uint16_t start_handle, uint16_t end_handle,
|
||||
uint16_t attribute_type_len, uint8_t * attribute_type){
|
||||
|
||||
UNUSED(att_connection);
|
||||
|
||||
log_info("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size);
|
||||
log_info_hexdump(attribute_type, attribute_type_len);
|
||||
uint8_t request_type = ATT_READ_BY_GROUP_TYPE_REQUEST;
|
||||
@ -876,6 +887,8 @@ static uint16_t handle_read_by_group_type_request(att_connection_t * att_connect
|
||||
static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
|
||||
UNUSED(response_buffer_size);
|
||||
|
||||
uint8_t request_type = ATT_WRITE_REQUEST;
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
@ -912,6 +925,8 @@ static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t
|
||||
static uint16_t handle_prepare_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
|
||||
UNUSED(response_buffer_size);
|
||||
|
||||
uint8_t request_type = ATT_PREPARE_WRITE_REQUEST;
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
@ -981,6 +996,9 @@ void att_clear_transaction_queue(att_connection_t * att_connection){
|
||||
static uint16_t handle_execute_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
|
||||
uint8_t * response_buffer, uint16_t response_buffer_size){
|
||||
|
||||
UNUSED(request_len);
|
||||
UNUSED(response_buffer_size);
|
||||
|
||||
uint8_t request_type = ATT_EXECUTE_WRITE_REQUEST;
|
||||
if (request_buffer[1]) {
|
||||
// deliver queued errors
|
||||
@ -1005,6 +1023,9 @@ 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){
|
||||
|
||||
UNUSED(response_buffer);
|
||||
UNUSED(response_buffer_size);
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) return;
|
||||
@ -1099,9 +1120,11 @@ uint16_t att_handle_request(att_connection_t * att_connection,
|
||||
case ATT_WRITE_COMMAND:
|
||||
handle_write_command(att_connection, request_buffer, request_len, response_buffer, response_buffer_size);
|
||||
break;
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
case ATT_SIGNED_WRITE_COMMAND:
|
||||
log_info("handle_signed_write_command preprocessed by att_server.c");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
log_info("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]);
|
||||
log_info_hexdump(&request_buffer[9], request_len-9);
|
||||
|
@ -78,6 +78,7 @@ static att_server_t * att_server_for_handle(hci_con_handle_t con_handle){
|
||||
return &hci_connection->att_server;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static att_server_t * att_server_for_state(att_server_state_t state){
|
||||
btstack_linked_list_iterator_t it;
|
||||
hci_connections_get_iterator(&it);
|
||||
@ -88,6 +89,7 @@ static att_server_t * att_server_for_state(att_server_state_t state){
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
@ -132,6 +134,9 @@ static void att_handle_value_indication_timeout(btstack_timer_source_t *ts){
|
||||
}
|
||||
|
||||
static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
att_server_t * att_server;
|
||||
hci_con_handle_t con_handle;
|
||||
@ -232,6 +237,7 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
|
||||
|
||||
att_server_t * att_server = att_server_for_state(ATT_SERVER_W4_SIGNED_WRITE_VALIDATION);
|
||||
@ -252,7 +258,7 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
|
||||
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
|
||||
att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// pre: att_server->state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED
|
||||
// pre: can send now
|
||||
@ -300,6 +306,7 @@ static int att_server_process_validated_request(att_server_t * att_server){
|
||||
static void att_run_for_context(att_server_t * att_server){
|
||||
switch (att_server->state){
|
||||
case ATT_SERVER_REQUEST_RECEIVED:
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
if (att_server->request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){
|
||||
log_info("ATT Signed Write!");
|
||||
if (!sm_cmac_ready()) {
|
||||
@ -341,7 +348,7 @@ static void att_run_for_context(att_server_t * att_server){
|
||||
sm_cmac_signed_write_start(csrk, att_server->request_buffer[0], attribute_handle, att_server->request_size - 15, &att_server->request_buffer[3], counter_packet, att_signed_write_handle_cmac_result);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
// move on
|
||||
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
|
||||
att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);
|
||||
|
@ -60,6 +60,9 @@ 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){
|
||||
UNUSED(offset);
|
||||
UNUSED(buffer_size);
|
||||
|
||||
if (attribute_handle == battery_value_handle_value){
|
||||
if (buffer) {
|
||||
buffer[0] = battery_value;
|
||||
@ -77,6 +80,11 @@ static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint1
|
||||
}
|
||||
|
||||
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){
|
||||
UNUSED(con_handle);
|
||||
UNUSED(transaction_mode);
|
||||
UNUSED(offset);
|
||||
UNUSED(buffer_size);
|
||||
|
||||
if (attribute_handle == battery_value_handle_client_configuration){
|
||||
battery_value_client_configuration = little_endian_read_16(buffer, 0);
|
||||
}
|
||||
@ -93,8 +101,8 @@ void battery_service_server_init(uint8_t value){
|
||||
battery_value = value;
|
||||
|
||||
// get service handle range
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
uint16_t start_handle = 0;
|
||||
uint16_t end_handle = 0xfff;
|
||||
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;
|
||||
|
||||
|
@ -68,7 +68,10 @@ static uint8_t pts_suppress_mtu_exchange;
|
||||
static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size);
|
||||
static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code);
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static void att_signed_write_handle_cmac_result(uint8_t hash[8]);
|
||||
#endif
|
||||
|
||||
static uint16_t peripheral_mtu(gatt_client_t *peripheral){
|
||||
if (peripheral->mtu > l2cap_max_le_mtu()){
|
||||
@ -275,6 +278,7 @@ static void att_read_multiple_request(uint16_t peripheral_handle, uint16_t num_v
|
||||
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, offset);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
// precondition: can_send_packet_now == TRUE
|
||||
static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value, uint32_t sign_counter, uint8_t sgn[8]){
|
||||
l2cap_reserve_packet_buffer();
|
||||
@ -286,6 +290,7 @@ static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_
|
||||
reverse_64(sgn, &request[3 + value_length + 4]);
|
||||
l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
|
||||
}
|
||||
#endif
|
||||
|
||||
// precondition: can_send_packet_now == TRUE
|
||||
static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){
|
||||
@ -424,9 +429,11 @@ static void send_gatt_read_characteristic_descriptor_request(gatt_client_t * per
|
||||
att_read_request(ATT_READ_REQUEST, peripheral->con_handle, peripheral->attribute_handle);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t sign_counter){
|
||||
att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
|
||||
uint8_t attr_length = packet[1];
|
||||
@ -682,6 +689,7 @@ static void report_gatt_long_characteristic_value_blob(gatt_client_t * periphera
|
||||
}
|
||||
|
||||
static void report_gatt_characteristic_descriptor(gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t *value, uint16_t value_length, uint16_t value_offset){
|
||||
UNUSED(value_offset);
|
||||
uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->con_handle, descriptor_handle, value, value_length);
|
||||
emit_event_new(peripheral->callback, packet, value_length + 8);
|
||||
}
|
||||
@ -959,6 +967,7 @@ static void gatt_client_run(void){
|
||||
send_gatt_execute_write_request(peripheral);
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
case P_W4_CMAC_READY:
|
||||
if (sm_cmac_ready()){
|
||||
sm_key_t csrk;
|
||||
@ -981,6 +990,7 @@ static void gatt_client_run(void){
|
||||
gatt_client_handle_transaction_complete(peripheral);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -996,6 +1006,9 @@ static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8
|
||||
}
|
||||
|
||||
static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
@ -1342,6 +1355,7 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle,
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &gatt_client_connections);
|
||||
@ -1373,6 +1387,7 @@ uint8_t gatt_client_signed_write_without_response(btstack_packet_handler_t callb
|
||||
gatt_client_run();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t gatt_client_discover_primary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
|
||||
gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
|
||||
|
@ -249,7 +249,7 @@ uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_
|
||||
*/
|
||||
uint8_t gatt_client_discover_characteristics_for_handle_range_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16);
|
||||
uint8_t gatt_client_discover_characteristics_for_handle_range_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint8_t * uuid);
|
||||
uint8_t gatt_client_discover_characteristics_for_service_by_uuid16 (btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t *service, uint16_t uuid16);
|
||||
uint8_t gatt_client_discover_characteristics_for_service_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t *service, uint16_t uuid16);
|
||||
uint8_t gatt_client_discover_characteristics_for_service_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t *service, uint8_t * uuid128);
|
||||
|
||||
/**
|
||||
|
@ -83,6 +83,7 @@ void le_device_db_init(void){
|
||||
}
|
||||
|
||||
void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
|
||||
(void)bd_addr;
|
||||
}
|
||||
|
||||
// @returns number of device in db
|
||||
|
210
src/ble/sm.c
210
src/ble/sm.c
@ -51,6 +51,22 @@
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
|
||||
#if !defined(ENABLE_LE_PERIPHERAL) && !defined(ENABLE_LE_CENTRAL)
|
||||
#error "LE Security Manager used, but neither ENABLE_LE_PERIPHERAL nor ENABLE_LE_CENTRAL defined. Please add at least one to btstack_config.h."
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_LE_PERIPHERAL) && defined(ENABLE_LE_CENTRAL)
|
||||
#define IS_RESPONDER(role) (role)
|
||||
#else
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// only central - never responder (avoid 'unused variable' warnings)
|
||||
#define IS_RESPONDER(role) (0 && role)
|
||||
#else
|
||||
// only peripheral - always responder (avoid 'unused variable' warnings)
|
||||
#define IS_RESPONDER(role) (1 || role)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
|
||||
#error "Support for DHKEY Support in HCI Controller not implemented yet. Please use software implementation"
|
||||
@ -59,7 +75,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// Software ECDH implementation provided by mbedtls
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
#include "mbedtls/config.h"
|
||||
@ -68,6 +83,10 @@
|
||||
#include "sm_mbedtls_allocator.h"
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_LE_SIGNED_WRITE) || defined(ENABLE_LE_SECURE_CONNECTIONS)
|
||||
#define ENABLE_CMAC_ENGINE
|
||||
#endif
|
||||
|
||||
//
|
||||
// SM internal types and globals
|
||||
//
|
||||
@ -180,6 +199,7 @@ static random_address_update_t rau_state;
|
||||
static bd_addr_t sm_random_address;
|
||||
|
||||
// CMAC Calculation: General
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
static cmac_state_t sm_cmac_state;
|
||||
static uint16_t sm_cmac_message_len;
|
||||
static sm_key_t sm_cmac_k;
|
||||
@ -189,11 +209,14 @@ static uint8_t sm_cmac_block_current;
|
||||
static uint8_t sm_cmac_block_count;
|
||||
static uint8_t (*sm_cmac_get_byte)(uint16_t offset);
|
||||
static void (*sm_cmac_done_handler)(uint8_t * hash);
|
||||
#endif
|
||||
|
||||
// CMAC for ATT Signed Writes
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static uint8_t sm_cmac_header[3];
|
||||
static const uint8_t * sm_cmac_message;
|
||||
static uint8_t sm_cmac_sign_counter[4];
|
||||
#endif
|
||||
|
||||
// CMAC for Secure Connection functions
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
@ -363,7 +386,6 @@ static void sm_done_for_handle(hci_con_handle_t con_handle);
|
||||
static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle);
|
||||
static inline int sm_calc_actual_encryption_key_size(int other);
|
||||
static int sm_validate_stk_generation_method(void);
|
||||
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data);
|
||||
|
||||
static void log_info_hex16(const char * name, uint16_t value){
|
||||
log_info("%-6s 0x%04x", name, value);
|
||||
@ -454,6 +476,8 @@ static void gap_random_address_trigger(void){
|
||||
}
|
||||
|
||||
static void gap_random_address_update_handler(btstack_timer_source_t * timer){
|
||||
UNUSED(timer);
|
||||
|
||||
log_info("GAP Random Address Update due");
|
||||
btstack_run_loop_set_timer(&gap_random_address_update_timer, gap_random_adress_update_period);
|
||||
btstack_run_loop_add_timer(&gap_random_address_update_timer);
|
||||
@ -667,6 +691,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){
|
||||
UNUSED(channel);
|
||||
|
||||
// log event
|
||||
hci_dump_packet(packet_type, 1, packet, size);
|
||||
// dispatch to all event handlers
|
||||
@ -837,17 +863,6 @@ int sm_address_resolution_lookup(uint8_t address_type, bd_addr_t address){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CMAC Implementation using AES128 engine
|
||||
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
|
||||
int i;
|
||||
int carry = 0;
|
||||
for (i=len-1; i >= 0 ; i--){
|
||||
int new_carry = data[i] >> 7;
|
||||
data[i] = data[i] << 1 | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
// while x_state++ for an enum is possible in C, it isn't in C++. we use this helpers to avoid compile errors for now
|
||||
static inline void sm_next_responding_state(sm_connection_t * sm_conn){
|
||||
sm_conn->sm_engine_state = (security_manager_state_t) (((int)sm_conn->sm_engine_state) + 1);
|
||||
@ -860,6 +875,7 @@ static inline void rau_next_state(void){
|
||||
}
|
||||
|
||||
// CMAC calculation using AES Engine
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
|
||||
static inline void sm_cmac_next_state(void){
|
||||
sm_cmac_state = (cmac_state_t) (((int)sm_cmac_state) + 1);
|
||||
@ -899,8 +915,10 @@ void sm_cmac_general_start(const sm_key_t key, uint16_t message_len, uint8_t (*g
|
||||
// let's go
|
||||
sm_run();
|
||||
}
|
||||
#endif
|
||||
|
||||
// cmac for ATT Message signing
|
||||
#ifdef ENABLE_LE_SIGNED_WRITE
|
||||
static uint8_t sm_cmac_signed_write_message_get_byte(uint16_t offset){
|
||||
if (offset >= sm_cmac_message_len) {
|
||||
log_error("sm_cmac_signed_write_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_message_len);
|
||||
@ -929,8 +947,9 @@ void sm_cmac_signed_write_start(const sm_key_t k, uint8_t opcode, hci_con_handle
|
||||
sm_cmac_message = message;
|
||||
sm_cmac_general_start(k, total_message_len, &sm_cmac_signed_write_message_get_byte, done_handler);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
static void sm_cmac_handle_aes_engine_ready(void){
|
||||
switch (sm_cmac_state){
|
||||
case CMAC_CALC_SUBKEYS: {
|
||||
@ -969,6 +988,17 @@ static void sm_cmac_handle_aes_engine_ready(void){
|
||||
}
|
||||
}
|
||||
|
||||
// CMAC Implementation using AES128 engine
|
||||
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
|
||||
int i;
|
||||
int carry = 0;
|
||||
for (i=len-1; i >= 0 ; i--){
|
||||
int new_carry = data[i] >> 7;
|
||||
data[i] = data[i] << 1 | carry;
|
||||
carry = new_carry;
|
||||
}
|
||||
}
|
||||
|
||||
static void sm_cmac_handle_encryption_result(sm_key_t data){
|
||||
switch (sm_cmac_state){
|
||||
case CMAC_W4_SUBKEYS: {
|
||||
@ -1030,13 +1060,14 @@ static void sm_cmac_handle_encryption_result(sm_key_t data){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sm_trigger_user_response(sm_connection_t * sm_conn){
|
||||
// notify client for: JUST WORKS confirm, Numeric comparison confirm, PASSKEY display or input
|
||||
setup->sm_user_response = SM_USER_RESPONSE_IDLE;
|
||||
switch (setup->sm_stk_generation_method){
|
||||
case PK_RESP_INPUT:
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
|
||||
sm_notify_client_base(SM_EVENT_PASSKEY_INPUT_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
|
||||
} else {
|
||||
@ -1044,7 +1075,7 @@ static void sm_trigger_user_response(sm_connection_t * sm_conn){
|
||||
}
|
||||
break;
|
||||
case PK_INIT_INPUT:
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
sm_notify_client_passkey(SM_EVENT_PASSKEY_DISPLAY_NUMBER, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, big_endian_read_32(setup->sm_tk, 12));
|
||||
} else {
|
||||
setup->sm_user_response = SM_USER_RESPONSE_PENDING;
|
||||
@ -1071,7 +1102,7 @@ static void sm_trigger_user_response(sm_connection_t * sm_conn){
|
||||
|
||||
static int sm_key_distribution_all_received(sm_connection_t * sm_conn){
|
||||
int recv_flags;
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave / responder
|
||||
recv_flags = sm_key_distribution_flags_for_set(sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres));
|
||||
} else {
|
||||
@ -1119,7 +1150,7 @@ static void sm_init_setup(sm_connection_t * sm_conn){
|
||||
}
|
||||
|
||||
sm_pairing_packet_t * local_packet;
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave
|
||||
local_packet = &setup->sm_s_pres;
|
||||
gap_advertisements_get_address(&setup->sm_s_addr_type, setup->sm_s_address);
|
||||
@ -1148,7 +1179,7 @@ static int sm_stk_generation_init(sm_connection_t * sm_conn){
|
||||
|
||||
sm_pairing_packet_t * remote_packet;
|
||||
int remote_key_request;
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave / responder
|
||||
remote_packet = &setup->sm_m_preq;
|
||||
remote_key_request = sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq);
|
||||
@ -1192,7 +1223,9 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
||||
hci_con_handle_t con_handle = 0;
|
||||
|
||||
sm_connection_t * sm_connection;
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
sm_key_t ltk;
|
||||
#endif
|
||||
switch (mode){
|
||||
case ADDRESS_RESOLUTION_GENERAL:
|
||||
break;
|
||||
@ -1204,6 +1237,7 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
||||
sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
|
||||
sm_connection->sm_le_db_index = matched_device_id;
|
||||
log_info("ADDRESS_RESOLUTION_SUCEEDED, index %d", sm_connection->sm_le_db_index);
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
if (sm_connection->sm_role) break;
|
||||
if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break;
|
||||
sm_connection->sm_security_request_received = 0;
|
||||
@ -1214,14 +1248,17 @@ static void sm_address_resolution_handle_event(address_resolution_event_t event)
|
||||
} else {
|
||||
sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ADDRESS_RESOLUTION_FAILED:
|
||||
sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED;
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
if (sm_connection->sm_role) break;
|
||||
if (!sm_connection->sm_bonding_requested && !sm_connection->sm_security_request_received) break;
|
||||
sm_connection->sm_security_request_received = 0;
|
||||
sm_connection->sm_bonding_requested = 0;
|
||||
sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1353,7 +1390,7 @@ static void sm_sc_start_calculating_local_confirm(sm_connection_t * sm_conn){
|
||||
}
|
||||
|
||||
static void sm_sc_state_after_receiving_random(sm_connection_t * sm_conn){
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// Responder
|
||||
sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
|
||||
} else {
|
||||
@ -1434,7 +1471,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
|
||||
break;
|
||||
case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
|
||||
memcpy(setup->sm_local_dhkey_check, hash, 16);
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
if (setup->sm_state_vars & SM_STATE_VAR_DHKEY_COMMAND_RECEIVED){
|
||||
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
|
||||
@ -1450,7 +1487,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
|
||||
sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
|
||||
break;
|
||||
}
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
|
||||
} else {
|
||||
@ -1466,7 +1503,7 @@ static void sm_sc_cmac_done(uint8_t * hash){
|
||||
reverse_128(hash, setup->sm_t);
|
||||
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){
|
||||
if (IS_RESPONDER(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
|
||||
@ -1563,7 +1600,7 @@ static void f5_calculate_mackey(sm_connection_t * sm_conn){
|
||||
bd_addr_slave[0] = setup->sm_s_addr_type;
|
||||
memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
|
||||
memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
f5_mackkey(sm_conn, setup->sm_t, setup->sm_peer_nonce, setup->sm_local_nonce, bd_addr_master, bd_addr_slave);
|
||||
} else {
|
||||
@ -1625,7 +1662,7 @@ static void g2_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_k
|
||||
|
||||
static void g2_calculate(sm_connection_t * sm_conn) {
|
||||
// calc Va if numeric comparison
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
g2_engine(sm_conn, setup->sm_peer_qx, ec_qx, setup->sm_peer_nonce, setup->sm_local_nonce);;
|
||||
} else {
|
||||
@ -1675,7 +1712,7 @@ static void sm_sc_calculate_f6_for_dhkey_check(sm_connection_t * sm_conn){
|
||||
iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
|
||||
iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
|
||||
iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
f6_engine(sm_conn, setup->sm_mackey, setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
|
||||
} else {
|
||||
@ -1700,7 +1737,7 @@ static void sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn){
|
||||
iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
|
||||
iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
|
||||
iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
f6_engine(sm_conn, setup->sm_mackey, setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
|
||||
} else {
|
||||
@ -1750,6 +1787,7 @@ static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
|
||||
// key management secure connections:
|
||||
// - both devices store same LTK from ECDH key exchange.
|
||||
|
||||
#if defined(ENABLE_LE_SECURE_CONNECTIONS) || defined(ENABLE_LE_CENTRAL)
|
||||
static void sm_load_security_info(sm_connection_t * sm_connection){
|
||||
int encryption_key_size;
|
||||
int authenticated;
|
||||
@ -1763,7 +1801,9 @@ static void sm_load_security_info(sm_connection_t * sm_connection){
|
||||
sm_connection->sm_connection_authenticated = authenticated;
|
||||
sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_connection){
|
||||
memcpy(setup->sm_local_rand, sm_connection->sm_local_rand, 8);
|
||||
setup->sm_local_ediv = sm_connection->sm_local_ediv;
|
||||
@ -1776,6 +1816,7 @@ static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_con
|
||||
sm_connection->sm_actual_encryption_key_size, sm_connection->sm_connection_authenticated);
|
||||
sm_connection->sm_engine_state = SM_RESPONDER_PH4_Y_GET_ENC;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sm_run(void){
|
||||
|
||||
@ -1853,6 +1894,7 @@ static void sm_run(void){
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
// CMAC
|
||||
switch (sm_cmac_state){
|
||||
case CMAC_CALC_SUBKEYS:
|
||||
@ -1865,6 +1907,7 @@ static void sm_run(void){
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CSRK Lookup
|
||||
// -- if csrk lookup ready, find connection that require csrk lookup
|
||||
@ -1975,7 +2018,9 @@ static void sm_run(void){
|
||||
// - if no connection locked and we're ready/waiting for setup context, fetch it and start
|
||||
int done = 1;
|
||||
int err;
|
||||
UNUSED(err);
|
||||
switch (sm_connection->sm_engine_state) {
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
case SM_RESPONDER_SEND_SECURITY_REQUEST:
|
||||
// send packet if possible,
|
||||
if (l2cap_can_send_fixed_channel_packet_now(sm_connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL)){
|
||||
@ -2007,21 +2052,24 @@ static void sm_run(void){
|
||||
}
|
||||
sm_connection->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
|
||||
break;
|
||||
case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
|
||||
sm_reset_setup();
|
||||
sm_start_calculating_ltk_from_ediv_and_rand(sm_connection);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
case SM_INITIATOR_PH0_HAS_LTK:
|
||||
sm_reset_setup();
|
||||
sm_load_security_info(sm_connection);
|
||||
sm_connection->sm_engine_state = SM_INITIATOR_PH0_SEND_START_ENCRYPTION;
|
||||
break;
|
||||
case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
|
||||
sm_reset_setup();
|
||||
sm_start_calculating_ltk_from_ediv_and_rand(sm_connection);
|
||||
break;
|
||||
case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
|
||||
sm_reset_setup();
|
||||
sm_init_setup(sm_connection);
|
||||
sm_timeout_start(sm_connection);
|
||||
sm_connection->sm_engine_state = SM_INITIATOR_PH1_SEND_PAIRING_REQUEST;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
case SM_SC_RECEIVED_LTK_REQUEST:
|
||||
@ -2086,6 +2134,7 @@ static void sm_run(void){
|
||||
|
||||
sm_key_t plaintext;
|
||||
int key_distribution_flags;
|
||||
UNUSED(key_distribution_flags);
|
||||
|
||||
log_info("sm_run: state %u", connection->sm_engine_state);
|
||||
|
||||
@ -2164,6 +2213,7 @@ static void sm_run(void){
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// initiator side
|
||||
case SM_INITIATOR_PH0_SEND_START_ENCRYPTION: {
|
||||
sm_key_t peer_ltk_flipped;
|
||||
@ -2182,6 +2232,7 @@ static void sm_run(void){
|
||||
l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
|
||||
sm_timeout_reset(connection);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
|
||||
@ -2197,7 +2248,7 @@ static void sm_run(void){
|
||||
switch (setup->sm_stk_generation_method){
|
||||
case JUST_WORKS:
|
||||
case NK_BOTH_INPUT:
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// responder
|
||||
sm_sc_start_calculating_local_confirm(connection);
|
||||
} else {
|
||||
@ -2213,7 +2264,7 @@ static void sm_run(void){
|
||||
memcpy(setup->sm_rb, setup->sm_tk, 16);
|
||||
setup->sm_passkey_bit = 0;
|
||||
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// responder
|
||||
connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
|
||||
} else {
|
||||
@ -2235,7 +2286,7 @@ static void sm_run(void){
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_PAIRING_CONFIRM;
|
||||
reverse_128(setup->sm_local_confirm, &buffer[1]);
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
|
||||
@ -2249,7 +2300,7 @@ static void sm_run(void){
|
||||
buffer[0] = SM_CODE_PAIRING_RANDOM;
|
||||
reverse_128(setup->sm_local_nonce, &buffer[1]);
|
||||
if (setup->sm_stk_generation_method != JUST_WORKS && setup->sm_stk_generation_method != NK_BOTH_INPUT && setup->sm_passkey_bit < 20){
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// responder
|
||||
connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
|
||||
} else {
|
||||
@ -2257,7 +2308,7 @@ static void sm_run(void){
|
||||
connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
|
||||
}
|
||||
} else {
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// responder
|
||||
if (setup->sm_stk_generation_method == NK_BOTH_INPUT){
|
||||
connection->sm_engine_state = SM_SC_W2_CALCULATE_G2;
|
||||
@ -2278,7 +2329,7 @@ static void sm_run(void){
|
||||
buffer[0] = SM_CODE_PAIRING_DHKEY_CHECK;
|
||||
reverse_128(setup->sm_local_dhkey_check, &buffer[1]);
|
||||
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_SC_W4_LTK_REQUEST_SC;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
|
||||
@ -2290,6 +2341,8 @@ static void sm_run(void){
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
case SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE:
|
||||
// echo initiator for now
|
||||
sm_pairing_packet_set_code(setup->sm_s_pres,SM_CODE_PAIRING_RESPONSE);
|
||||
@ -2316,12 +2369,13 @@ static void sm_run(void){
|
||||
sm_trigger_user_response(connection);
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
|
||||
case SM_PH2_SEND_PAIRING_RANDOM: {
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_PAIRING_RANDOM;
|
||||
reverse_128(setup->sm_local_random, &buffer[1]);
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_RESPONDER_PH2_W4_LTK_REQUEST;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_RANDOM;
|
||||
@ -2391,7 +2445,7 @@ static void sm_run(void){
|
||||
// already busy?
|
||||
if (sm_aes128_state == SM_AES128_ACTIVE) break;
|
||||
// calculate STK
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
sm_s1_r_prime(setup->sm_local_random, setup->sm_peer_random, plaintext);
|
||||
} else {
|
||||
sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, plaintext);
|
||||
@ -2412,7 +2466,7 @@ static void sm_run(void){
|
||||
uint8_t buffer[17];
|
||||
buffer[0] = SM_CODE_PAIRING_CONFIRM;
|
||||
reverse_128(setup->sm_local_confirm, &buffer[1]);
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_RESPONDER_PH2_W4_PAIRING_RANDOM;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_CONFIRM;
|
||||
@ -2421,6 +2475,7 @@ static void sm_run(void){
|
||||
sm_timeout_reset(connection);
|
||||
return;
|
||||
}
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
case SM_RESPONDER_PH2_SEND_LTK_REPLY: {
|
||||
sm_key_t stk_flipped;
|
||||
reverse_128(setup->sm_ltk, stk_flipped);
|
||||
@ -2428,13 +2483,6 @@ static void sm_run(void){
|
||||
hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, stk_flipped);
|
||||
return;
|
||||
}
|
||||
case SM_INITIATOR_PH3_SEND_START_ENCRYPTION: {
|
||||
sm_key_t stk_flipped;
|
||||
reverse_128(setup->sm_ltk, stk_flipped);
|
||||
connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
|
||||
hci_send_cmd(&hci_le_start_encryption, connection->sm_handle, 0, 0, 0, stk_flipped);
|
||||
return;
|
||||
}
|
||||
case SM_RESPONDER_PH4_SEND_LTK_REPLY: {
|
||||
sm_key_t ltk_flipped;
|
||||
reverse_128(setup->sm_ltk, ltk_flipped);
|
||||
@ -2451,6 +2499,16 @@ static void sm_run(void){
|
||||
sm_next_responding_state(connection);
|
||||
sm_aes128_start(sm_persistent_dhk, plaintext, connection);
|
||||
return;
|
||||
#endif
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
case SM_INITIATOR_PH3_SEND_START_ENCRYPTION: {
|
||||
sm_key_t stk_flipped;
|
||||
reverse_128(setup->sm_ltk, stk_flipped);
|
||||
connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
|
||||
hci_send_cmd(&hci_le_start_encryption, connection->sm_handle, 0, 0, 0, stk_flipped);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SM_PH3_DISTRIBUTE_KEYS:
|
||||
if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION){
|
||||
@ -2509,7 +2567,7 @@ static void sm_run(void){
|
||||
}
|
||||
|
||||
// keys are sent
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// slave -> receive master keys if any
|
||||
if (sm_key_distribution_all_received(connection)){
|
||||
sm_key_distribution_handle_all_received(connection);
|
||||
@ -2579,6 +2637,7 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
switch (sm_cmac_state){
|
||||
case CMAC_W4_SUBKEYS:
|
||||
case CMAC_W4_MI:
|
||||
@ -2592,6 +2651,7 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// retrieve sm_connection provided to sm_aes128_start_encryption
|
||||
sm_connection_t * connection = (sm_connection_t*) sm_aes128_context;
|
||||
@ -2621,7 +2681,7 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
connection->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
|
||||
return;
|
||||
}
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_PH2_CALC_STK;
|
||||
@ -2632,7 +2692,7 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
reverse_128(data, setup->sm_ltk);
|
||||
sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
|
||||
log_info_key("stk", setup->sm_ltk);
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
|
||||
} else {
|
||||
connection->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
|
||||
@ -2678,7 +2738,7 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
|
||||
} else {
|
||||
// no keys to send, just continue
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
// slave -> receive master keys
|
||||
connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
|
||||
} else {
|
||||
@ -2692,12 +2752,14 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
}
|
||||
}
|
||||
return;
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
case SM_RESPONDER_PH4_LTK_W4_ENC:
|
||||
reverse_128(data, setup->sm_ltk);
|
||||
sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
|
||||
log_info_key("ltk", setup->sm_ltk);
|
||||
connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2706,6 +2768,8 @@ static void sm_handle_encryption_result(uint8_t * data){
|
||||
#ifdef USE_MBEDTLS_FOR_ECDH
|
||||
|
||||
static int sm_generate_f_rng(void * context, unsigned char * buffer, size_t size){
|
||||
UNUSED(context);
|
||||
|
||||
int offset = setup->sm_passkey_bit;
|
||||
log_info("sm_generate_f_rng: size %u - offset %u", (int) size, offset);
|
||||
while (size) {
|
||||
@ -2827,7 +2891,7 @@ static void sm_handle_random_result(uint8_t * data){
|
||||
}
|
||||
sm_reset_tk();
|
||||
big_endian_store_32(setup->sm_tk, 12, tk);
|
||||
if (connection->sm_role){
|
||||
if (IS_RESPONDER(connection->sm_role)){
|
||||
connection->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
|
||||
} else {
|
||||
if (setup->sm_use_secure_connections){
|
||||
@ -2872,6 +2936,9 @@ static void sm_handle_random_result(uint8_t * data){
|
||||
|
||||
static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
sm_connection_t * sm_conn;
|
||||
hci_con_handle_t con_handle;
|
||||
|
||||
@ -2942,7 +3009,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_conn->sm_irk_lookup_state = IRK_LOOKUP_W4_READY;
|
||||
|
||||
// just connected -> everything else happens in sm_run()
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave - state already could be SM_RESPONDER_SEND_SECURITY_REQUEST instead
|
||||
if (sm_conn->sm_engine_state == SM_GENERAL_IDLE){
|
||||
if (sm_slave_request_security) {
|
||||
@ -3029,7 +3096,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_done_for_handle(sm_conn->sm_handle);
|
||||
break;
|
||||
case SM_PH2_W4_CONNECTION_ENCRYPTED:
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave
|
||||
if (setup->sm_use_secure_connections){
|
||||
sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
|
||||
@ -3066,7 +3133,7 @@ static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint
|
||||
sm_done_for_handle(sm_conn->sm_handle);
|
||||
break;
|
||||
case SM_PH2_W4_CONNECTION_ENCRYPTED:
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// slave
|
||||
sm_conn->sm_engine_state = SM_PH3_GET_RANDOM;
|
||||
} else {
|
||||
@ -3182,6 +3249,8 @@ static int sm_validate_stk_generation_method(void){
|
||||
|
||||
static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(size);
|
||||
|
||||
if (packet_type == HCI_EVENT_PACKET && packet[0] == L2CAP_EVENT_CAN_SEND_NOW){
|
||||
sm_run();
|
||||
}
|
||||
@ -3199,6 +3268,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
log_debug("sm_pdu_handler: state %u, pdu 0x%02x", sm_conn->sm_engine_state, packet[0]);
|
||||
|
||||
int err;
|
||||
UNUSED(err);
|
||||
|
||||
if (packet[0] == SM_CODE_KEYPRESS_NOTIFICATION){
|
||||
uint8_t buffer[5];
|
||||
@ -3216,6 +3286,8 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
case SM_GENERAL_TIMEOUT:
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
|
||||
// Initiator
|
||||
case SM_INITIATOR_CONNECTED:
|
||||
if ((packet[0] != SM_CODE_SECURITY_REQUEST) || (sm_conn->sm_role)){
|
||||
@ -3305,7 +3377,9 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
reverse_128(&packet[1], setup->sm_peer_random);
|
||||
sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
// Responder
|
||||
case SM_RESPONDER_IDLE:
|
||||
case SM_RESPONDER_SEND_SECURITY_REQUEST:
|
||||
@ -3319,6 +3393,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
|
||||
sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_SECURE_CONNECTIONS
|
||||
case SM_SC_W4_PUBLIC_KEY_COMMAND:
|
||||
@ -3348,7 +3423,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
}
|
||||
|
||||
#endif
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
|
||||
} else {
|
||||
@ -3386,7 +3461,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
// received confirm value
|
||||
reverse_128(&packet[1], setup->sm_peer_confirm);
|
||||
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
// responder
|
||||
if (sm_passkey_used(setup->sm_stk_generation_method)){
|
||||
if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
|
||||
@ -3450,6 +3525,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
|
||||
if (packet[0] != SM_CODE_PAIRING_CONFIRM){
|
||||
sm_pdu_received_in_wrong_state(sm_conn);
|
||||
@ -3491,6 +3567,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
reverse_128(&packet[1], setup->sm_peer_random);
|
||||
sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SM_PH3_RECEIVE_KEYS:
|
||||
switch(packet[0]){
|
||||
@ -3530,7 +3607,7 @@ static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uin
|
||||
|
||||
sm_key_distribution_handle_all_received(sm_conn);
|
||||
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
if (setup->sm_use_secure_connections && (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION)){
|
||||
sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_H6_ILK;
|
||||
} else {
|
||||
@ -3582,9 +3659,11 @@ void sm_set_io_capabilities(io_capability_t io_capability){
|
||||
sm_io_capabilities = io_capability;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
void sm_set_request_security(int enable){
|
||||
sm_slave_request_security = enable;
|
||||
}
|
||||
#endif
|
||||
|
||||
void sm_set_er(sm_key_t er){
|
||||
memcpy(sm_persistent_er, er, 16);
|
||||
@ -3624,7 +3703,9 @@ void sm_init(void){
|
||||
sm_max_encryption_key_size = 16;
|
||||
sm_min_encryption_key_size = 7;
|
||||
|
||||
#ifdef ENABLE_CMAC_ENGINE
|
||||
sm_cmac_state = CMAC_IDLE;
|
||||
#endif
|
||||
dkg_state = DKG_W4_WORKING;
|
||||
rau_state = RAU_W4_WORKING;
|
||||
sm_aes128_state = SM_AES128_IDLE;
|
||||
@ -3677,6 +3758,10 @@ void sm_use_fixed_ec_keypair(uint8_t * qx, uint8_t * qy, uint8_t * d){
|
||||
memcpy(ec_d, d, 32);
|
||||
sm_have_ec_keypair = 1;
|
||||
ec_key_generation_state = EC_KEY_GENERATION_DONE;
|
||||
#else
|
||||
UNUSED(qx);
|
||||
UNUSED(qy);
|
||||
UNUSED(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -3755,7 +3840,7 @@ void sm_request_pairing(hci_con_handle_t con_handle){
|
||||
if (!sm_conn) return; // wrong connection
|
||||
|
||||
log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
|
||||
if (sm_conn->sm_role){
|
||||
if (IS_RESPONDER(sm_conn->sm_role)){
|
||||
sm_send_security_request_for_connection(sm_conn);
|
||||
} else {
|
||||
// used as a trigger to start central/master/initiator security procedures
|
||||
@ -3896,16 +3981,21 @@ static int gap_random_address_type_requires_updates(void){
|
||||
if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_OFF) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
static uint8_t own_address_type(void){
|
||||
if (gap_random_adress_type == 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
hci_le_advertisements_set_own_address_type(own_address_type());
|
||||
#endif
|
||||
if (!gap_random_address_type_requires_updates()) return;
|
||||
gap_random_address_update_start();
|
||||
gap_random_address_trigger();
|
||||
@ -3930,6 +4020,7 @@ void gap_random_address_set(bd_addr_t addr){
|
||||
sm_run();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
/*
|
||||
* @brief Set Advertisement Paramters
|
||||
* @param adv_int_min
|
||||
@ -3947,4 +4038,5 @@ void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, u
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -55,7 +55,9 @@
|
||||
#endif
|
||||
|
||||
// Avoid complaints of unused arguments when log levels are disabled.
|
||||
static inline void __log_unused(const char *format, ...) {}
|
||||
static inline void __log_unused(const char *format, ...) {
|
||||
UNUSED(format);
|
||||
}
|
||||
|
||||
// allow to provide port specific printf
|
||||
#ifndef BTSTACK_PRINTF
|
||||
|
@ -214,6 +214,9 @@ void log_info_hexdump(const void *data, int size){
|
||||
buffer[j] = 0;
|
||||
log_info("%s", buffer);
|
||||
}
|
||||
#else
|
||||
UNUSED(data);
|
||||
UNUSED(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -229,6 +232,9 @@ void log_info_key(const char * name, sm_key_t key){
|
||||
}
|
||||
buffer[j] = 0;
|
||||
log_info("%-6s %s", name, buffer);
|
||||
#else
|
||||
UNUSED(name);
|
||||
UNUSED(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,6 @@ static btstack_linked_list_t bnep_channels = NULL;
|
||||
|
||||
static gap_security_level_t bnep_security_level;
|
||||
|
||||
static void (*app_packet_handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
|
||||
static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
|
||||
static void bnep_channel_finalize(bnep_channel_t *channel);
|
||||
static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
|
||||
@ -1090,8 +1087,10 @@ static int bnep_handle_ethernet_packet(bnep_channel_t *channel, bd_addr_t addr_d
|
||||
#endif
|
||||
|
||||
/* Notify application layer and deliver the ethernet packet */
|
||||
(*app_packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid,
|
||||
ethernet_packet, size + sizeof(uint16_t) + 2 * sizeof(bd_addr_t));
|
||||
if (channel->packet_handler){
|
||||
(*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet,
|
||||
size + sizeof(uint16_t) + 2 * sizeof(bd_addr_t));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -1170,6 +1169,8 @@ static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet,
|
||||
*/
|
||||
static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
|
||||
{
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
uint16_t psm;
|
||||
uint16_t l2cap_cid;
|
||||
|
@ -54,6 +54,7 @@ static void db_open(void){
|
||||
}
|
||||
|
||||
static void db_set_local_bd_addr(bd_addr_t bd_addr){
|
||||
(void)bd_addr;
|
||||
}
|
||||
|
||||
static void db_close(void){
|
||||
|
@ -503,6 +503,8 @@ void btstack_sbc_decoder_process_data(btstack_sbc_decoder_state_t * state, int p
|
||||
void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, btstack_sbc_mode_t mode,
|
||||
int blocks, int subbands, int allmethod, int sample_rate, int bitpool){
|
||||
|
||||
UNUSED(bitpool);
|
||||
|
||||
if (sbc_encoder_state_singleton && sbc_encoder_state_singleton != state ){
|
||||
log_error("SBC encoder: different sbc decoder state is allready registered");
|
||||
}
|
||||
|
@ -455,6 +455,10 @@ void hfp_create_sdp_record(uint8_t * service, uint32_t service_record_handle, ui
|
||||
static hfp_connection_t * connection_doing_sdp_query = NULL;
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
hfp_connection_t * hfp_connection = connection_doing_sdp_query;
|
||||
|
||||
if ( hfp_connection->state != HFP_W4_SDP_QUERY_COMPLETE) return;
|
||||
@ -528,6 +532,8 @@ static void hfp_handle_failed_sco_connection(uint8_t status){
|
||||
|
||||
|
||||
void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
uint16_t rfcomm_cid, handle;
|
||||
hfp_connection_t * hfp_connection = NULL;
|
||||
|
@ -436,6 +436,8 @@ static int hfp_ag_retrieve_indicators_status_cmd(uint16_t cid){
|
||||
}
|
||||
|
||||
static int hfp_ag_set_indicator_status_update_cmd(uint16_t cid, uint8_t activate){
|
||||
UNUSED(activate);
|
||||
|
||||
// AT\r\n%s:3,0,0,%d\r\n
|
||||
return hfp_ag_ok(cid);
|
||||
}
|
||||
@ -1815,6 +1817,8 @@ static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){
|
||||
}
|
||||
|
||||
static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
|
||||
hfp_connection_t * hfp_connection = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||
if (!hfp_connection) return;
|
||||
|
||||
|
@ -982,6 +982,8 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){
|
||||
|
||||
|
||||
static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
|
||||
hfp_connection_t * hfp_connection = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||
if (!hfp_connection) return;
|
||||
|
||||
|
@ -131,7 +131,12 @@ static void hsp_run(void);
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){}
|
||||
static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(event);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void hsp_ag_register_packet_handler(btstack_packet_handler_t callback){
|
||||
if (callback == NULL){
|
||||
@ -344,6 +349,8 @@ void hsp_ag_set_speaker_gain(uint8_t gain){
|
||||
}
|
||||
|
||||
static void hsp_ringing_timeout_handler(btstack_timer_source_t * timer){
|
||||
UNUSED(timer);
|
||||
|
||||
ag_ring = 1;
|
||||
btstack_run_loop_set_timer(&hs_timeout, 2000); // 2 seconds timeout
|
||||
btstack_run_loop_add_timer(&hs_timeout);
|
||||
@ -531,6 +538,8 @@ static void hsp_run(void){
|
||||
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
|
||||
if (packet_type == RFCOMM_DATA_PACKET){
|
||||
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
||||
size--;
|
||||
@ -696,6 +705,10 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet[0]){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet);
|
||||
|
@ -124,7 +124,12 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
static btstack_packet_handler_t hsp_hs_callback;
|
||||
static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){}
|
||||
static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(event);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void hsp_hs_register_packet_handler(btstack_packet_handler_t callback){
|
||||
if (callback == NULL){
|
||||
@ -442,6 +447,8 @@ static void hsp_run(void){
|
||||
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
|
||||
// printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
|
||||
if (packet_type == RFCOMM_DATA_PACKET){
|
||||
// skip over leading newline
|
||||
@ -598,6 +605,10 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
}
|
||||
|
||||
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case SDP_EVENT_QUERY_RFCOMM_SERVICE:
|
||||
channel_nr = sdp_event_query_rfcomm_service_get_rfcomm_channel(packet);
|
||||
|
@ -909,6 +909,8 @@ static void rfcomm_multiplexer_set_state_and_request_can_send_now_event(rfcomm_m
|
||||
* @return handled packet
|
||||
*/
|
||||
static int rfcomm_hci_event_handler(uint8_t *packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
uint16_t psm;
|
||||
uint16_t l2cap_cid;
|
||||
@ -1038,6 +1040,7 @@ static int rfcomm_hci_event_handler(uint8_t *packet, uint16_t size){
|
||||
}
|
||||
|
||||
static int rfcomm_multiplexer_l2cap_packet_handler(uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
// get or create a multiplexer for a certain device
|
||||
rfcomm_multiplexer_t *multiplexer = rfcomm_multiplexer_for_l2cap_cid(channel);
|
||||
@ -1403,7 +1406,8 @@ static void rfcomm_channel_state_machine_with_dlci(rfcomm_multiplexer_t * multip
|
||||
}
|
||||
|
||||
static void rfcomm_channel_packet_handler(rfcomm_multiplexer_t * multiplexer, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(size);
|
||||
|
||||
// rfcomm: (0) addr [76543 server channel] [2 direction: initiator uses 1] [1 C/R: CMD by initiator = 1] [0 EA=1]
|
||||
const uint8_t frame_dlci = packet[0] >> 2;
|
||||
uint8_t message_dlci; // used by commands in UIH(_PF) packets
|
||||
|
@ -385,6 +385,8 @@ static void sdp_client_parse_service_search_attribute_response(uint8_t* packet){
|
||||
}
|
||||
|
||||
void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
// uint16_t handle;
|
||||
if (packet_type == L2CAP_DATA_PACKET){
|
||||
uint16_t responseTransactionID = big_endian_read_16(packet,1);
|
||||
|
@ -100,6 +100,8 @@ static void sdp_rfcomm_query_emit_service(void){
|
||||
}
|
||||
|
||||
static void sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
|
||||
UNUSED(attribute_value_length);
|
||||
|
||||
// init state on first byte
|
||||
if (data_offset == 0){
|
||||
pdl_state = GET_PROTOCOL_LIST_LENGTH;
|
||||
@ -241,6 +243,9 @@ static void sdp_client_query_rfcomm_handle_service_name_data(uint32_t attribute_
|
||||
}
|
||||
|
||||
static void sdp_client_query_rfcomm_handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE:
|
||||
// handle service without a name
|
||||
|
@ -448,6 +448,8 @@ static void sdp_respond(void){
|
||||
|
||||
// we assume that we don't get two requests in a row
|
||||
static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
uint16_t transaction_id;
|
||||
SDP_PDU_ID_t pdu_id;
|
||||
uint16_t remote_mtu;
|
||||
|
@ -371,6 +371,8 @@ struct sdp_context_append_attributes {
|
||||
};
|
||||
|
||||
static int sdp_traversal_append_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
|
||||
UNUSED(type);
|
||||
UNUSED(size);
|
||||
struct sdp_context_append_attributes * context = (struct sdp_context_append_attributes *) my_context;
|
||||
if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
|
||||
// DES_HEADER(3) + DES_DATA + (UINT16(3) + attribute)
|
||||
@ -429,6 +431,9 @@ static int spd_append_range(struct sdp_context_filter_attributes* context, uint1
|
||||
}
|
||||
|
||||
static int sdp_traversal_filter_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
|
||||
UNUSED(type);
|
||||
UNUSED(size);
|
||||
|
||||
struct sdp_context_filter_attributes * context = (struct sdp_context_filter_attributes *) my_context;
|
||||
|
||||
if (!sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) return 0;
|
||||
@ -488,6 +493,9 @@ struct sdp_context_get_filtered_size {
|
||||
};
|
||||
|
||||
static int sdp_traversal_get_filtered_size(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
|
||||
UNUSED(type);
|
||||
UNUSED(size);
|
||||
|
||||
struct sdp_context_get_filtered_size * context = (struct sdp_context_get_filtered_size *) my_context;
|
||||
if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
|
||||
context->size += 3 + de_get_len(attributeValue);
|
||||
@ -510,6 +518,9 @@ struct sdp_context_attribute_by_id {
|
||||
uint8_t * attributeValue;
|
||||
};
|
||||
static int sdp_traversal_attribute_by_id(uint16_t attributeID, uint8_t * attributeValue, de_type_t attributeType, de_size_t size, void *my_context){
|
||||
UNUSED(attributeType);
|
||||
UNUSED(size);
|
||||
|
||||
struct sdp_context_attribute_by_id * context = (struct sdp_context_attribute_by_id *) my_context;
|
||||
if (attributeID == context->attributeID) {
|
||||
context->attributeValue = attributeValue;
|
||||
@ -574,6 +585,8 @@ struct sdp_context_contains_uuid128 {
|
||||
};
|
||||
int sdp_record_contains_UUID128(uint8_t *record, uint8_t *uuid128);
|
||||
static int sdp_traversal_contains_UUID128(uint8_t * element, de_type_t type, de_size_t size, void *my_context){
|
||||
UNUSED(size);
|
||||
|
||||
struct sdp_context_contains_uuid128 * context = (struct sdp_context_contains_uuid128 *) my_context;
|
||||
uint8_t normalizedUUID[16];
|
||||
if (type == DE_UUID){
|
||||
@ -602,6 +615,9 @@ struct sdp_context_match_pattern {
|
||||
};
|
||||
|
||||
int sdp_traversal_match_pattern(uint8_t * element, de_type_t attributeType, de_size_t size, void *my_context){
|
||||
UNUSED(attributeType);
|
||||
UNUSED(size);
|
||||
|
||||
struct sdp_context_match_pattern * context = (struct sdp_context_match_pattern *) my_context;
|
||||
uint8_t normalizedUUID[16];
|
||||
uint8_t uuidOK = de_get_normalized_uuid(normalizedUUID, element);
|
||||
|
151
src/hci.c
151
src/hci.c
@ -45,9 +45,11 @@
|
||||
#include "btstack_config.h"
|
||||
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
#ifdef HAVE_EMBEDDED_TICK
|
||||
#include "btstack_run_loop_embedded.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PLATFORM_IPHONE_OS
|
||||
#include "../port/ios/src/btstack_control_iphone.h"
|
||||
@ -103,10 +105,12 @@ static int hci_is_le_connection(hci_connection_t * connection);
|
||||
static int hci_number_free_acl_slots_for_connection_type( bd_addr_type_t address_type);
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// called from test/ble_client/advertising_data_parser.c
|
||||
void le_handle_advertisement_report(uint8_t *packet, int size);
|
||||
static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// the STACK is here
|
||||
#ifndef HAVE_MALLOC
|
||||
@ -114,8 +118,10 @@ static hci_stack_t hci_stack_static;
|
||||
#endif
|
||||
static hci_stack_t * hci_stack = NULL;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
// test helper
|
||||
static uint8_t disable_l2cap_timeouts = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* create connection for given address
|
||||
@ -814,10 +820,12 @@ uint16_t hci_max_acl_data_packet_length(void){
|
||||
return hci_stack->acl_data_packet_length;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
int hci_extended_sco_link_supported(void){
|
||||
// No. 31, byte 3, bit 7
|
||||
return (hci_stack->local_supported_features[3] & (1 << 7)) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int hci_non_flushable_packet_boundary_flag_supported(void){
|
||||
// No. 54, byte 6, bit 6
|
||||
@ -858,7 +866,11 @@ void gap_advertisements_get_address(uint8_t * addr_type, bd_addr_t addr){
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
void le_handle_advertisement_report(uint8_t *packet, int size){
|
||||
|
||||
UNUSED(size);
|
||||
|
||||
int offset = 3;
|
||||
int num_reports = packet[offset];
|
||||
offset += 1;
|
||||
@ -884,6 +896,9 @@ void le_handle_advertisement_report(uint8_t *packet, int size){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
|
||||
static uint32_t hci_transport_uart_get_main_baud_rate(void){
|
||||
if (!hci_stack->config) return 0;
|
||||
@ -896,6 +911,8 @@ static uint32_t hci_transport_uart_get_main_baud_rate(void){
|
||||
}
|
||||
|
||||
static void hci_initialization_timeout_handler(btstack_timer_source_t * ds){
|
||||
UNUSED(ds);
|
||||
|
||||
switch (hci_stack->substate){
|
||||
case HCI_INIT_W4_SEND_RESET:
|
||||
log_info("Resend HCI Reset");
|
||||
@ -931,6 +948,7 @@ static void hci_initialization_timeout_handler(btstack_timer_source_t * ds){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hci_initializing_next_state(void){
|
||||
hci_stack->substate = (hci_substate_t )( ((int) hci_stack->substate) + 1);
|
||||
@ -943,7 +961,7 @@ static void hci_initializing_run(void){
|
||||
case HCI_INIT_SEND_RESET:
|
||||
hci_state_reset();
|
||||
|
||||
#ifndef HAVE_PLATFORM_IPHONE_OS
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
// prepare reset if command complete not received in 100ms
|
||||
btstack_run_loop_set_timer(&hci_stack->timeout, HCI_RESET_RESEND_TIMEOUT_MS);
|
||||
btstack_run_loop_set_timer_handler(&hci_stack->timeout, hci_initialization_timeout_handler);
|
||||
@ -961,6 +979,8 @@ static void hci_initializing_run(void){
|
||||
hci_send_cmd(&hci_read_local_name);
|
||||
hci_stack->substate = HCI_INIT_W4_SEND_READ_LOCAL_NAME;
|
||||
break;
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
case HCI_INIT_SEND_RESET_CSR_WARM_BOOT:
|
||||
hci_state_reset();
|
||||
// prepare reset if command complete not received in 100ms
|
||||
@ -1051,11 +1071,6 @@ static void hci_initializing_run(void){
|
||||
hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
|
||||
hci_send_cmd(&hci_read_local_supported_commands);
|
||||
break;
|
||||
case HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS:
|
||||
log_info("Resend hci_read_local_supported_commands after CSR Warm Boot double reset");
|
||||
hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
|
||||
hci_send_cmd(&hci_read_local_supported_commands);
|
||||
break;
|
||||
case HCI_INIT_SET_BD_ADDR:
|
||||
log_info("Set Public BD ADDR to %s", bd_addr_to_str(hci_stack->custom_bd_addr));
|
||||
hci_stack->chipset->set_bd_addr_command(hci_stack->custom_bd_addr, hci_stack->hci_packet_buffer);
|
||||
@ -1063,6 +1078,13 @@ static void hci_initializing_run(void){
|
||||
hci_stack->substate = HCI_INIT_W4_SET_BD_ADDR;
|
||||
hci_send_cmd_packet(hci_stack->hci_packet_buffer, 3 + hci_stack->hci_packet_buffer[2]);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS:
|
||||
log_info("Resend hci_read_local_supported_commands after CSR Warm Boot double reset");
|
||||
hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
|
||||
hci_send_cmd(&hci_read_local_supported_commands);
|
||||
break;
|
||||
case HCI_INIT_READ_BD_ADDR:
|
||||
hci_stack->substate = HCI_INIT_W4_READ_BD_ADDR;
|
||||
hci_send_cmd(&hci_read_bd_addr);
|
||||
@ -1168,6 +1190,8 @@ static void hci_init_done(void){
|
||||
}
|
||||
|
||||
static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
UNUSED(size);
|
||||
|
||||
uint8_t command_completed = 0;
|
||||
|
||||
if (hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_COMPLETE){
|
||||
@ -1195,6 +1219,8 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
|
||||
// Vendor == CSR
|
||||
if (hci_stack->substate == HCI_INIT_W4_CUSTOM_INIT && hci_event_packet_get_type(packet) == HCI_EVENT_VENDOR_SPECIFIC){
|
||||
// TODO: track actual command
|
||||
@ -1258,20 +1284,28 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!command_completed) return;
|
||||
|
||||
int need_baud_change = hci_stack->config
|
||||
int need_baud_change = 0;
|
||||
int need_addr_change = 0;
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
need_baud_change = hci_stack->config
|
||||
&& hci_stack->chipset
|
||||
&& hci_stack->chipset->set_baudrate_command
|
||||
&& hci_stack->hci_transport->set_baudrate
|
||||
&& ((hci_transport_config_uart_t *)hci_stack->config)->baudrate_main;
|
||||
|
||||
int need_addr_change = hci_stack->custom_bd_addr_set
|
||||
need_addr_change = hci_stack->custom_bd_addr_set
|
||||
&& hci_stack->chipset
|
||||
&& hci_stack->chipset->set_bd_addr_command;
|
||||
#endif
|
||||
|
||||
switch(hci_stack->substate){
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
case HCI_INIT_SEND_RESET:
|
||||
// on CSR with BCSP/H5, resend triggers resend of HCI Reset and leads to substate == HCI_INIT_SEND_RESET
|
||||
// fix: just correct substate and behave as command below
|
||||
@ -1308,6 +1342,12 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
// repeat custom init
|
||||
hci_stack->substate = HCI_INIT_CUSTOM_INIT;
|
||||
return;
|
||||
#else
|
||||
case HCI_INIT_W4_SEND_RESET:
|
||||
hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS;
|
||||
return ;
|
||||
#endif
|
||||
|
||||
case HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS:
|
||||
if (need_baud_change && hci_stack->manufacturer == COMPANY_ID_BROADCOM_CORPORATION){
|
||||
hci_stack->substate = HCI_INIT_SEND_BAUD_CHANGE_BCM;
|
||||
@ -1319,6 +1359,7 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
}
|
||||
hci_stack->substate = HCI_INIT_READ_BD_ADDR;
|
||||
return;
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
case HCI_INIT_W4_SEND_BAUD_CHANGE_BCM:
|
||||
if (need_baud_change){
|
||||
uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
|
||||
@ -1343,6 +1384,7 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
|
||||
case HCI_INIT_W4_SEND_RESET_ST_WARM_BOOT:
|
||||
hci_stack->substate = HCI_INIT_READ_BD_ADDR;
|
||||
return;
|
||||
#endif
|
||||
case HCI_INIT_W4_READ_BD_ADDR:
|
||||
// only read buffer size if supported
|
||||
if (hci_stack->local_supported_commands[0] & 0x01) {
|
||||
@ -1449,6 +1491,7 @@ static void event_handler(uint8_t *packet, int size){
|
||||
hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
|
||||
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
|
||||
if (packet[5]) break;
|
||||
// terminate, name 248 chars
|
||||
packet[6+248] = 0;
|
||||
log_info("local name: %s", &packet[6]);
|
||||
@ -1482,10 +1525,12 @@ static void event_handler(uint8_t *packet, int size){
|
||||
}
|
||||
log_info("hci_le_read_buffer_size: size %u, count %u", hci_stack->le_data_packets_length, hci_stack->le_acl_packets_total_num);
|
||||
}
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_white_list_size)){
|
||||
hci_stack->le_whitelist_capacity = little_endian_read_16(packet, 6);
|
||||
log_info("hci_le_read_white_list_size: size %u", hci_stack->le_whitelist_capacity);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_bd_addr)) {
|
||||
reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1],
|
||||
@ -1523,10 +1568,6 @@ static void event_handler(uint8_t *packet, int size){
|
||||
hci_stack->manufacturer = little_endian_read_16(packet, 10);
|
||||
// hci_stack->lmp_subversion = little_endian_read_16(packet, 12);
|
||||
log_info("Manufacturer: 0x%04x", hci_stack->manufacturer);
|
||||
// notify app
|
||||
if (hci_stack->local_version_information_callback){
|
||||
hci_stack->local_version_information_callback(packet);
|
||||
}
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_commands)){
|
||||
hci_stack->local_supported_commands[0] =
|
||||
@ -1536,11 +1577,13 @@ static void event_handler(uint8_t *packet, int size){
|
||||
(packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+18] & 0x08); // bit 3 = Octet 18, bit 3
|
||||
log_info("Local supported commands summary 0x%02x", hci_stack->local_supported_commands[0]);
|
||||
}
|
||||
#ifdef ENABLE_CLASSIC
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_synchronous_flow_control_enable)){
|
||||
if (packet[5] == 0){
|
||||
hci_stack->synchronous_flow_control_enabled = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_STATUS:
|
||||
@ -1808,9 +1851,11 @@ static void event_handler(uint8_t *packet, int size){
|
||||
conn = hci_connection_for_handle(handle);
|
||||
if (!conn) break;
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
if (hci_is_le_connection(conn) && hci_stack->le_advertisements_enabled){
|
||||
hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_ENABLE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
conn->state = RECEIVED_DISCONNECTION_COMPLETE;
|
||||
break;
|
||||
@ -1826,6 +1871,7 @@ static void event_handler(uint8_t *packet, int size){
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
case HCI_EVENT_ROLE_CHANGE:
|
||||
if (packet[2]) break; // status != 0
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
@ -1833,6 +1879,7 @@ static void event_handler(uint8_t *packet, int size){
|
||||
if (!conn) break; // no conn
|
||||
conn->role = packet[9];
|
||||
break;
|
||||
#endif
|
||||
|
||||
case HCI_EVENT_TRANSPORT_PACKET_SENT:
|
||||
// release packet buffer only for asynchronous transport and if there are not further fragements
|
||||
@ -1861,17 +1908,20 @@ static void event_handler(uint8_t *packet, int size){
|
||||
#ifdef ENABLE_BLE
|
||||
case HCI_EVENT_LE_META:
|
||||
switch (packet[2]){
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
case HCI_SUBEVENT_LE_ADVERTISING_REPORT:
|
||||
// log_info("advertising report received");
|
||||
if (hci_stack->le_scanning_state != LE_SCANNING) break;
|
||||
le_handle_advertisement_report(packet, size);
|
||||
break;
|
||||
#endif
|
||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
||||
// Connection management
|
||||
reverse_bd_addr(&packet[8], addr);
|
||||
addr_type = (bd_addr_type_t)packet[7];
|
||||
log_info("LE Connection_complete (status=%u) type %u, %s", packet[3], addr_type, bd_addr_to_str(addr));
|
||||
conn = hci_connection_for_bd_addr_and_type(addr, addr_type);
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// if auto-connect, remove from whitelist in both roles
|
||||
if (hci_stack->le_connecting_state == LE_CONNECTING_WHITELIST){
|
||||
hci_remove_from_whitelist(addr_type, addr);
|
||||
@ -1887,15 +1937,20 @@ static void event_handler(uint8_t *packet, int size){
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// on success, both hosts receive connection complete event
|
||||
if (packet[6] == HCI_ROLE_MASTER){
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// if we're master, it was an outgoing connection and we're done with it
|
||||
hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
// if we're slave, it was an incoming connection, advertisements have stopped
|
||||
hci_stack->le_advertisements_active = 0;
|
||||
// try to re-enable them
|
||||
hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_ENABLE;
|
||||
#endif
|
||||
}
|
||||
// LE connections are auto-accepted, so just create a connection if there isn't one already
|
||||
if (!conn){
|
||||
@ -2035,14 +2090,19 @@ static void hci_state_reset(void){
|
||||
hci_stack->new_scan_enable_value = 0xff;
|
||||
|
||||
// LE
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
hci_stack->adv_addr_type = 0;
|
||||
hci_stack->le_advertisements_random_address_set = 0;
|
||||
memset(hci_stack->adv_address, 0, 6);
|
||||
#endif
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
hci_stack->le_scanning_state = LE_SCAN_IDLE;
|
||||
hci_stack->le_scan_type = 0xff;
|
||||
hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
|
||||
hci_stack->le_whitelist = 0;
|
||||
hci_stack->le_whitelist_capacity = 0;
|
||||
#endif
|
||||
|
||||
hci_stack->le_connection_parameter_range.le_conn_interval_min = 6;
|
||||
hci_stack->le_connection_parameter_range.le_conn_interval_max = 3200;
|
||||
hci_stack->le_connection_parameter_range.le_conn_latency_min = 0;
|
||||
@ -2159,17 +2219,20 @@ void hci_close(void){
|
||||
void gap_set_class_of_device(uint32_t class_of_device){
|
||||
hci_stack->class_of_device = class_of_device;
|
||||
}
|
||||
|
||||
void hci_disable_l2cap_timeout_check(void){
|
||||
disable_l2cap_timeouts = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
|
||||
// Set Public BD ADDR - passed on to Bluetooth chipset if supported in bt_control_h
|
||||
void hci_set_bd_addr(bd_addr_t addr){
|
||||
memcpy(hci_stack->custom_bd_addr, addr, 6);
|
||||
hci_stack->custom_bd_addr_set = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void hci_disable_l2cap_timeout_check(void){
|
||||
disable_l2cap_timeouts = 1;
|
||||
}
|
||||
// State-Module-Driver overview
|
||||
// state module low-level
|
||||
// HCI_STATE_OFF off close
|
||||
@ -2502,6 +2565,8 @@ static void hci_run(void){
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
if (hci_stack->state == HCI_STATE_WORKING){
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
// handle le scan
|
||||
switch(hci_stack->le_scanning_state){
|
||||
case LE_START_SCAN:
|
||||
@ -2523,6 +2588,8 @@ static void hci_run(void){
|
||||
hci_send_cmd(&hci_le_set_scan_parameters, scan_type, hci_stack->le_scan_interval, hci_stack->le_scan_window, hci_stack->adv_addr_type, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
// le advertisement control
|
||||
if (hci_stack->le_advertisements_todo){
|
||||
log_info("hci_run: gap_le: adv todo: %x", hci_stack->le_advertisements_todo );
|
||||
@ -2564,7 +2631,9 @@ static void hci_run(void){
|
||||
hci_send_cmd(&hci_le_set_advertise_enable, 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
//
|
||||
// LE Whitelist Management
|
||||
//
|
||||
@ -2631,6 +2700,7 @@ static void hci_run(void){
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2649,6 +2719,7 @@ static void hci_run(void){
|
||||
#endif
|
||||
default:
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
log_info("sending hci_le_create_connection");
|
||||
hci_send_cmd(&hci_le_create_connection,
|
||||
0x0060, // scan interval: 60 ms
|
||||
@ -2666,6 +2737,7 @@ static void hci_run(void){
|
||||
);
|
||||
|
||||
connection->state = SENT_CREATE_CONNECTION;
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -2683,10 +2755,12 @@ static void hci_run(void){
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
case SEND_CANCEL_CONNECTION:
|
||||
connection->state = SENT_CANCEL_CONNECTION;
|
||||
hci_send_cmd(&hci_le_create_connection_cancel);
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
case SEND_DISCONNECT:
|
||||
connection->state = SENT_DISCONNECT;
|
||||
@ -2751,7 +2825,6 @@ static void hci_run(void){
|
||||
hci_send_cmd(&hci_user_passkey_request_reply, &connection->address, 000000);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connection->bonding_flags & BONDING_REQUEST_REMOTE_FEATURES){
|
||||
connection->bonding_flags &= ~BONDING_REQUEST_REMOTE_FEATURES;
|
||||
@ -2759,27 +2832,31 @@ static void hci_run(void){
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->bonding_flags & BONDING_DISCONNECT_SECURITY_BLOCK){
|
||||
connection->bonding_flags &= ~BONDING_DISCONNECT_SECURITY_BLOCK;
|
||||
hci_send_cmd(&hci_disconnect, connection->con_handle, 0x0005); // authentication failure
|
||||
return;
|
||||
}
|
||||
if (connection->bonding_flags & BONDING_DISCONNECT_DEDICATED_DONE){
|
||||
connection->bonding_flags &= ~BONDING_DISCONNECT_DEDICATED_DONE;
|
||||
connection->bonding_flags |= BONDING_EMIT_COMPLETE_ON_DISCONNECT;
|
||||
hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13); // authentication done
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->bonding_flags & BONDING_SEND_AUTHENTICATE_REQUEST){
|
||||
connection->bonding_flags &= ~BONDING_SEND_AUTHENTICATE_REQUEST;
|
||||
hci_send_cmd(&hci_authentication_requested, connection->con_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->bonding_flags & BONDING_SEND_ENCRYPTION_REQUEST){
|
||||
connection->bonding_flags &= ~BONDING_SEND_ENCRYPTION_REQUEST;
|
||||
hci_send_cmd(&hci_set_connection_encryption, connection->con_handle, 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connection->bonding_flags & BONDING_DISCONNECT_SECURITY_BLOCK){
|
||||
connection->bonding_flags &= ~BONDING_DISCONNECT_SECURITY_BLOCK;
|
||||
hci_send_cmd(&hci_disconnect, connection->con_handle, 0x0005); // authentication failure
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
if (connection->le_con_parameter_update_state == CON_PARAMETER_UPDATE_CHANGE_HCI_CON_PARAMETERS){
|
||||
@ -2806,6 +2883,7 @@ static void hci_run(void){
|
||||
|
||||
// free whitelist entries
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
{
|
||||
btstack_linked_list_iterator_t lit;
|
||||
btstack_linked_list_iterator_init(&lit, &hci_stack->le_whitelist);
|
||||
@ -2815,6 +2893,7 @@ static void hci_run(void){
|
||||
btstack_memory_whitelist_entry_free(entry);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
// close all open connections
|
||||
connection = (hci_connection_t *) hci_stack->connections;
|
||||
@ -2988,16 +3067,19 @@ int hci_send_cmd_packet(uint8_t *packet, int size){
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
if (IS_COMMAND(packet, hci_le_set_advertising_parameters)){
|
||||
hci_stack->adv_addr_type = packet[8];
|
||||
}
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
if (IS_COMMAND(packet, hci_le_set_random_address)){
|
||||
hci_stack->le_advertisements_random_address_set = 1;
|
||||
reverse_bd_addr(&packet[3], hci_stack->adv_address);
|
||||
}
|
||||
if (IS_COMMAND(packet, hci_le_set_advertising_parameters)){
|
||||
hci_stack->adv_addr_type = packet[8];
|
||||
}
|
||||
if (IS_COMMAND(packet, hci_le_set_advertise_enable)){
|
||||
hci_stack->le_advertisements_active = packet[3];
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
if (IS_COMMAND(packet, hci_le_create_connection)){
|
||||
// white list used?
|
||||
uint8_t initiator_filter_policy = packet[7];
|
||||
@ -3017,6 +3099,7 @@ int hci_send_cmd_packet(uint8_t *packet, int size){
|
||||
if (IS_COMMAND(packet, hci_le_create_connection_cancel)){
|
||||
hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
hci_stack->num_cmd_packets--;
|
||||
@ -3164,6 +3247,7 @@ static void hci_emit_l2cap_check_timeout(hci_connection_t *conn){
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
static void hci_emit_le_connection_complete(uint8_t address_type, bd_addr_t address, hci_con_handle_t con_handle, uint8_t status){
|
||||
uint8_t event[21];
|
||||
event[0] = HCI_EVENT_LE_META;
|
||||
@ -3181,6 +3265,7 @@ static void hci_emit_le_connection_complete(uint8_t address_type, bd_addr_t addr
|
||||
hci_emit_event(event, sizeof(event), 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void hci_emit_disconnection_complete(hci_con_handle_t con_handle, uint8_t reason){
|
||||
uint8_t event[6];
|
||||
@ -3250,6 +3335,7 @@ static void hci_emit_discoverable_enabled(uint8_t enabled){
|
||||
hci_emit_event(event, sizeof(event), 1);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
// query if remote side supports eSCO
|
||||
int hci_remote_esco_supported(hci_con_handle_t con_handle){
|
||||
hci_connection_t * connection = hci_connection_for_handle(con_handle);
|
||||
@ -3267,6 +3353,7 @@ int hci_remote_ssp_supported(hci_con_handle_t con_handle){
|
||||
int gap_ssp_supported_on_both_sides(hci_con_handle_t handle){
|
||||
return hci_local_ssp_activated() && hci_remote_ssp_supported(handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
// GAP API
|
||||
/**
|
||||
@ -3397,6 +3484,7 @@ void gap_set_local_name(const char * local_name){
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
void gap_start_scan(void){
|
||||
if (hci_stack->le_scanning_state == LE_SCANNING) return;
|
||||
hci_stack->le_scanning_state = LE_START_SCAN;
|
||||
@ -3484,6 +3572,7 @@ uint8_t gap_connect_cancel(void){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Updates the connection parameters for a given LE connection
|
||||
@ -3529,6 +3618,8 @@ int gap_request_connection_parameter_update(hci_con_handle_t con_handle, uint16_
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
|
||||
static void gap_advertisments_changed(void){
|
||||
// disable advertisements before updating adv, scan data, or adv params
|
||||
if (hci_stack->le_advertisements_active){
|
||||
@ -3614,6 +3705,7 @@ void gap_advertisements_enable(int enabled){
|
||||
hci_run();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint8_t gap_disconnect(hci_con_handle_t handle){
|
||||
@ -3650,6 +3742,7 @@ gap_connection_type_t gap_get_connection_type(hci_con_handle_t connection_handle
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
/**
|
||||
* @brief Auto Connection Establishment - Start Connecting to device
|
||||
* @param address_typ
|
||||
@ -3720,7 +3813,7 @@ void gap_auto_connection_stop_all(void){
|
||||
}
|
||||
hci_run();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
@ -3774,14 +3867,6 @@ void hci_set_hardware_error_callback(void (*fn)(uint8_t error)){
|
||||
hci_stack->hardware_error_callback = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set callback for local information from Bluetooth controller right after HCI Reset
|
||||
* @note Can be used to select chipset driver dynamically during startup
|
||||
*/
|
||||
void hci_set_local_version_information_callback(void (*fn)(uint8_t * local_version_information)){
|
||||
hci_stack->local_version_information_callback = fn;
|
||||
}
|
||||
|
||||
void hci_disconnect_all(void){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &hci_stack->connections);
|
||||
|
21
src/hci.h
21
src/hci.h
@ -620,9 +620,6 @@ typedef struct {
|
||||
/* callbacks for events */
|
||||
btstack_linked_list_t event_handlers;
|
||||
|
||||
// local version information callback
|
||||
void (*local_version_information_callback)(uint8_t * local_version_information);
|
||||
|
||||
// hardware error callback
|
||||
void (*hardware_error_callback)(uint8_t error);
|
||||
|
||||
@ -702,6 +699,7 @@ typedef struct {
|
||||
uint8_t adv_addr_type;
|
||||
bd_addr_t adv_address;
|
||||
|
||||
#ifdef ENABLE_LE_CENTRAL
|
||||
le_scanning_state_t le_scanning_state;
|
||||
le_connecting_state_t le_connecting_state;
|
||||
|
||||
@ -710,8 +708,14 @@ typedef struct {
|
||||
uint16_t le_scan_interval;
|
||||
uint16_t le_scan_window;
|
||||
|
||||
// LE Whitelist Management
|
||||
uint16_t le_whitelist_capacity;
|
||||
btstack_linked_list_t le_whitelist;
|
||||
#endif
|
||||
|
||||
le_connection_parameter_range_t le_connection_parameter_range;
|
||||
|
||||
#ifdef ENABLE_LE_PERIPHERAL
|
||||
uint8_t * le_advertisements_data;
|
||||
uint8_t le_advertisements_data_len;
|
||||
|
||||
@ -731,10 +735,7 @@ typedef struct {
|
||||
uint8_t le_advertisements_channel_map;
|
||||
uint8_t le_advertisements_filter_policy;
|
||||
bd_addr_t le_advertisements_direct_address;
|
||||
|
||||
// LE Whitelist Management
|
||||
uint16_t le_whitelist_capacity;
|
||||
btstack_linked_list_t le_whitelist;
|
||||
#endif
|
||||
|
||||
// custom BD ADDR
|
||||
bd_addr_t custom_bd_addr;
|
||||
@ -774,12 +775,6 @@ void hci_set_link_key_db(btstack_link_key_db_t const * link_key_db);
|
||||
*/
|
||||
void hci_set_hardware_error_callback(void (*fn)(uint8_t error));
|
||||
|
||||
/**
|
||||
* @brief Set callback for local information from Bluetooth controller right after HCI Reset
|
||||
* @note Can be used to select chipset driver dynamically during startup
|
||||
*/
|
||||
void hci_set_local_version_information_callback(void (*fn)(uint8_t * local_version_information));
|
||||
|
||||
/**
|
||||
* @brief Set Public BD ADDR - passed on to Bluetooth chipset during init if supported in bt_control_h
|
||||
*/
|
||||
|
@ -107,14 +107,20 @@ void hci_dump_open(const char *filename, hci_dump_format_t format){
|
||||
dump_file = fileno(stdout);
|
||||
} else {
|
||||
|
||||
# ifdef _WIN32
|
||||
dump_file = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
# else
|
||||
dump_file = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
# endif
|
||||
int oflags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
#ifdef _WIN32
|
||||
oflags |= O_BINARY;
|
||||
#endif
|
||||
|
||||
dump_file = open(filename, oflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
|
||||
if (dump_file < 0){
|
||||
printf("hci_dump_open: failed to open file %s\n", filename);
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNUSED(filename);
|
||||
UNUSED(format);
|
||||
|
||||
dump_file = 1;
|
||||
#endif
|
||||
}
|
||||
@ -140,6 +146,13 @@ static void printf_packet(uint8_t packet_type, uint8_t in, uint8_t * packet, uin
|
||||
printf("ACL => ");
|
||||
}
|
||||
break;
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
if (in) {
|
||||
printf("SCO <= ");
|
||||
} else {
|
||||
printf("SCO => ");
|
||||
}
|
||||
break;
|
||||
case LOG_MESSAGE_PACKET:
|
||||
printf("LOG -- %s\n", (char*) packet);
|
||||
return;
|
||||
|
18
src/l2cap.c
18
src/l2cap.c
@ -197,6 +197,8 @@ void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t
|
||||
}
|
||||
|
||||
void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
UNUSED(con_handle);
|
||||
|
||||
int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
|
||||
if (index < 0) return;
|
||||
fixed_channels[index].waiting_for_can_send_now = 1;
|
||||
@ -204,6 +206,8 @@ void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, u
|
||||
}
|
||||
|
||||
int l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
UNUSED(channel_id);
|
||||
|
||||
return hci_can_send_acl_packet_now(con_handle);
|
||||
}
|
||||
|
||||
@ -1070,6 +1074,10 @@ static void l2cap_notify_channel_can_send(void){
|
||||
}
|
||||
|
||||
static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *packet, uint16_t size){
|
||||
|
||||
UNUSED(packet_type);
|
||||
UNUSED(cid);
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t address;
|
||||
hci_con_handle_t handle;
|
||||
@ -1080,7 +1088,8 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
UNUSED(address);
|
||||
UNUSED(hci_con_used);
|
||||
UNUSED(it);
|
||||
|
||||
UNUSED(handle);
|
||||
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
|
||||
// Notify channel packet handler if they can send now
|
||||
@ -1122,8 +1131,8 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
// handle disconnection complete events
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// send l2cap disconnect events for all channels on this handle and free them
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
#ifdef ENABLE_CLASSIC
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
|
||||
@ -1135,6 +1144,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_le_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
|
||||
@ -1842,7 +1852,9 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
|
||||
#endif
|
||||
|
||||
static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ){
|
||||
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
|
||||
l2cap_channel_t * l2cap_channel;
|
||||
UNUSED(l2cap_channel);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// btstack_config.h for Arduino port
|
||||
// btstack_config.h for most tests
|
||||
//
|
||||
|
||||
#ifndef __BTSTACK_CONFIG
|
||||
@ -21,6 +21,9 @@
|
||||
#define ENABLE_SDP_DES_DUMP
|
||||
#define ENABLE_SDP_EXTRA_QUERIES
|
||||
// #define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LE_SIGNED_WRITE
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE 52
|
||||
|
Loading…
x
Reference in New Issue
Block a user