mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 01:27:41 +00:00
Merge branch 'develop' into windows-h4
This commit is contained in:
commit
5c7fd12999
@ -35,12 +35,14 @@ 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.
|
||||
|
||||
For information on MFi/iAP2 support, please <a href="mailto:contact@bluekitchen-gmbh.com">contact us</a>.
|
||||
|
||||
## Evaluation Platforms
|
||||
|
||||
#### Embedded Platforms:
|
||||
|
@ -31,9 +31,9 @@ Broadcom, whose Bluetooth + Wifi division has been acquired by the Cypress Semic
|
||||
|
||||
CSR, which has been acquired by Qualcomm, provides all relevant information on their Support website after signing an NDA.
|
||||
|
||||
Chipset | Type | HCI Transport | BD_ADDR (1) | SCO over HCI (2) | LE DLE | Multiple LE Roles (3)| BTstack folder | Comment
|
||||
Chipset | Type | HCI Transport | BD_ADDR (1) | SCO over HCI (2) | LE DLE | Multiple LE Roles | BTstack folder | Comment
|
||||
-------------------- |-----------| ---------------|--------------|------------------|--------|----------------------|----------------|---------
|
||||
Broadcom UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | Maybe | bcm | Max UART baudrate 3 mbps
|
||||
Broadcom UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | Maybe (3) | bcm | Max UART baudrate 3 mbps
|
||||
Broadcom USB Dongles | Dual mode | USB | Yes | No (didn't work) | No | No | bcm |
|
||||
CSR UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | No | csr |
|
||||
CSR USB Dongles | Dual mode | USB | Mostly | Yes | No | No | csr |
|
||||
@ -43,13 +43,13 @@ EM 9304 | LE | SPI, H4 | ? | n.a.
|
||||
Nordic nRF | LE | H4 | fixed random | n.a. | Yes | Yes | | Requires custom HCI firmware
|
||||
STM STLC2500D | Classic | H4 | No | No (didn't try) | n.a | n.a. | stlc2500d | Custom deep sleep management not supported
|
||||
Toshiba TC35661 | Dual mode | H4 | No | No (didn't try) | No | No | tc3566 | HCI version not tested. See below
|
||||
TI CC256x, WL183x | Dual mode | H4, H5, eHCILL | Yes | Yes | No | No | cc256x | Also WL185x, WL187x, and WL189x
|
||||
TI CC256x, WL183x | Dual mode | H4, H5, eHCILL | Yes | Yes | No | Yes for CC256XC | cc256x | Also WL185x, WL187x, and WL189x
|
||||
|
||||
**Notes**:
|
||||
|
||||
1. BD_ADDR: Not all Bluetooth chipset come with a fixed valid MAC Address. Better Broadcom and CSR dongles come with a MAC address from the dongle manufacturer, but cheaper ones might come with identical addresses.
|
||||
2. SCO over HCI: All Bluetooth Classic chipsets support SCO over HCI, for those that are marked with No, we either didn't try or didn't found enough information to configure it correctly.
|
||||
2. Multiple LE Roles: Apple uses Broadcom Bluetooth+Wifi in their iOS devices and newer iOS versions support multipe concurrent LE roles,
|
||||
3. Multiple LE Roles: Apple uses Broadcom Bluetooth+Wifi in their iOS devices and newer iOS versions support multipe concurrent LE roles,
|
||||
so at least some Broadcom models support multiple concurrent LE roles.
|
||||
|
||||
## Broadcom
|
||||
@ -178,39 +178,39 @@ STMicroelectronics offers the Bluetooth V2.1 + EDR chipset STLC2500D that suppor
|
||||
|
||||
## Texas Instruments CC256x series
|
||||
|
||||
The Texas Instruments CC256x series is currently in its third iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT model (CC2567). A variant of the Dual-mode chipset is also integrated into TI's WiLink 8 Wifi+Bluetooth combo modules of the WL183x, WL185x, WL187x, and WL189x series.
|
||||
The Texas Instruments CC256x series is currently in its fourth iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT (CC2567) model. A variant of the Dual-mode chipset is also integrated into TI's WiLink 8 Wifi+Bluetooth combo modules of the WL183x, WL185x, WL187x, and WL189x series.
|
||||
|
||||
The CC256x chipset is connected via an UART connection and supports the H4, H5 (since third iteration), and eHCILL.
|
||||
|
||||
The latest generation CC256xC chipsets support multiple LE roles in parallel.
|
||||
|
||||
The different CC256x chipset can be identified by the LMP Subversion returned by the *hci_read_local_version_information* command. TI also uses a numeric way (AKA) to identify their chipsets. The table shows the LMP Subversion and AKA number for the main CC256x series.
|
||||
|
||||
Chipset | LMP Subversion | AKA
|
||||
--------|----------------|-------
|
||||
CC2560 | 0x191f | 6.2.31
|
||||
CC2560A, CC2564 | 0x1B0F | 6.6.15
|
||||
CC256xB | 0x1B90 | 6.7.16
|
||||
CC256xC | 0x9a1a | 6.12.26
|
||||
|
||||
**SCO data** is routed to the I2S/PCM interface but can be configured with the [HCI_VS_Write_SCO_Configuration](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Write_SCO_Configuration_.280xFE10.29) command.
|
||||
|
||||
**Baud rate** can be set with [HCI_VS_Update_UART_HCI_Baudrate](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Update_UART_HCI_Baudrate_.280xFF36.29). The chipset confirms the change with a command complete event after which the local UART is set to the new speed. Oddly enough, the CC256x chipsets ignore the incoming CTS line during this particular command complete response. If the MCU gets UART overrun errors in this situation, a work around could be to set a timer for 100 ms and ignore all incoming data (i.e. the command complete event) during that period. Then, after the timeout, the UART can be set to the new speed safely.
|
||||
|
||||
**BD Addr** can be set with [HCI_VS_Write_BD_Addr](2.2.1 HCI_VS_Write_BD_Addr (0xFC06)) although all chipsets have an official address stored.
|
||||
|
||||
**Init Scripts.** In order to use the CC256x chipset an initialization script must be obtained and converted into a C file for use with BTstack.
|
||||
**Init Scripts.** In order to use the CC256x chipset an initialization script must be obtained and converted into a C file for use with BTstack. For newer revisions, TI provides a main.bts and a ble_add_on.bts that need to be combined.
|
||||
|
||||
The Makefile at *chipset/cc256x/Makefile* is able to automatically download and convert the requested file. It does this by:
|
||||
The Makefile at *chipset/cc256x/Makefile.inc* is able to automatically download and convert the requested file. It does this by:
|
||||
|
||||
- Downloading one or more [BTS files](http://processors.wiki.ti.com/index.php/CC256x_Downloads) for your chipset.
|
||||
- Running the Python script:
|
||||
|
||||
<!-- -->
|
||||
|
||||
./convert_bts_init_scripts.py
|
||||
./convert_bts_init_scripts.py main.bts [ble_add_on.bts] output_file.c
|
||||
|
||||
**Update:** For the latest revision of the CC256x chipsets, the CC2560B
|
||||
and CC2564B, TI decided to split the init script into a main part and
|
||||
the BLE part. The conversion script has been updated to detect
|
||||
*bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts*
|
||||
if present and merges them into a single .c file.
|
||||
|
||||
**Update 2:** In May 2015, TI renamed the init scripts to match
|
||||
the naming scheme previously used on Linux systems. The conversion
|
||||
script has been updated to also detect *initscripts_TIInit_6.7.16_bt_spec_4.1.bts*
|
||||
and integrates *initscripts_TIInit_6.7.16_ble_add-on.bts* if present.
|
||||
|
||||
**BTstack integration**: The common code for all CC256x chipsets is provided by *btstack_chipset_cc256x.c*. During the setup, *btstack_chipset_cc256x_instance* function is used to get a *btstack_chiopset_t* instance and passed to *hci_init* function.
|
||||
**BTstack integration**: The common code for all CC256x chipsets is provided by *btstack_chipset_cc256x.c*. During the setup, *btstack_chipset_cc256x_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function. *btstack_chipset_cc256x_lmp_subversion* provides the LMP Subversion for the selected init script.
|
||||
|
||||
SCO Data can be routed over HCI, so HFP Wide-Band Speech is supported.
|
||||
|
||||
|
@ -1,114 +1,190 @@
|
||||
#
|
||||
# Makefile to download and convert .bts files from
|
||||
# Makefile to download and convert TI's CC256x Service Pack .bts files from
|
||||
# http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
#
|
||||
BASE_URL = https://git.ti.com/ti-bt/service-packs/blobs/raw/a027ae390d8790e56e1c78136c78fe6537470e91
|
||||
# Service Packs for CC256xB v1.5 and CC256xC v1.0 downloaded from BlueKitchen company website
|
||||
# https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/p/560523/2056007#2056007
|
||||
|
||||
TI_GIT_REPO_URL = https://git.ti.com/ti-bt/service-packs/blobs/raw/a027ae390d8790e56e1c78136c78fe6537470e91
|
||||
BLUEKITCHEN_URL = https://bluekitchen-gmbh.com/files/
|
||||
CONVERSION_SCRIPT=$(BTSTACK_ROOT)/chipset/cc256x/convert_bts_init_scripts.py
|
||||
|
||||
# first generation CC2560 - TIInit_6.2.31.bts part of .zip archive
|
||||
|
||||
# First generation CC2560 - AKA TIInit_6.2.31.bts
|
||||
|
||||
# v2.44 - file part of .zip archive
|
||||
|
||||
CC2560_BT_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/d/da/CC2560_BT_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/d/da/CC2560_BT_SP_BTS.zip
|
||||
|
||||
bluetooth_init_cc2560_2.44.bts: CC2560_BT_SP_BTS.zip
|
||||
unzip CC2560_BT_SP_BTS.zip
|
||||
mv CC2560_BT_SP_BTS/bluetooth_init_cc2560_2.44.bts .
|
||||
rm -rf CC2560_BT_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2560_BT_SP_BTS.zip CC2560_BT_SP_BTS/bluetooth_init_cc2560_2.44.bts
|
||||
|
||||
# Second generation CC2560A and CC2564 - AKA TIInit_6.6.15.bts
|
||||
|
||||
# second generation CC2560A and CC2564 - TIInit_6.6.15.bts part of .zip archive
|
||||
# v2.14 - files part of .zip archive
|
||||
|
||||
CC2560A_BT_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/e/e7/CC2560A_BT_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/e/e7/CC2560A_BT_SP_BTS.zip
|
||||
|
||||
CC2564_BT_BLE_SP_BTS.zip:
|
||||
curl -O http://processors.wiki.ti.com/images/1/1e/CC2564_BT_BLE_SP_BTS.zip
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O http://processors.wiki.ti.com/images/1/1e/CC2564_BT_BLE_SP_BTS.zip
|
||||
|
||||
bluetooth_init_cc2560A_2.14.bts: CC2560A_BT_SP_BTS.zip
|
||||
unzip CC2560A_BT_SP_BTS.zip
|
||||
mv CC2560A_BT_SP_BTS/bluetooth_init_cc2560a_2.14.bts .
|
||||
rm -rf CC2560A_BT_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2560A_BT_SP_BTS.zip CC2560A_BT_SP_BTS/bluetooth_init_cc2560A_2.14.bts
|
||||
|
||||
bluetooth_init_cc2564_2.14.bts: CC2564_BT_BLE_SP_BTS.zip
|
||||
unzip CC2564_BT_BLE_SP_BTS.zip
|
||||
mv CC2564_BT_BLE_SP_BTS/bluetooth_init_cc2564_2.14.bts .
|
||||
rm -rf CC2564_BT_BLE_SP_BTS
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o CC2564_BT_BLE_SP_BTS.zip CC2564_BT_BLE_SP_BTS/bluetooth_init_cc2564_2.14.bts
|
||||
|
||||
# Third generation CC256xB - AKA TIInit_6.6.16.bts
|
||||
|
||||
# third generation
|
||||
|
||||
# versioned files for v1.2
|
||||
# v1.2 - versioned files TI Git Repo
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts:
|
||||
curl -O $(BASE_URL)/bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts:
|
||||
curl -O $(BASE_URL)/bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts
|
||||
|
||||
BLE_init_cc2564B_1.2.bts:
|
||||
curl -O $(BASE_URL)/BLE_init_cc2564B_1.2.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/BLE_init_cc2564B_1.2.bts
|
||||
|
||||
# unversioned files for v1.4
|
||||
# v1.4 - versioned files TI Git Repo
|
||||
TIInit_6.7.16_bt_spec_4.1.bts:
|
||||
curl -O https://git.ti.com/ti-bt/service-packs/blobs/raw/54f5c151dacc608b19ab2ce4c30e27a3983048b2/initscripts/TIInit_6.7.16_bt_spec_4.1.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O https://git.ti.com/ti-bt/service-packs/blobs/raw/54f5c151dacc608b19ab2ce4c30e27a3983048b2/initscripts/TIInit_6.7.16_bt_spec_4.1.bts
|
||||
|
||||
TIInit_6.7.16_ble_add-on.bts:
|
||||
curl -O https://git.ti.com/ti-bt/service-packs/blobs/raw/89c8db14929f10d75627b132690432cd71f5f54f/initscripts/TIInit_6.7.16_ble_add-on.bts
|
||||
TIInit_6.7.16_ble_add-on.bts:
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O https://git.ti.com/ti-bt/service-packs/blobs/raw/89c8db14929f10d75627b132690432cd71f5f54f/initscripts/TIInit_6.7.16_ble_add-on.bts
|
||||
|
||||
# v1.5 - unversioned files from BlueKitchen website, original: http://www.ti.com/tool/cc256xb-bt-sp
|
||||
cc256x_bt_sp_v1.5.zip:
|
||||
echo "Downloading $@"
|
||||
@curl -sS -O $(BLUEKITCHEN_URL)/cc256x_bt_sp_v1.5.zip
|
||||
|
||||
initscripts-TIInit_6.7.16_bt_spec_4.1.bts: cc256x_bt_sp_v1.5.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256x_bt_sp_v1.5.zip CC256X_BT_SP/v1.5/initscripts-TIInit_6.7.16_bt_spec_4.1.bts
|
||||
|
||||
initscripts-TIInit_6.7.16_ble_add-on.bts: cc256x_bt_sp_v1.5.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256x_bt_sp_v1.5.zip CC256X_BT_SP/v1.5/initscripts-TIInit_6.7.16_ble_add-on.bts
|
||||
|
||||
|
||||
# Fourth generation CC256xC - TIInit_6.12.26.bts
|
||||
|
||||
# v1.0 - unversioned files from BlueKitchen website, original: http://www.ti.com/tool/cc256xc-bt-sp
|
||||
cc256xc_bt_sp_v1.0.zip:
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(BLUEKITCHEN_URL)/cc256xc_bt_sp_v1.0.zip
|
||||
|
||||
initscripts-TIInit_6.12.26.bts: cc256xc_bt_sp_v1.0.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256xc_bt_sp_v1.0.zip CC256XC_BT_SP/v1.0/initscripts-TIInit_6.12.26.bts
|
||||
|
||||
initscripts-TIInit_6.12.26_ble_add-on.bts: cc256xc_bt_sp_v1.0.zip
|
||||
@echo "Extracting $@"
|
||||
@unzip -q -j -o cc256xc_bt_sp_v1.0.zip CC256XC_BT_SP/v1.0/initscripts-TIInit_6.12.26_ble_add-on.bts
|
||||
|
||||
|
||||
# Various scripts for WL chipsets
|
||||
|
||||
# WL chipset
|
||||
TIInit_11.8.32.bts:
|
||||
curl -O $(BASE_URL)/TIInit_11.8.32.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_11.8.32.bts
|
||||
|
||||
TIInit_12.10.28.bts:
|
||||
curl -O $(BASE_URL)/TIInit_12.10.28.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_12.10.28.bts
|
||||
|
||||
TIInit_12.8.32.bts:
|
||||
curl -O $(BASE_URL)/TIInit_12.8.32.bts
|
||||
@echo "Downloading $@"
|
||||
@curl -sS -O $(TI_GIT_REPO_URL)/TIInit_12.8.32.bts
|
||||
|
||||
|
||||
|
||||
# convert to .c files based on main file and option add-on
|
||||
|
||||
# convert to .c files
|
||||
bluetooth_init_cc2560_2.44.c: bluetooth_init_cc2560_2.44.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560A_2.14.c: bluetooth_init_cc2560A_2.14.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564_2.14.c: bluetooth_init_cc2564_2.14.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c: bluetooth_init_cc2560B_1.2_BT_Spec_4.0.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c: bluetooth_init_cc2564B_1.2_BT_Spec_4.0.bts BLE_init_cc2564B_1.2.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.2_BT_Spec_4.1.c: bluetooth_init_cc2560B_1.2_BT_Spec_4.1.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.2_BT_Spec_4.1.c: bluetooth_init_cc2564B_1.2_BT_Spec_4.1.bts BLE_init_cc2564B_1.2.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.4_BT_Spec_4.1.c: TIInit_6.7.16_bt_spec_4.1.bts
|
||||
cp TIInit_6.7.16_bt_spec_4.1.bts bluetooth_init_cc2560B_1.4_BT_Spec_4.1.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c: TIInit_6.7.16_bt_spec_4.1.bts TIInit_6.7.16_ble_add-on.bts
|
||||
cp TIInit_6.7.16_bt_spec_4.1.bts bluetooth_init_cc2564B_1.4_BT_Spec_4.1.bts
|
||||
cp TIInit_6.7.16_ble_add-on.bts BLE_init_cc2564B_1.4.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560B_1.5_BT_Spec_4.1.c: initscripts-TIInit_6.7.16_bt_spec_4.1.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564B_1.5_BT_Spec_4.1.c: initscripts-TIInit_6.7.16_bt_spec_4.1.bts initscripts-TIInit_6.7.16_ble_add-on.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2560C_1.0.c: initscripts-TIInit_6.12.26.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
bluetooth_init_cc2564C_1.0.c: initscripts-TIInit_6.12.26.bts initscripts-TIInit_6.12.26_ble_add-on.bts
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_11.8.32.c: TIInit_11.8.32.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_12.10.28.c: TIInit_12.10.28.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
TIInit_12.8.32.c: TIInit_12.8.32.bts
|
||||
$(CONVERSION_SCRIPT)
|
||||
@echo "Creating $@"
|
||||
@$(CONVERSION_SCRIPT) $^ $@
|
||||
|
||||
all-scripts: bluetooth_init_cc2560_2.44.c bluetooth_init_cc2560A_2.14.c bluetooth_init_cc2564_2.14.bts bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c bluetooth_init_cc2560B_1.2_BT_Spec_4.1.c bluetooth_init_cc2564B_1.2_BT_Spec_4.1.c TIInit_11.8.32.c TIInit_12.10.28.c TIInit_12.8.32.c
|
||||
all-scripts: \
|
||||
bluetooth_init_cc2560_2.44.c \
|
||||
bluetooth_init_cc2560A_2.14.c \
|
||||
bluetooth_init_cc2564_2.14.bts \
|
||||
bluetooth_init_cc2560B_1.4_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2560B_1.5_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2564B_1.5_BT_Spec_4.1.c \
|
||||
bluetooth_init_cc2560C_1.0.c \
|
||||
bluetooth_init_cc2564C_1.0.c \
|
||||
TIInit_11.8.32.c \
|
||||
TIInit_12.10.28.c \
|
||||
TIInit_12.8.32.c \
|
||||
|
||||
clean-scripts:
|
||||
rm -fr CC256*.zip bluetooth_init_cc256*.bts bluetooth_init_cc256*.c TIInit_*.bts TIInit_*.c BLE_init_cc256*.bts BLE_init_cc256*.c
|
||||
rm -fr cc256x*.zip CC256*.zip bluetooth_init_cc256*.c TIInit*.c *.bts BLE_init_cc256*.c
|
||||
|
||||
|
||||
|
@ -88,10 +88,60 @@ static int16_t init_power_in_dB = 13; // 13 dBm
|
||||
// support for SCO over HCI
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
static int init_send_route_sco_over_hci = 0;
|
||||
// Follow recommendation from https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/t/397004
|
||||
// route SCO over HCI (connection type=1, tx buffer size = 120, tx buffer max latency= 720, accept packets with CRC Error
|
||||
static const uint8_t hci_route_sco_over_hci[] = {
|
||||
#if 1
|
||||
// Follow recommendation from https://e2e.ti.com/support/wireless_connectivity/bluetooth_cc256x/f/660/t/397004
|
||||
// route SCO over HCI (connection type=1, tx buffer size = 120, tx buffer max latency= 720, accept packets with CRC Error
|
||||
0x10, 0xfe, 0x05, 0x01, 0x78, 0xd0, 0x02, 0x01,
|
||||
#else
|
||||
// Configure SCO via I2S interface - 256 kbps
|
||||
// Send_HCI_VS_Write_CODEC_Config 0xFD06,
|
||||
0x06, 0xfd,
|
||||
// len
|
||||
34,
|
||||
//3072, - clock rate 3072000 hz
|
||||
0x00, 0x01,
|
||||
// 0x00 - clock direction: output = master
|
||||
0x00,
|
||||
// 8000, framesync frequency in hz
|
||||
0x40, 0x1f, 0x00, 0x00,
|
||||
// 0x0001, framesync duty cycle
|
||||
0x01, 0x00,
|
||||
// 1, framesync edge
|
||||
1,
|
||||
// 0x00, framesync polarity
|
||||
0x00,
|
||||
// 0x00, RESERVED
|
||||
0x00,
|
||||
// 16, channel 1 out size
|
||||
8, 0,
|
||||
// 0x0001, channel 1 out offset
|
||||
0x01, 0x00,
|
||||
// 1, channel 1 out edge
|
||||
1,
|
||||
// 16, channel 1 in size
|
||||
8, 0,
|
||||
// 0x0001, channel 1 in offset
|
||||
0x01, 0x00,
|
||||
// 0, channel 1 in edge
|
||||
0,
|
||||
// 0x00, RESERVED
|
||||
0x00,
|
||||
// 16, channel 2 out size
|
||||
8, 0,
|
||||
// 17, channel 2 out offset
|
||||
9, 0,
|
||||
// 0x01, channel 2 out edge
|
||||
0x01,
|
||||
// 16, channel 2 in size
|
||||
8, 0,
|
||||
// 17, channel 2 in offset
|
||||
9, 0,
|
||||
// 0x00, channel 2 in edge
|
||||
0x00,
|
||||
// 0x0001, RESERVED
|
||||
0x00
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -50,9 +50,21 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#include "btstack_chipset.h"
|
||||
|
||||
/**
|
||||
* Configure output power before HCI POWER_ON
|
||||
*/
|
||||
void btstack_chipset_cc256x_set_power(int16_t power_in_dB);
|
||||
|
||||
/**
|
||||
* Get chipset instance for CC256x series
|
||||
*/
|
||||
const btstack_chipset_t * btstack_chipset_cc256x_instance(void);
|
||||
|
||||
/**
|
||||
* Get LMP Subversion of compile-time init script
|
||||
*/
|
||||
uint16_t btstack_chipset_cc256x_lmp_subversion(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -9,16 +9,19 @@ import re
|
||||
import sys
|
||||
import os
|
||||
|
||||
print('''
|
||||
CC256x init script conversion tool for use with BTstack, v0.1
|
||||
usage = '''
|
||||
CC256x init script conversion tool for use with BTstack, v0.2
|
||||
Copyright 2012-2014 BlueKitchen GmbH
|
||||
''')
|
||||
|
||||
usage = '''This script prepares init scripts for TI's
|
||||
CC256x chipsets for use with BTstack .
|
||||
Usage:
|
||||
$ ./convert_bts_init_scripts.py main.bts [ble-add-on.bts] output.c
|
||||
|
||||
Please download the Service Pack for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
Then, unzip it and copy the *.bts file into this folder and start the script again.
|
||||
Please specify the main .bts script and optionally the BLE Add-on to generate the init script .c file.
|
||||
|
||||
The Makefile include chipset/cc256x/Makefile.inc automates the process of downloading and converting .bts files.
|
||||
|
||||
If this is not an option, you can download the Service Packs for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads
|
||||
Then, unzip it and copy the *.bts file into this folder before start the script again.
|
||||
'''
|
||||
|
||||
fartext = '''
|
||||
@ -30,6 +33,14 @@ __attribute__((__progmem__))
|
||||
#endif
|
||||
'''
|
||||
|
||||
get_lmp_subversion = '''
|
||||
const uint16_t {prefix}_init_script_lmp_subversion = {lmp_subversion};
|
||||
|
||||
uint16_t btstack_chipset_cc256x_lmp_subversion(void){{
|
||||
return {prefix}_init_script_lmp_subversion;
|
||||
}}
|
||||
'''
|
||||
|
||||
data_indent = ' '
|
||||
|
||||
def read_little_endian_16(f):
|
||||
@ -96,15 +107,15 @@ def append_calibration_sequence(additions, str_list, data_indent):
|
||||
str_list.append("0x01, 0x80, 0xfd, 0x06, 0x3c, 0xf0, 0x5f, 0x00, 0x00, 0x00,\n\n")
|
||||
return 20
|
||||
|
||||
def convert_bts(main_bts_file, bts_add_on):
|
||||
|
||||
def convert_bts(output_file, main_bts_file, bts_add_on, aka, lmp_subversion):
|
||||
array_name = 'cc256x'
|
||||
c_file = main_bts_file.replace('bts', 'c')
|
||||
|
||||
input_files = [ main_bts_file ]
|
||||
if bts_add_on != "":
|
||||
input_files.append(bts_add_on)
|
||||
|
||||
with open(c_file, 'w') as fout:
|
||||
with open(output_file, 'w') as fout:
|
||||
|
||||
# assert script contains templates for configuration by BTstack
|
||||
have_eHCILL = False
|
||||
@ -113,7 +124,7 @@ def convert_bts(main_bts_file, bts_add_on):
|
||||
have_power_vector_edr3 = False;
|
||||
have_class2_single_power = False;
|
||||
|
||||
print("Creating {0}".format(c_file))
|
||||
print("Creating {0}".format(output_file))
|
||||
|
||||
part_size = 0
|
||||
|
||||
@ -223,18 +234,24 @@ 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( '\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 +283,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')
|
||||
|
||||
|
||||
|
||||
|
@ -160,15 +160,19 @@ def createIndex(btstackfolder, apis, githubfolder):
|
||||
functions[ref_function.group(1)] = codeReference(ref_function.group(1), githubfolder, api_tuple[0], linenr)
|
||||
continue
|
||||
|
||||
function = re.match('.*?\s+\*?\s*(.*?)\(.*\(*.*;\n', line)
|
||||
function = re.match('(.*?)\(.*\(*.*;\n', line)
|
||||
if function:
|
||||
functions[function.group(1)] = codeReference(function.group(1), githubfolder, api_tuple[0], linenr)
|
||||
parts = function.group(1).split(" ");
|
||||
name = parts[len(parts)-1]
|
||||
functions[name] = codeReference( name, githubfolder, api_tuple[0], linenr)
|
||||
continue
|
||||
|
||||
function = re.match('.*?\s+\*?\s*(.*?)\(.*\(*.*', line)
|
||||
function = re.match('.(.*?)\(.*\(*.*', line)
|
||||
if function:
|
||||
parts = function.group(1).split(" ");
|
||||
name = parts[len(parts)-1]
|
||||
multiline_function_def = 1
|
||||
functions[function.group(1)] = codeReference(function.group(1), githubfolder, api_tuple[0], linenr)
|
||||
functions[name] = codeReference(name, githubfolder, api_tuple[0], linenr)
|
||||
|
||||
|
||||
def main(argv):
|
||||
@ -207,6 +211,11 @@ def main(argv):
|
||||
writeAPI(apifile, btstackfolder, apis, mk_codeidentation)
|
||||
createIndex(btstackfolder, apis, githubfolder)
|
||||
|
||||
for function in functions:
|
||||
parts = function.split(' ')
|
||||
if (len(parts) > 1):
|
||||
print (parts)
|
||||
|
||||
references = functions.copy()
|
||||
references.update(typedefs)
|
||||
|
||||
|
@ -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};
|
||||
@ -729,6 +723,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
|
||||
|
@ -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;
|
||||
@ -343,6 +346,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 +463,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 +499,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 +533,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 +581,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
|
||||
}
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ static uint8_t sco_ring_buffer[SCO_RING_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];
|
||||
#endif
|
||||
|
||||
// outgoing buffer for HCI Command packets
|
||||
@ -235,8 +236,8 @@ 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;
|
||||
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) {
|
||||
int c;
|
||||
for (c=0;c<ASYNC_BUFFERS;c++){
|
||||
if (transfer == event_in_transfer[c]){
|
||||
libusb_free_transfer(transfer);
|
||||
@ -257,10 +258,27 @@ 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;
|
||||
libusb_free_transfer(transfer);
|
||||
sco_ring_transfers[c] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
for (c=0;c<SCO_RING_BUFFER_COUNT;c++){
|
||||
if (transfer == sco_ring_transfers[c]){
|
||||
sco_ring_transfers_in_flight[c] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int r;
|
||||
// log_info("begin async_callback endpoint %x, status %x, actual length %u", transfer->endpoint, transfer->status, transfer->actual_length );
|
||||
|
||||
@ -317,6 +335,7 @@ static int usb_send_sco_packet(uint8_t *packet, int size){
|
||||
sco_ring_write = 0;
|
||||
}
|
||||
sco_ring_transfers_active++;
|
||||
sco_ring_transfers_in_flight[tranfer_index] = 1;
|
||||
|
||||
// log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_ring_transfers_active);
|
||||
|
||||
@ -407,11 +426,19 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){
|
||||
}
|
||||
resubmit = 1;
|
||||
} else if (transfer->endpoint == sco_out_addr){
|
||||
log_info("sco out done, {{ %u/%u (%x)}, { %u/%u (%x)}, { %u/%u (%x)}}",
|
||||
transfer->iso_packet_desc[0].actual_length, transfer->iso_packet_desc[0].length, transfer->iso_packet_desc[0].status,
|
||||
transfer->iso_packet_desc[1].actual_length, transfer->iso_packet_desc[1].length, transfer->iso_packet_desc[1].status,
|
||||
transfer->iso_packet_desc[2].actual_length, transfer->iso_packet_desc[2].length, transfer->iso_packet_desc[2].status);
|
||||
int i;
|
||||
for (i = 0; i < transfer->num_iso_packets; i++) {
|
||||
struct libusb_iso_packet_descriptor *pack = &transfer->iso_packet_desc[i];
|
||||
if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
log_error("Error: pack %u status %d\n", i, pack->status);
|
||||
}
|
||||
}
|
||||
// log_info("sco out done, {{ %u/%u (%x)}, { %u/%u (%x)}, { %u/%u (%x)}}",
|
||||
// transfer->iso_packet_desc[0].actual_length, transfer->iso_packet_desc[0].length, transfer->iso_packet_desc[0].status,
|
||||
// transfer->iso_packet_desc[1].actual_length, transfer->iso_packet_desc[1].length, transfer->iso_packet_desc[1].status,
|
||||
// transfer->iso_packet_desc[2].actual_length, transfer->iso_packet_desc[2].length, transfer->iso_packet_desc[2].status);
|
||||
// notify upper layer if there's space for new SCO packets
|
||||
|
||||
if (sco_ring_have_space()) {
|
||||
uint8_t event[] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0};
|
||||
packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
|
||||
@ -879,6 +906,7 @@ 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -980,6 +1008,18 @@ static int usb_close(void){
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
for (c = 0 ; c < ISOC_BUFFERS ; 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]);
|
||||
} else {
|
||||
log_info("libusb_free_transfer sco_ring_transfers[%d]", c);
|
||||
libusb_free_transfer(sco_ring_transfers[c]);
|
||||
sco_ring_transfers[c] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
|
||||
@ -1008,6 +1048,15 @@ static int usb_close(void){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!completed) continue;
|
||||
|
||||
for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){
|
||||
if (sco_ring_transfers[c]){
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1016,6 +1065,7 @@ static int usb_close(void){
|
||||
#ifdef ENABLE_SCO_OVER_HCI
|
||||
libusb_release_interface(handle, 1);
|
||||
#endif
|
||||
log_info("Libusb shutdown complete");
|
||||
|
||||
case LIB_USB_DEVICE_OPENDED:
|
||||
libusb_close(handle);
|
||||
|
@ -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
|
||||
|
@ -96,9 +96,32 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
// assert manufacturer is TI
|
||||
if (manufacturer != COMPANY_ID_TEXAS_INSTRUMENTS_INC){
|
||||
printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
|
||||
break;
|
||||
}
|
||||
// assert correct init script is used based on expected lmp_subversion
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
|
||||
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_setup(void){
|
||||
|
@ -97,7 +97,8 @@ BLE_OBJ = $(BLE:.c=.o)
|
||||
# create firmware image from common objects and example source file
|
||||
|
||||
all: led_counter.hex spp_counter.hex gap_inquiry.hex spp_flowcontrol.hex \
|
||||
sdp_rfcomm_query.hex sdp_general_query.hex ble_server.hex
|
||||
sdp_rfcomm_query.hex sdp_general_query.hex
|
||||
# ble_server.hex
|
||||
|
||||
# fetch and convert init scripts
|
||||
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
|
@ -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){
|
||||
|
@ -1,46 +0,0 @@
|
||||
diff --git a/samples/bluetooth/hci_uart/src/main.c b/samples/bluetooth/hci_uart/src/main.c
|
||||
index b103f05..80a82d3 100644
|
||||
--- a/samples/bluetooth/hci_uart/src/main.c
|
||||
+++ b/samples/bluetooth/hci_uart/src/main.c
|
||||
@@ -36,6 +36,9 @@
|
||||
#include <bluetooth/buf.h>
|
||||
#include <bluetooth/hci_raw.h>
|
||||
|
||||
+#include "ll.h"
|
||||
+#include "nrf.h"
|
||||
+
|
||||
static struct device *hci_uart_dev;
|
||||
|
||||
#define STACK_SIZE 1024
|
||||
@@ -301,6 +304,18 @@ static int hci_uart_init(struct device *unused)
|
||||
DEVICE_INIT(hci_uart, "hci_uart", &hci_uart_init, NULL, NULL,
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
|
||||
+void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
|
||||
+ buffer[pos++] = value;
|
||||
+ buffer[pos++] = value >> 8;
|
||||
+}
|
||||
+
|
||||
+void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
|
||||
+ buffer[pos++] = value;
|
||||
+ buffer[pos++] = value >> 8;
|
||||
+ buffer[pos++] = value >> 16;
|
||||
+ buffer[pos++] = value >> 24;
|
||||
+}
|
||||
+
|
||||
void main(void)
|
||||
{
|
||||
/* incoming events and data from the controller */
|
||||
@@ -320,6 +335,12 @@ void main(void)
|
||||
(nano_fiber_entry_t)tx_fiber, 0, 0, 7, 0);
|
||||
|
||||
bt_enable_raw(&rx_queue);
|
||||
+
|
||||
+ // make Random Static Address available via HCI Read BD ADDR as fake public address
|
||||
+ uint8_t addr[6];
|
||||
+ little_endian_store_16(addr, 4, NRF_FICR->DEVICEADDR[1] | 0xc000);
|
||||
+ little_endian_store_32(addr, 0, NRF_FICR->DEVICEADDR[0]);
|
||||
+ ll_address_set(0, addr);
|
||||
|
||||
while (1) {
|
||||
struct net_buf *buf;
|
@ -2,23 +2,28 @@
|
||||
|
||||
ZEPHYR_BASE=../../..
|
||||
|
||||
echo "Adding BTstack sources as subsys/btstack"
|
||||
echo "Integrating BTstack into Zephyr"
|
||||
|
||||
if grep -q -F "NRF_FICR->DEVICEADDR" ${ZEPHYR_BASE}/samples/bluetooth/hci_uart/src/main.c; then
|
||||
echo "HCI Firmware patch already installed"
|
||||
else
|
||||
# assert files don't exist since patch would get irritated
|
||||
echo "Applying HCI Firmware patch"
|
||||
rm -f ${ZEPHYR_BASE}/samples/bluetooth/hci_uart/flash*
|
||||
cat hci_firmware.patch | patch -d ${ZEPHYR_BASE} -p1
|
||||
fi
|
||||
|
||||
echo "Adding subsys/btstack"
|
||||
|
||||
# add btstack folder to subsys/Makefile
|
||||
MAKEFILE_ADD_ON='obj-$(CONFIG_BTSTACK) += btstack/'
|
||||
NET_MAKEFILE=${ZEPHYR_BASE}/subsys/Makefile
|
||||
grep -q -F btstack ${NET_MAKEFILE} || echo ${MAKEFILE_ADD_ON} >> ${NET_MAKEFILE}
|
||||
|
||||
# add BTstack KConfig to net/Kconfig
|
||||
# add BTstack KConfig to subsys/Kconfig
|
||||
SUBSYS_KCONFIG=${ZEPHYR_BASE}/subsys/Kconfig
|
||||
grep -q -F btstack ${SUBSYS_KCONFIG} || echo 'source "subsys/btstack/Kconfig"' >> ${SUBSYS_KCONFIG}
|
||||
|
||||
# set Nordic Semiconductor as manufacturer
|
||||
CTRL_H=${ZEPHYR_BASE}/subsys/bluetooth/controller/ll/ctrl.h
|
||||
sed -i "s|#define RADIO_BLE_COMPANY_ID.*0xFFFF.|#define RADIO_BLE_COMPANY_ID (0x0059) // Nordic Semiconductor ASA|g" ${CTRL_H}
|
||||
|
||||
|
||||
# create subsys/btstack
|
||||
mkdir -p ${ZEPHYR_BASE}/subsys/btstack
|
||||
|
||||
@ -52,17 +57,3 @@ rsync -a Makefile.bluedroid-decoder ${ZEPHYR_BASE}/subsys/btstack/bluedroid/deco
|
||||
|
||||
# create samples/btstack
|
||||
./create_examples.py
|
||||
|
||||
|
||||
## Additonal changes for HCI Controller firmware in samples/bluetooth/hci-uart
|
||||
HCI_UART=${ZEPHYR_BASE}/samples/bluetooth/hci_uart
|
||||
|
||||
# add flash scripts to hci-uart
|
||||
rsync -a flash_nrf51_pca10028.sh ${HCI_UART}/flash_nrf51_pca10028.sh
|
||||
rsync -a flash_nrf52_pca10040.sh ${HCI_UART}/flash_nrf52_pca10040.sh
|
||||
|
||||
# use 115200 baud
|
||||
sed -i 's|CONFIG_UART_NRF5_BAUD_RATE=1000000|CONFIG_UART_NRF5_BAUD_RATE=115200|g' ${HCI_UART}/nrf5.conf
|
||||
|
||||
# provide static random address to host via hci read bd addr
|
||||
grep -q -F ll_address_set ${HCI_UART}/src/main.c || cat hci_uart.patch | patch -d ${ZEPHYR_BASE} -p1
|
||||
|
@ -9,7 +9,7 @@ CONFIG_SERIAL=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
|
||||
CONFIG_BLUETOOTH=y
|
||||
CONFIG_BLUETOOTH_STACK_HCI_RAW=y
|
||||
CONFIG_BLUETOOTH_HCI_RAW=y
|
||||
CONFIG_BLUETOOTH_MAX_CONN=16
|
||||
CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS=4
|
||||
CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS=4
|
||||
|
@ -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,
|
||||
@ -89,6 +90,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
|
||||
if (hci_event_command_complete_get_return_parameters(packet)[0]) break;
|
||||
// terminate, name 248 chars
|
||||
packet[6+248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
@ -96,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;
|
||||
@ -134,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:
|
||||
@ -154,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
|
||||
@ -161,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");
|
||||
@ -197,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();
|
||||
@ -210,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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -45,6 +45,8 @@
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
typedef struct btstack_linked_item {
|
||||
struct btstack_linked_item *next; // <-- next element in list, or NULL
|
||||
@ -89,8 +91,11 @@ int btstack_linked_list_iterator_has_next(btstack_linked_list_iterat
|
||||
btstack_linked_item_t * btstack_linked_list_iterator_next(btstack_linked_list_iterator_t * it);
|
||||
void btstack_linked_list_iterator_remove(btstack_linked_list_iterator_t * it);
|
||||
|
||||
/* API_END */
|
||||
|
||||
void test_linked_list(void);
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -65,12 +65,14 @@ extern "C" {
|
||||
|
||||
// will be moved to daemon/btstack_device_name_db.h
|
||||
|
||||
|
||||
/**
|
||||
* @brief The device name type
|
||||
*/
|
||||
#define DEVICE_NAME_LEN 248
|
||||
typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief Minimum function for uint32_t
|
||||
@ -223,6 +225,7 @@ int uuid_has_bluetooth_prefix(uint8_t * uuid128);
|
||||
*/
|
||||
uint32_t btstack_atoi(const char *str);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
41
src/hci.c
41
src/hci.c
@ -1445,9 +1445,8 @@ static void event_handler(uint8_t *packet, int size){
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
// get num cmd packets
|
||||
// log_info("HCI_EVENT_COMMAND_COMPLETE cmds old %u - new %u", hci_stack->num_cmd_packets, packet[2]);
|
||||
hci_stack->num_cmd_packets = packet[2];
|
||||
// get num cmd packets - limit to 1 to reduce complexity
|
||||
hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
|
||||
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
|
||||
// terminate, name 248 chars
|
||||
@ -1524,10 +1523,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] =
|
||||
@ -1545,9 +1540,8 @@ static void event_handler(uint8_t *packet, int size){
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_STATUS:
|
||||
// get num cmd packets
|
||||
// log_info("HCI_EVENT_COMMAND_STATUS cmds - old %u - new %u", hci_stack->num_cmd_packets, packet[3]);
|
||||
hci_stack->num_cmd_packets = packet[3];
|
||||
// get num cmd packets - limit to 1 to reduce complexity
|
||||
hci_stack->num_cmd_packets = packet[3] ? 1 : 0;
|
||||
break;
|
||||
|
||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:{
|
||||
@ -3069,11 +3063,8 @@ void gap_ssp_set_auto_accept(int auto_accept){
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
||||
*/
|
||||
int hci_send_cmd(const hci_cmd_t *cmd, ...){
|
||||
|
||||
// va_list part of hci_send_cmd
|
||||
int hci_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
|
||||
if (!hci_can_send_command_packet_now()){
|
||||
log_error("hci_send_cmd called but cannot send packet now");
|
||||
return 0;
|
||||
@ -3085,13 +3076,19 @@ int hci_send_cmd(const hci_cmd_t *cmd, ...){
|
||||
|
||||
hci_reserve_packet_buffer();
|
||||
uint8_t * packet = hci_stack->hci_packet_buffer;
|
||||
uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
|
||||
return hci_send_cmd_packet(packet, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
||||
*/
|
||||
int hci_send_cmd(const hci_cmd_t *cmd, ...){
|
||||
va_list argptr;
|
||||
va_start(argptr, cmd);
|
||||
uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
|
||||
int res = hci_send_cmd_va_arg(cmd, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return hci_send_cmd_packet(packet, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Create various non-HCI events.
|
||||
@ -3773,14 +3770,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);
|
||||
|
13
src/hci.h
13
src/hci.h
@ -620,9 +620,6 @@ typedef struct {
|
||||
/* callbacks for events */
|
||||
btstack_linked_list_t event_handlers;
|
||||
|
||||
// local version information callback
|
||||
void (*local_version_information_callback)(uint8_t * local_version_information);
|
||||
|
||||
// hardware error callback
|
||||
void (*hardware_error_callback)(uint8_t error);
|
||||
|
||||
@ -774,12 +771,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
|
||||
*/
|
||||
@ -900,6 +891,10 @@ void hci_release_packet_buffer(void);
|
||||
/* API_END */
|
||||
|
||||
|
||||
/**
|
||||
* va_list version of hci_send_cmd
|
||||
*/
|
||||
int hci_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argtr);
|
||||
|
||||
/**
|
||||
* Get connection iterator. Only used by l2cap.c and sm.c
|
||||
|
@ -62,7 +62,6 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h> // for timestamps
|
||||
#include <sys/stat.h> // for mode flags
|
||||
#include <stdarg.h> // for va_list
|
||||
#endif
|
||||
|
||||
// BLUEZ hcidump - struct not used directly, but left here as documentation
|
||||
@ -265,19 +264,24 @@ static int hci_dump_log_level_active(int log_level){
|
||||
return log_level_enabled[log_level];
|
||||
}
|
||||
|
||||
void hci_dump_log_va_arg(int log_level, const char * format, va_list argptr){
|
||||
if (hci_dump_log_level_active(log_level)) {
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
int len = vsnprintf(log_message_buffer, sizeof(log_message_buffer), format, argptr);
|
||||
hci_dump_packet(LOG_MESSAGE_PACKET, 0, (uint8_t*) log_message_buffer, len);
|
||||
#else
|
||||
printf_timestamp();
|
||||
printf("LOG -- ");
|
||||
vprintf(format, argptr);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void hci_dump_log(int log_level, const char * format, ...){
|
||||
if (!hci_dump_log_level_active(log_level)) return;
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
int len = vsnprintf(log_message_buffer, sizeof(log_message_buffer), format, argptr);
|
||||
hci_dump_packet(LOG_MESSAGE_PACKET, 0, (uint8_t*) log_message_buffer, len);
|
||||
#else
|
||||
printf_timestamp();
|
||||
printf("LOG -- ");
|
||||
vprintf(format, argptr);
|
||||
printf("\n");
|
||||
#endif
|
||||
hci_dump_log_va_arg(log_level, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#define __HCI_DUMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h> // for va_list
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
@ -104,6 +105,8 @@ void hci_dump_close(void);
|
||||
|
||||
/* API_END */
|
||||
|
||||
void hci_dump_log_va_arg(int log_level, const char * format, va_list argtr);
|
||||
|
||||
#ifdef __AVR__
|
||||
void hci_dump_log_P(int log_level, PGM_P format, ...);
|
||||
#endif
|
||||
|
18
src/l2cap.c
18
src/l2cap.c
@ -219,11 +219,9 @@ void l2cap_release_packet_buffer(void){
|
||||
hci_release_packet_buffer();
|
||||
}
|
||||
|
||||
static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle, uint16_t remote_cid, uint16_t len){
|
||||
int pb = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02;
|
||||
|
||||
static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle, uint8_t packet_boundary, uint16_t remote_cid, uint16_t len){
|
||||
// 0 - Connection handle : PB=pb : BC=00
|
||||
little_endian_store_16(acl_buffer, 0, con_handle | (pb << 12) | (0 << 14));
|
||||
little_endian_store_16(acl_buffer, 0, con_handle | (packet_boundary << 12) | (0 << 14));
|
||||
// 2 - ACL length
|
||||
little_endian_store_16(acl_buffer, 2, len + 4);
|
||||
// 4 - L2CAP packet length
|
||||
@ -232,6 +230,7 @@ static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle
|
||||
little_endian_store_16(acl_buffer, 6, remote_cid);
|
||||
}
|
||||
|
||||
// assumption - only on LE connections
|
||||
int l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len){
|
||||
|
||||
if (!hci_is_packet_buffer_reserved()){
|
||||
@ -247,11 +246,12 @@ int l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid
|
||||
log_debug("l2cap_send_prepared_connectionless handle %u, cid 0x%02x", con_handle, cid);
|
||||
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
l2cap_setup_header(acl_buffer, con_handle, cid, len);
|
||||
l2cap_setup_header(acl_buffer, con_handle, 0, cid, len);
|
||||
// send
|
||||
return hci_send_acl_packet_buffer(len+8);
|
||||
}
|
||||
|
||||
// assumption - only on LE connections
|
||||
int l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(con_handle)){
|
||||
@ -449,6 +449,7 @@ static int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_
|
||||
return hci_send_acl_packet_buffer(len);
|
||||
}
|
||||
|
||||
// assumption - only on Classic connections
|
||||
int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
|
||||
|
||||
if (!hci_is_packet_buffer_reserved()){
|
||||
@ -469,12 +470,15 @@ int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
|
||||
|
||||
log_debug("l2cap_send_prepared cid 0x%02x, handle %u, 1 credit used", local_cid, channel->con_handle);
|
||||
|
||||
// set non-flushable packet boundary flag if supported on Controller
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
l2cap_setup_header(acl_buffer, channel->con_handle, channel->remote_cid, len);
|
||||
uint8_t packet_boundary_flag = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02;
|
||||
l2cap_setup_header(acl_buffer, channel->con_handle, packet_boundary_flag, channel->remote_cid, len);
|
||||
// send
|
||||
return hci_send_acl_packet_buffer(len+8);
|
||||
}
|
||||
|
||||
// assumption - only on Classic connections
|
||||
int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
||||
|
||||
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
@ -812,7 +816,7 @@ static void l2cap_run(void){
|
||||
memcpy(&l2cap_payload[pos], &channel->send_sdu_buffer[channel->send_sdu_pos-2], payload_size); // -2 for virtual SDU len
|
||||
pos += payload_size;
|
||||
channel->send_sdu_pos += payload_size;
|
||||
l2cap_setup_header(acl_buffer, channel->con_handle, channel->remote_cid, pos);
|
||||
l2cap_setup_header(acl_buffer, channel->con_handle, 0, channel->remote_cid, pos);
|
||||
// done
|
||||
|
||||
channel->credits_outgoing--;
|
||||
|
421
tool/btstack_rtos_generator.py
Executable file
421
tool/btstack_rtos_generator.py
Executable file
@ -0,0 +1,421 @@
|
||||
#!/usr/bin/env python
|
||||
import os, sys, getopt, re, pickle
|
||||
|
||||
copyright = """/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
"""
|
||||
|
||||
single_hfile_header_begin = """
|
||||
|
||||
/*
|
||||
* btstack_rtos.h
|
||||
*
|
||||
* @brief BTstack Wrapper for use with Real-Time OS
|
||||
* Wraps each public BTstack function into a thread-safe version
|
||||
*
|
||||
* @note Don't edit - generated by tool/btstack_rtos_generator.py
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTSTACK_RTOS_H
|
||||
#define __BTSTACK_RTOS_H
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "btstack_config.h"
|
||||
|
||||
#ifndef BTSTACK_RTOS_ENTER
|
||||
#error Please define BTSTACK_RTOS_ENTER that locks a recursive mutex when using the RTOS wrapper btstack_rtos.h
|
||||
#endif
|
||||
|
||||
#ifndef BTSTACK_RTOS_EXIT
|
||||
#error Please define BTSTACK_RTOS_EXIT that releases a recursive mutex when using the RTOS wrapper btstack_rtos.h
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
|
||||
"""
|
||||
|
||||
single_hfile_api_header = """
|
||||
#include "API_NAME"
|
||||
"""
|
||||
|
||||
single_hfile_header_end = """
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BTSTACK_RTOS_H
|
||||
"""
|
||||
|
||||
multiple_header_begin = """
|
||||
|
||||
/*
|
||||
* FILENAME
|
||||
*
|
||||
* @brief BTstack Wrapper for use with Real-Time OS
|
||||
* Wraps each public BTstack function into a thread-safe version
|
||||
*
|
||||
* @note Don't edit - generated by tool/btstack_rtos_generator.py
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GUARD
|
||||
#define GUARD
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "btstack_config.h"
|
||||
#include "HEADER"
|
||||
|
||||
#ifndef BTSTACK_RTOS_ENTER
|
||||
#error Please define BTSTACK_RTOS_ENTER that locks a recursive mutex when using the RTOS wrapper btstack_rtos.h
|
||||
#endif
|
||||
|
||||
#ifndef BTSTACK_RTOS_EXIT
|
||||
#error Please define BTSTACK_RTOS_EXIT that releases a recursive mutex when using the RTOS wrapper btstack_rtos.h
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
|
||||
"""
|
||||
|
||||
multiple_header_end = """
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // GUARD
|
||||
"""
|
||||
|
||||
class State:
|
||||
SearchStartAPI = 0
|
||||
SearchEndAPI = 1
|
||||
DoneAPI = 2
|
||||
|
||||
|
||||
num_functions = 0
|
||||
|
||||
# [file_name, api_title, api_label]
|
||||
apis = [
|
||||
["src/ble/ancs_client.h", "BLE ANCS Client", "ancsClient", True],
|
||||
["src/ble/att_db_util.h", "BLE ATT Database", "attDb", True],
|
||||
["src/ble/att_server.h", "BLE ATT Server", "attServer", True],
|
||||
["src/ble/gatt_client.h", "BLE GATT Client", "gattClient", True],
|
||||
["src/ble/le_device_db.h", "BLE Device Database", "leDeviceDb", True],
|
||||
["src/ble/sm.h", "BLE Security Manager", "sm", True],
|
||||
|
||||
["src/classic/bnep.h", "BNEP", "bnep", True],
|
||||
["src/classic/btstack_link_key_db.h","Link Key DB","lkDb", True],
|
||||
["src/classic/hsp_hs.h","HSP Headset","hspHS", True],
|
||||
["src/classic/hsp_ag.h","HSP Audio Gateway","hspAG", True],
|
||||
["src/classic/hfp_hf.h","HFP Hands-Free","hfpHF", True],
|
||||
["src/classic/hfp_ag.h","HFP Audio Gateway","hfpAG", True],
|
||||
["src/classic/pan.h", "PAN", "pan", True],
|
||||
["src/classic/rfcomm.h", "RFCOMM", "rfcomm", True],
|
||||
["src/classic/sdp_client.h", "SDP Client", "sdpClient", True],
|
||||
["src/classic/sdp_client_rfcomm.h", "SDP RFCOMM Query", "sdpQueries", True],
|
||||
["src/classic/sdp_server.h", "SDP Server", "sdpSrv", True],
|
||||
["src/classic/sdp_util.h","SDP Utils", "sdpUtil", True],
|
||||
|
||||
["src/ad_parser.h", "BLE Advertisements Parser", "advParser", False],
|
||||
# ["src/btstack_chipset.h","BTstack Chipset","btMemory", True],
|
||||
# ["src/btstack_control.h","BTstack Hardware Control","btControl", True],
|
||||
["src/btstack_event.h","HCI Event Getter","btEvent", False],
|
||||
# ["src/btstack_memory.h","BTstack Memory Management","btMemory", True],
|
||||
["src/btstack_linked_list.h","BTstack Linked List","btList", False],
|
||||
["src/btstack_run_loop.h", "Run Loop", "runLoop", True],
|
||||
["src/btstack_util.h", "Common Utils", "btUtil", False],
|
||||
["src/gap.h", "GAP", "gap", True],
|
||||
["src/hci.h", "HCI", "hci", True],
|
||||
["src/hci_dump.h","HCI Logging","hciTrace", True],
|
||||
# ["src/hci_transport.h","HCI Transport","hciTransport", True],
|
||||
["src/l2cap.h", "L2CAP", "l2cap", True],
|
||||
]
|
||||
|
||||
def split_arguments(args_string):
|
||||
args = []
|
||||
brace_level = 0
|
||||
arg = ''
|
||||
for c in args_string:
|
||||
if c == '(':
|
||||
brace_level += 1
|
||||
if c == ')':
|
||||
brace_level -= 1
|
||||
if c == ',' and brace_level == 0:
|
||||
args.append(arg)
|
||||
arg = ''
|
||||
continue
|
||||
arg = arg + c
|
||||
if len(arg):
|
||||
args.append(arg)
|
||||
return args
|
||||
|
||||
def argument_name(parameter):
|
||||
function_pointer = re.match('[\w\s\*]*\(\s*\*(\w*)\s*\)\(.*\)', parameter)
|
||||
if function_pointer:
|
||||
return function_pointer.group(1)
|
||||
parts = parameter.split(' ')
|
||||
filtered_parts = [part for part in parts if part not in ['']]
|
||||
arg = filtered_parts[len(filtered_parts)-1].replace('*','').replace('[]','')
|
||||
# le_device_db_encryption_set(index, ediv, rand[8], ltk, key_size, authenticated, authorized);
|
||||
if arg == 'rand[8]':
|
||||
arg = 'rand'
|
||||
return arg
|
||||
|
||||
def create_wrapper(fout, type_and_name, arg_string, need_lock):
|
||||
global num_functions
|
||||
|
||||
parts = type_and_name.split(' ')
|
||||
filtered_parts = [part for part in parts if part not in ['static','inline','']]
|
||||
name = filtered_parts[len(filtered_parts)-1]
|
||||
return_type = ' '.join(filtered_parts[:-1])
|
||||
# handle *function_name
|
||||
if name.startswith('*'):
|
||||
name = name[1:]
|
||||
return_type = return_type + ' *'
|
||||
rtos_name = "rtos_" + name
|
||||
is_void_function = len(filtered_parts) == 2 and filtered_parts[0] == "void"
|
||||
args = split_arguments(arg_string)
|
||||
call = []
|
||||
is_ellipse_function = False
|
||||
if len(args)!= 1 or args[0] != 'void':
|
||||
for arg in args:
|
||||
call_arg = argument_name(arg)
|
||||
if call_arg == '...':
|
||||
is_ellipse_function = True
|
||||
call.append('argptr')
|
||||
name += '_va_arg'
|
||||
else:
|
||||
call.append(argument_name(arg))
|
||||
call_args = ', '.join(call)
|
||||
fout.write('static inline ' + return_type + ' ' + rtos_name + '(' + ", ".join(args) + '){\n')
|
||||
orig_call = name + '(' + call_args + ')'
|
||||
if need_lock:
|
||||
fout.write(' BTSTACK_RTOS_ENTER();\n')
|
||||
if is_ellipse_function:
|
||||
fout.write(' va_list argptr;\n')
|
||||
fout.write(' va_start(argptr, %s);\n' % call[-2])
|
||||
if is_void_function:
|
||||
fout.write(' ' + orig_call+';\n')
|
||||
else:
|
||||
fout.write(' ' + return_type + ' res = ' + orig_call + ';\n')
|
||||
if is_ellipse_function:
|
||||
fout.write(' va_end(argptr);\n')
|
||||
fout.write(' BTSTACK_RTOS_EXIT();\n')
|
||||
if not is_void_function:
|
||||
fout.write(' return res;\n')
|
||||
else:
|
||||
if is_void_function:
|
||||
fout.write(' ' + orig_call+';\n')
|
||||
else:
|
||||
fout.write(' return ' + orig_call + ';\n')
|
||||
fout.write('}\n')
|
||||
fout.write('\n')
|
||||
num_functions += 1
|
||||
|
||||
def write_wrappers_for_file(fout, file, header_name, need_lock):
|
||||
with open(file, 'rb') as fin:
|
||||
typedefFound = 0
|
||||
multiline_function_def = 0
|
||||
multiline = ''
|
||||
multiline_comment = 0
|
||||
inline_function = 0
|
||||
state = State.SearchStartAPI
|
||||
|
||||
for line in fin:
|
||||
if state == State.DoneAPI:
|
||||
continue
|
||||
|
||||
if state == State.SearchStartAPI:
|
||||
parts = re.match('.*API_START.*',line)
|
||||
if parts:
|
||||
state = State.SearchEndAPI
|
||||
continue
|
||||
|
||||
if state == State.SearchEndAPI:
|
||||
parts = re.match('.*API_END.*',line)
|
||||
if parts:
|
||||
state = State.DoneAPI
|
||||
continue
|
||||
|
||||
if inline_function:
|
||||
function_end = re.match('.*}.*', line)
|
||||
if function_end:
|
||||
inline_function = 0
|
||||
continue
|
||||
|
||||
if multiline_function_def:
|
||||
multiline += line
|
||||
function_end = re.match('.*\)', line)
|
||||
if function_end:
|
||||
multiline_function_def = 0
|
||||
function = re.match('([\w\s\*]*)\(([\w\s,\*]*)\).*', multiline)
|
||||
if function:
|
||||
type_and_name = function.group(1)
|
||||
arg_string = function.group(2)
|
||||
create_wrapper(fout, type_and_name, arg_string, need_lock)
|
||||
continue
|
||||
|
||||
if multiline_comment:
|
||||
comment_end = re.match('.*\*/.*', line)
|
||||
if comment_end:
|
||||
multiline_comment = 0
|
||||
fout.write(line)
|
||||
continue
|
||||
|
||||
# search typedef struct end
|
||||
if typedefFound:
|
||||
typedef = re.match('}\s*(.*);\n', line)
|
||||
if typedef:
|
||||
typedefFound = 0
|
||||
continue
|
||||
|
||||
# search comment line
|
||||
comment = re.match(".*/\*.*\*/.*", line)
|
||||
if comment:
|
||||
fout.write(line)
|
||||
continue
|
||||
|
||||
# search start of multi line comment
|
||||
comment = re.match(".*/\*", line)
|
||||
if comment:
|
||||
fout.write(line)
|
||||
multiline_comment = 1
|
||||
continue
|
||||
|
||||
# ignore __attribute__ for hci_dump_log in src/hci_dump.h
|
||||
param = re.match(".*__attribute__", line)
|
||||
if param:
|
||||
continue
|
||||
|
||||
# search typedef struct begin
|
||||
typedef = re.match('.*typedef\s+struct.*', line)
|
||||
if typedef:
|
||||
typedefFound = 1
|
||||
|
||||
# complete function declaration
|
||||
function = re.match('([\w\s\*]*)\((.*)\).*', line)
|
||||
if function:
|
||||
if "return" in line:
|
||||
continue
|
||||
type_and_name = function.group(1)
|
||||
arg_string = function.group(2)
|
||||
create_wrapper(fout, type_and_name, arg_string, need_lock)
|
||||
inline_function = 'inline' in line;
|
||||
continue
|
||||
|
||||
# multi-line function declaration
|
||||
function = re.match('([\w\s\*]*)\((.*).*', line)
|
||||
if function:
|
||||
multiline = line
|
||||
multiline_function_def = 1
|
||||
continue
|
||||
|
||||
# fout.write(single_hfile_header_begin)
|
||||
|
||||
|
||||
def create_wrapper_file(btstack_root, apis, wrapper_file):
|
||||
with open(wrapper_file, 'w') as fout:
|
||||
fout.write(copyright)
|
||||
fout.write(single_hfile_header_begin)
|
||||
|
||||
for api_tuple in apis:
|
||||
api_filename = btstack_root + "/" + api_tuple[0]
|
||||
need_lock = api_tuple[3]
|
||||
header_file = api_tuple[0].replace('src/','')
|
||||
fout.write(single_hfile_api_header.replace("API_NAME", header_file))
|
||||
write_wrappers_for_file(fout, api_filename, header_file, need_lock)
|
||||
# fout.write(single_hfile_header_begin)
|
||||
fout.write(single_hfile_header_end)
|
||||
|
||||
def create_wrapper_files(btstack_root, rtos_folder, apis):
|
||||
for api_tuple in apis:
|
||||
api_filename = btstack_root + "/" + api_tuple[0]
|
||||
need_lock = api_tuple[3]
|
||||
header_file = api_tuple[0].replace('src/','')
|
||||
path_parts = header_file.split('/')
|
||||
path_parts[-1] = 'rtos_' + path_parts[-1]
|
||||
rtos_file = '/'.join(path_parts)
|
||||
wrapper_file = rtos_folder + '/' + rtos_file
|
||||
# print('- %s' % wrapper_file)
|
||||
with open(wrapper_file, 'w') as fout:
|
||||
guard = '__' + rtos_file.replace('.','_').upper()
|
||||
fout.write(copyright)
|
||||
fout.write(multiple_header_begin.replace('FILENAME',rtos_file).replace('GUARD',guard).replace('HEADER',header_file))
|
||||
write_wrappers_for_file(fout, api_filename, header_file, need_lock)
|
||||
fout.write(multiple_header_end.replace('GUARD',guard))
|
||||
|
||||
def assert_dir_exists(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
def main(argv):
|
||||
btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..')
|
||||
print ('BTstack folder is: %s' % btstack_root)
|
||||
|
||||
# single file
|
||||
# gen_path = btstack_root + '/src/btstack_rtos.h'
|
||||
# print ('Generating RTOS wrapper %s' % gen_path)
|
||||
# create_wrapper_file(btstack_root, apis, gen_path)
|
||||
|
||||
# individual files in platform/rtos
|
||||
print ('Generating RTOS wrappers...')
|
||||
rtos_folder = btstack_root + '/platform/rtos'
|
||||
assert_dir_exists(rtos_folder)
|
||||
assert_dir_exists(rtos_folder+'/ble')
|
||||
assert_dir_exists(rtos_folder+'/classic')
|
||||
create_wrapper_files(btstack_root, rtos_folder, apis)
|
||||
|
||||
# summary
|
||||
print ('Number wrapped headers: %u' % len(apis))
|
||||
print ('Number wrapped functions: %u' % num_functions)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
Loading…
x
Reference in New Issue
Block a user