Merge branch 'develop' into a2dp

This commit is contained in:
Milanka Ringwald 2017-01-16 15:30:07 +01:00
commit d3d88e8bb5
93 changed files with 1357 additions and 421 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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