Merge branch 'develop'

This commit is contained in:
Matthias Ringwald 2016-11-19 22:08:47 +01:00
commit 8a15b73a9f
35 changed files with 712 additions and 216 deletions

231
chipset/README.md Normal file
View File

@ -0,0 +1,231 @@
In this chapter, we first explain how Bluetooth chipsets are connected physically and
then provide information about popular Bluetooth chipset and their use with BTstack.
The communication between a Host (a computer or an MCU) and a Host Controller (the actual Bluetoot chipset) follows the Host Controller Interface (HCI), see {@fig:HostChipsetConnection}. HCI defines how commands, events, asynchronous and synchronous data packets are exchanged. Asynchronous packets (ACL) are used for data transfer, while synchronous packets (SCO) are used for Voice with the Headset and the Hands-Free Profiles.
![Host Controller to Host connection](../doc/manual/docs/picts/host_chipset_connection.png){#fig:HostChipsetConnection}
On desktop-class computers incl. laptops, USB is mainly used as HCI transport layer. For USB Bluetooth chipsets, there is little variation: most USB dongles on the market currently contain a Broadcom BCM20702 or a CSR 851x chipset.
On embedded systems, UART connections are used instead, although USB could be used as well.
Most USB Bluetooth dongles on the market conatin either an Broadcom BCM20702
For UART connections, different transport layer variants exist. The most common one is the official "UART Transport", also called H4. It requires hardware flow control via the CTS/RTS lines and assumes no errors on the UART lines. The "Three-Wire UART Transport", also called H5, makes use of the SLIP protocol to transmit a packet and can deal with packet loss and bit-errors by retransmission. Finally, Texas Instruments created the "eHCILL transport" layer based on H4 that allows both sides to enter sleep mode without loosing synchronisation.
Unfortunately, the HCI standard misses a few relevant details:
* For UART based connections, the initial baud rate isn't defined but most Bluetooth chipsets use 115200 baud. For better throughput, a higher baud rate is necessary, but there's no standard HCI command to change it. Instead, each vendor had to come up with their own set of vendor-specific commands. Sometimes, additional steps, e.g. doing a warm reset, are neceesary to activate the baud rate change as well.
* Some Bluetooth chipsets don't have a unique MAC address. On start, the MAC address needs to be set, but there's no standard HCI command to set it.
* SCO data for Voice can either be transmitted via the HCI interface or via an explicit PCM/I2S interface on the chipset. Most chipsets default to the PCM/I2S interface. To use it via USB or for Wide-Band Speech in the Hands-Free Profile, the data needs to be delivered to the host MCU. Newer Bluetooth standards define a HCI command to configure the SCO routing, but it is not implemented in the chipsets we've tested so far. Instead, this is configured in a vendor-specific way as well.
* In addition, most vendors allow to patch or configure their chipsets at run time by sending custom comands to the chipset. Obviously, this is also vendor dependent.
The level of developer documentation and support varies widely between the various Bluetooth chipset providers.
From our experience, only Texas Instruments and EM Microelectronics provide all relevant information directly on their website. Nordic Semiconductor does not officially have Bluetooth chipsets with HCI interface, but their the documentation on their nRF5 series is complete and very informative. TI and Nordic also provide excellent support via their respective web forum.
Broadcom, whose Bluetooth + Wifi division has been acquired by the Cypress Semiconductor Corporation, provides developer documentation only to large customers as far as we know. It's possible to join their Community forum and download the WICED SDK. The WICED SDK is targeted at Wifi + Bluetooth Combo chipsets and contains the necessary chipset patch files.
CSR, which has been acquired by Qualcomm, provides all relevant information on their Support website after signing an NDA.
Chipset | Type | HCI Transport | BD_ADDR (1) | SCO over HCI (2) | LE DLE | Multiple LE Roles (3)| BTstack folder | Comment
-------------------- |-----------| ---------------|--------------|------------------|--------|----------------------|----------------|---------
Broadcom UART | Dual mode | H4, H5 | rarely | No (didn't work) | No | Maybe | 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 |
Dialog DA14581 | LE | H4, SPI | ? | n.a. | No | No | | Waiting for dev kit
EM 9301 | LE | SPI | No | n.a. | No | No | em9301 | Custom HCI SPI implementation
EM 9304 | LE | SPI, H4 | ? | n.a. | Yes | No | | Waiting for dev kit
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
**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,
so at least some Broadcom models support multiple concurrent LE roles.
## Broadcom
Before the Broadcom Wifi+Bluetooth division was taken over by Cypress Semiconductor, it was not possible to buy Broadcom chipset in low quantities. Nevertheless, module manufacturers like Ampak created modules that contained Broadcom BCM chipsets (Bluetooth as well as Bluetooth+Wifi combos) that might already have been pre-tested for FCC and similar certifications.
A popular example is the Ampak AP6212A module that contains an BCM 43438A1 and is used on the Raspberry Pi 3, the RedBear Duo, and the RedBear IoT pHAT for older Rasperry Pi models.
The best source for documentation on vendor specific commands so far has been the source code for blueZ and the Bluedroid Bluetooth stack from Android.
Broadcom USB dongles do not require special configuration, however SCO data is not routed over USB by default.
**Init scripts**: For UART connected chipsets, an init script has to be uploaded after power on. For Bluetooth chipsets that are used in Broadcom Wifi+Bluetooth combos, this file often can be found as a binary file in Linux distributions with the ending *'.hcd'* or as part of the WICED SDK as C source file that contains the init script as a data array for use without a file system.
To find the correct file, Broadcom chipsets return their model number when asked for their local name.
BTstack supports uploading of the init script in two variants: using .hcd files looked up by name in the posix-h4 port and by linking against the init script in the WICED port.
**BD Addr** can be set with a custom command. A fixed addres is provided on some modules, e.g. the AP6212A, but not on others.
**SCO data** can be configured with a custom command found in the bluez sources. We haven't been able to route SCO data over HCI yet.
**Baud rate** can be set with custom command. The baud rate resets during the warm start after uploading the init script. So, the overall scheme is this: start at default baud rate, get local version info, send custom Broadcom baud rate change command, wait for response, set local UART to high baud rate, and then send init script. After sending the last command from the init script, reset the local UART. Finally, send custom baud rate change command, wait for response, and set local UART to high baud rate.
**BTstack integration**: The common code for all Broadcom chipsets is provided by *btstack_chipset_bcm.c*. During the setup, *btstack_chipset_bcm_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function.
SCO Data can not be routed over HCI via USB or UART, so HFP Wide-Band Speech is not supported currently. HSP and HFP Narrow Band Speech is supported via I2C/PCM pins.
## CSR
Similar to Broadcom, the best source for documentation is the source code for blueZ.
CSR USB dongles do not require special configuration and SCO data is routed over USB by default.
CSR chipset do not require an actual init script in general, but they allow to configure the chipset via so-called PSKEYs. After setting one or more PSKEYs, a warm reset activates the new setting.
**BD Addr** can be set via PSKEY. A fixed address can be provided if the chipset has some kind of persistent memory to store it. Most USB Bluetooth dongles have a fixed BD ADDR.
**SCO data** can be configured via a set of PSKEYs. We haven't been able to route SCO data over HCI for UART connections yet.
**Baud rate** can be set as part of the initial configuration and gets actived by the warm reset.
**BTstack integration**: The common code for all Broadcom chipsets is provided by *btstack_chipset_csr.c*. During the setup, *btstack_chipset_csr_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function. The baud rate is set during the general configuration.
SCO Data is routed over HCI for USB dongles, but not for UART connections. HSP and HFP Narrow Band Speech is supported via I2C/PCM pins.
## Dialog Semiconductor
Dialog Semiconductor offers the DA14581, an LE-only SoC that can be programmed with an HCI firmware. The HCI firmware can be uploaded on boot into SRAM or stored in the OTP (One-time programmable) memory, or in an external SPI.
We just ordered a Dev Kit and will try to implement the firmware upload to SRAM option. This chipset supports the Bluetooth 4.2. specification but does not seem to implement the Data Length Extension nor supports multiple concurrent roles.
## EM Microelectronic Marin
For a long time, the EM9301 has been the only Bluetooth Single-Mode LE chipset with an HCI interface. The EM9301 can be connected via SPI or UART. The UART interface does not support hardware flow control and is not recommended for use with BTstack. The SPI mode uses a proprietary but documented exension to implement flow control and signal if the EM9301 has data to send.
**Update:** EM has just announced a new EM9304 that also features an HCI mode and supports the Bluetooth 4.2. specification. It seems to support the Data Length Extension but not and multiple concurrent roles.
**BD Addr** must be set during startup since it does not have a stored fix address.
**SCO data** is not supported since it is LE only.
**Baud rate** could be set for UART mode. For SPI, the master controls the speed via the SPI Clock line.
**Init scripts** are not required although it is possible to upload small firmware patches.
**BTstack integration**: The common code for the EM9301 is provided by *btstack_chipset_em9301.c*. During the setup, *btstack_chipset_em9301_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function. It enables to set the BD Addr during start.
## Nordic nRF5 series
The Single-Mode LE chipsets from the Nordic nRF5 series chipsets do not have an HCI interface. Instead, they provide an LE Bluetooth Stack as a binary library, the so-called *SoftDevices*. Developer can write their Bluetooth application on top of this library usually. Since the chipset can be programmed, it can also be loaded with a firmware that provides a regular HCI H4 interface for a Host.
An interesting feature of the nRF5 chipsets is that they can support multiple LE roles at the same time, e.g. being Central in one connection and a Peripheral in another connection. Also, the nRF52 SoftDevice implementation supports the Bluetooth 4.2 Data Length Extension.
Both nRF5 series, the nRF51 and the nRF52, can be used with an HCI firmware. The HCI firmware does not support the Data Length Extension yet, but this will be supported soon. Also, the nRF51 does not support encryted connections at the moment (November 18th, 2016) although this might become supported as well.
**BD ADDR** is not set automatically. However, during production, a 64-bit random number is stored in the each chip. Nordic uses this random number as a random static address in their SoftDevice implementation.
**SCO data** is not supported since it is LE only.
**Baud rate** is fixed to 115200 by the patch althouth the firmware could be extended to support a baud rate change.
**Init script** is not required.
**BTstack integration**: No special chipset driver is provided. In order to use the random static address, the provided patch stores this address as the (invalid) public address that is returned by the HCI Read BD Addr command. When BTstack detects that it is a Nordic chipset, it automatically uses this address as random static address - unless the app chooses to use private addresses.
To use these chipsets with BTstack, you need to install an arm-none-eabi gcc toolchain and the nRF5x Command Line Tools incl. the J-Link drivers, checkout the Zephyr project, apply a minimal patch to help with using a random static address, and flash it onto the chipset:
* Install [J-Link Software and documentation pack](https://www.segger.com/jlink-software.html).
* Get nrfjprog as part of the [nRFx-Command-Line-Tools](http://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK). Click on Downloads tab on the top and look for your OS.
* [Checkout Zephyr and install toolchain](https://www.zephyrproject.org/doc/getting_started/getting_started.html). We recommend using the [arm-non-eabi gcc binaries](https://launchpad.net/gcc-arm-embedded) instead of compiling it yourself. At least on OS X, this failed for us.
* Download our [patch](https://raw.githubusercontent.com/bluekitchen/btstack/develop/port/nrf5-zephyr/hci_firmware.patch) into the Zephyr root folder and apply it there:
<!-- -->
$ patch -p1 < hci_firmware.patch
* In *samples/bluetooth/hci_uart* compile the firmware for nRF52 Dev Kit
<!-- -->
$ make BOARD=nrf52_pca10040
* Upload the firmware
$ ./flash_nrf52_pca10040.sh
* For the nRF51 Dev Kit, use `make BOARD=nrf51_pca10028` and `./flash_nrf51_10028.sh` with the nRF51 kit.
* The nRF5 dev kit acts as an LE HCI Controller with H4 interface.
## STMicroelectronics
STMicroelectronics offers the Bluetooth V2.1 + EDR chipset STLC2500D that supports SPI and UART H4 connection.
**BD Addr** can be set with custom command alhough all chipsets have an official address stored.
**SCO data** might work. We didn't try.
**Baud rate** can be set with custom command. The baud rate change of the chipset happens within 0.5 seconds. At least on BTstack, knowning exactly when the command was fully sent over the UART is non-trivial, so BTstack switches to the new baud rate after 100 ms to expect the command response on the new speed.
**Init scripts** are not required although it is possible to upload firmware patches.
**BTstack integration**: Support for the STLC2500C is provided by *btstack_chipset_stlc.c*. During the setup, *btstack_chipset_stlc2500d_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function. It enables higher UART baud rate and to set the BD Addr during startup.
## Texas Instruments CC256x series
The Texas Instruments CC256x series is currently in its third iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT model (CC2567). A variant of the Dual-mode chipset is also integrated into TI's WiLink 8 Wifi+Bluetooth combo modules of the WL183x, WL185x, WL187x, and WL189x series.
The CC256x chipset is connected via an UART connection and supports the H4, H5 (since third iteration), and eHCILL.
**SCO data** is routed to the I2S/PCM interface but can be configured with the [HCI_VS_Write_SCO_Configuration](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Write_SCO_Configuration_.280xFE10.29) command.
**Baud rate** can be set with [HCI_VS_Update_UART_HCI_Baudrate](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Update_UART_HCI_Baudrate_.280xFF36.29). 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.
The Makefile at *chipset/cc256x/Makefile* is able to automatically download and convert the requested file. It does this by:
- Downloading one or more [BTS files](http://processors.wiki.ti.com/index.php/CC256x_Downloads) for your chipset.
- Running the Python script:
<!-- -->
./convert_bts_init_scripts.py
**Update:** For the latest revision of the CC256x chipsets, the CC2560B
and CC2564B, TI decided to split the init script into a main part and
the BLE part. The conversion script has been updated to detect
*bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts*
if present and merges them into a single .c file.
**Update 2:** In May 2015, TI renamed the init scripts to match
the naming scheme previously used on Linux systems. The conversion
script has been updated to also detect *initscripts_TIInit_6.7.16_bt_spec_4.1.bts*
and integrates *initscripts_TIInit_6.7.16_ble_add-on.bts* if present.
**BTstack integration**: The common code for all CC256x chipsets is provided by *btstack_chipset_cc256x.c*. During the setup, *btstack_chipset_cc256x_instance* function is used to get a *btstack_chiopset_t* instance and passed to *hci_init* function.
SCO Data can be routed over HCI, so HFP Wide-Band Speech is supported.
## Toshiba
The Toshiba TC35661 Dual-Mode chipset is available in three variants: standalone incl. binary Bluetooth stack, as a module with embedded stack or with a regular HCI interface. The HCI variant has the model number TC35661007.
We've tried their USB Evaluation Stick that contains an USB-to-UART adapter and the PAN1026 module that contains the TC35661 -501. We have been told by our distributor that the -501 variant also supports the HCI interface. However, while our tests have shown that Classic Bluetooth with SPP works fine with this variant, none of the LE commands work.
**SCO data** might work. We didn't try.
**Baud rate** can be set with custom command.
**BD Addr ** must be set with custom command. It does not have a stored valid public BD Addr.
**Init Script** is not required. A patch file might be uploaded.
**BTstack integration**: Support for the TC35661 series is provided by *btstack_chipset_tc3566x.c*. During the setup, *btstack_chipset_tc3566x_instance* function is used to get a *btstack_chipset_t* instance and passed to *hci_init* function. It enables higher UART baud rate and sets the BD Addr during startup.

9
chipset/bcm/Makefile.inc Normal file
View File

@ -0,0 +1,9 @@
#
# Makefile to download and convert .hcd init files for Broadcom Bluetooth chipsets
#
all: BCM43430A1.hcd
# used with Ampak AP6121 and BCM43438A1
BCM43430A1.hcd:
curl -O -L https://github.com/OpenELEC/misc-firmware/raw/master/firmware/brcm/BCM43430A1.hcd

View File

@ -51,21 +51,24 @@
#include "btstack_debug.h"
#include "btstack_chipset_bcm.h"
#ifdef HAVE_POSIX_FILE_IO
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#endif
static int send_download_command;
static uint32_t init_script_offset;
// Embedded == non posix systems
// actual init script provided by separate bt_firmware_image.c from WICED SDK
extern const uint8_t brcm_patchram_buf[];
extern const int brcm_patch_ram_length;
extern const char brcm_patch_version[];
//
static uint32_t init_script_offset;
static int send_download_command;
static void chipset_init(const void * config){
log_info("Broadcom init script %s, len %u", brcm_patch_version, brcm_patch_ram_length);
init_script_offset = 0;
send_download_command = 1;
}
// @note: Broadcom chips require higher UART clock for baud rate > 3000000 -> limit baud rate in hci.c
static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){
hci_cmd_buffer[0] = 0x18;
@ -84,6 +87,170 @@ static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer)
reverse_bd_addr(addr, &hci_cmd_buffer[3]);
}
#ifdef HAVE_POSIX_FILE_IO
static const char * hcd_file_path;
static const char * hcd_folder_path = ".";
static int hcd_fd;
static char matched_file[1000];
static void chipset_init(const void * config){
if (hcd_file_path){
log_info("chipset-bcm: init file %s", hcd_file_path);
} else {
log_info("chipset-bcm: init folder %s", hcd_folder_path);
}
send_download_command = 1;
init_script_offset = 0;
hcd_fd = -1;
}
static const uint8_t download_command[] = {0x2e, 0xfc, 0x00};
static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
if (hcd_fd < 0){
log_info("chipset-bcm: open file %s", hcd_file_path);
hcd_fd = open(hcd_file_path, O_RDONLY);
if (hcd_fd < 0){
log_error("chipset-bcm: can't open file %s", hcd_file_path);
return BTSTACK_CHIPSET_DONE;
}
}
// send download firmware command
if (send_download_command){
send_download_command = 0;
memcpy(hci_cmd_buffer, download_command, sizeof(download_command));
return BTSTACK_CHIPSET_VALID_COMMAND;
}
// read next command, but skip download command
do {
// read command
int res = read(hcd_fd, hci_cmd_buffer, 3);
if (res == 0){
log_info("chipset-bcm: end of file, size %u", init_script_offset);
close(hcd_fd);
// wait for firmware patch to be applied - shorter delay possible
sleep(1);
return BTSTACK_CHIPSET_DONE;
}
if (res < 0){
log_error("chipset-bcm: read error at %u", init_script_offset);
return BTSTACK_CHIPSET_DONE;
}
init_script_offset += 3;
// read parameters
int param_len = hci_cmd_buffer[2];
if (param_len){
res = read(hcd_fd, &hci_cmd_buffer[3], param_len);
}
if (res < 0){
log_error("chipset-bcm: read error at %u", init_script_offset);
return BTSTACK_CHIPSET_DONE;
}
init_script_offset += param_len;
} while (memcmp(hci_cmd_buffer, download_command, sizeof(download_command)) == 1);
return BTSTACK_CHIPSET_VALID_COMMAND;
}
void btstack_chipset_bcm_set_hcd_file_path(const char * path){
hcd_file_path = path;
}
void btstack_chipset_bcm_set_hcd_folder_path(const char * path){
hcd_folder_path = path;
}
static int equal_ignore_case(const char *str1, const char *str2){
if (!str1 || !str2) return (1);
int i = 0;
while (1){
if (!str1[i] && !str2[i]) return 1;
if (tolower(str1[i]) != tolower(str2[i])) return 0;
if (!str1[i] || !str2[i]) return 0;
i++;
}
}
// assumption starts with BCM or bcm
#define MAX_DEVICE_NAME_LEN 15
void btstack_chipset_bcm_set_device_name(const char * device_name){
// ignore if file path already set
if (hcd_file_path) {
log_error("chipset-bcm: set device name called %s although path %s already set", device_name, hcd_file_path);
return;
}
// construct filename for long variant
if (strlen(device_name) > MAX_DEVICE_NAME_LEN){
log_error("chipset-bcm: device name %s too long", device_name);
return;
}
char filename_complete[MAX_DEVICE_NAME_LEN+5];
strcpy(filename_complete, device_name);
strcat(filename_complete, ".hcd");
// construct short variant without revision info
char filename_short[MAX_DEVICE_NAME_LEN+5];
strcpy(filename_short, device_name);
int len = strlen(filename_short);
while (len > 3){
char c = filename_short[len-1];
if (isdigit(c) == 0) break;
len--;
}
if (len > 3){
filename_short[len-1] = 0;
}
strcat(filename_short, ".hcd");
log_info("chipset-bcm: looking for %s and %s", filename_short, filename_complete);
// find in folder
DIR *dirp = opendir(hcd_folder_path);
int match_short = 0;
int match_complete = 0;
if (!dirp){
log_error("chipset-bcm: could not get directory for %s", hcd_folder_path);
return;
}
while (1){
struct dirent *dp = readdir(dirp);
if (!dp) break;
if (equal_ignore_case(filename_complete, dp->d_name)){
match_complete = 1;
continue;
}
if (equal_ignore_case(filename_short, dp->d_name)){
match_short = 1;
}
}
closedir(dirp);
if (match_complete){
sprintf(matched_file, "%s/%s", hcd_folder_path, filename_complete);
hcd_file_path = matched_file;
return;
}
if (match_short){
sprintf(matched_file, "%s/%s", hcd_folder_path, filename_short);
hcd_file_path = matched_file;
return;
}
log_error("chipset-bcm: could not find %s or %s, please provide .hcd file in %s", filename_complete, filename_short, hcd_folder_path);
}
#else
static void chipset_init(const void * config){
log_info("chipset-bcm: init script %s, len %u", brcm_patch_version, brcm_patch_ram_length);
init_script_offset = 0;
send_download_command = 1;
}
static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
// send download firmware command
if (send_download_command){
@ -103,6 +270,7 @@ static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
init_script_offset += cmd_len;
return BTSTACK_CHIPSET_VALID_COMMAND;
}
#endif
static const btstack_chipset_t btstack_chipset_bcm = {

View File

@ -52,6 +52,27 @@ extern "C" {
const btstack_chipset_t * btstack_chipset_bcm_instance(void);
// Support for loading .hcd init files on POSIX systems
/**
* @brief Set path to .hcd init file
* @param path
*/
void btstack_chipset_bcm_set_hcd_file_path(const char * path);
/**
* @brief Set folder to look for .hcd init files
* @param path
*/
void btstack_chipset_bcm_set_hcd_folder_path(const char * path);
/**
* @brief Look for .hcd init file based on device name
* @param device_name e.g. BCM43430A1
*/
void btstack_chipset_bcm_set_device_name(const char * path);
#if defined __cplusplus
}
#endif

1
doc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
chipsets.md

View File

@ -26,6 +26,7 @@ preview: update_docs_and_apis html
mkdocs serve
update_docs_and_apis:
sed -e "s|../doc/manual/docs/||g" ../../chipset/README.md > docs/chipsets.md
rm -rf tmp
mkdir tmp
./update_apis.py
@ -33,7 +34,7 @@ update_docs_and_apis:
clean:
rm -rf docs_final tmp btstack *.pdf latex/btstack_generated.* latex/btstack_final.tex
rm -rf docs/appendix/apis.md docs/appendix/index.md docs/examples/examples.md
rm -rf docs/appendix/apis.md docs/appendix/index.md docs/examples/examples.md docs/chipsets.md
rm -rf docs_tmp latex btstack help

View File

@ -1,95 +0,0 @@
In this chapter, we first explain how Bluetooth chipsets are connected physically and
then provide information about popular Bluetooth chipset and their use with BTstack.
The communication between a Host (a computer or an MCU) and a Host Controller (the actual Bluetoot chipset) follows the Host Controller Interface (HCI), see {@fig:HostChipsetConnection}. HCI defines how commands, events, asynchronous and synchronous data packets are exchanged, see [here]). Asynchronous packets (ACL) are used for data transfer, while synchronous packets (SCO) are used for Voice with the Headset and the Hands-free Profiles.
![Host Controller to Host connection](picts/host_chipset_connection.png){#fig:HostChipsetConnection}
On desktop-class computers incl. laptops, USB is mainly used as HCI transport layer. On embedded systems, UART connections are used instead, although USB could be used as well.
For UART connections, different transport layer variants exist. The most common one is the official "UART Transport", also called H4. It requires hardware flow control via the CTS/RTS lines and assumes no errors on the UART lines. The "Three-Wire UART Transport", also called H5, makes use of the SLIP protocol to transmit a packet and can deal with packet loss and bit-errors by retranssion. Finally, Texas Instruments created the "eHCILL transport" layer based on H4 that allows both sides to enter sleep mode without loosing synchronisation.
Unfortunately, the HCI standard misses a few relevant details:
* For UART based connections, the initial baud rate isn't defined but most Bluetooth chipsets use 115200 baud. For better throughput, a higher baud rate is necessary, but there's no standard HCI command to change it. Instead, each vendor had to come up with their own set of vendor-specific commands. Sometimes, additional steps, e.g. doing a warm reset, are neceesary to activate the baud rate change as well.
* Some Bluetooth chipsets don't have a unique MAC address. On start, the MAC address needs to be set, but there's no standard HCI command to set it.
* SCO data for Voice can either be transmitted via the HCI interface or via an explicit PCM/I2S interface on the chipset. Most chipsets default to the PCM/I2S interface. To use it via USB or for Wide-Band Speech in the Hands-Free Profile, the data needs to be delivered to the host MCU. Newer Bluetooth standards define a HCI command to configure the routing, but it is not implemented in the chipsets we've tested so far. Instead, this is configured in a vendor-specific way as well.
* In addition, most vendors allow to patch their chipsets at run time by sending patch comands to the chipset. Obviously, this is also vendor dependent.
The level of developer documentation and support varies widely between the various Bluetooth chipset providers.
From our experience, only Texas Instruments and EM Microelectronics provide all relevant information directly on their website. Nordic Semiconductor does not officially have Bluetooth chipsets with HCI interface, but their the documentation on their nRF5 series is complete and very informative. TI and Nordic also provide excellent support via their web forum.
Broadcom, whose Bluetooth + Wifi division has been acquired by the Cypress Semiconductor Corporation, provides developer documentation only to large customers as far as we know. It's possible to join their Community forum and download the WICED SDK. The WICED SDK is targeted at Wifi + Bluetooth Combo chipsets and contains the necessary chipset patch files.
CSR, which has been acquired by Qualcomm, provides all relevant information on their Support website after signing an NDA.
Chipset | HCI Transport | SCO over HCI | BTstack support | Comment
-------------------- | ---------------|------------------|-------------------|--------
Broadcom USB Dongles | USB | No (didn't work) | chipset/bcm |
Broadcom BCM43438 | H4, H5 | No (didn't work) | chipset/bcm | max UART baudrate 3 mbps
CSR 8x10, 8x11 | H4, H5 | No (didn't work) | chipset/csr |
CSR USB Dongles | USB | Yes | chipset/csr |
EM 9301 | SPI | n.a. | chipset/em9301 | LE only, custom HCI SPI implementation
Nordic nRF | H4 | n.a. | n.a. | LE only, requires HCI firmware
STM STLC2500D | H4 | No (didn't try) | chipset/stlc2500d | custom deep sleep management not supported
TC35661 | H4 | No (didn't try) | chipset/tc3566 | BLE patches missing
TI CC256x, WL183x | H4, H5, eHCILL | Yes | chipset/cc256x | also WL185x, WL187x, and WL189x
**Note** All Bluetooth Classic chipsets support SCO over HCI, for those that are marked with No, we either didn't try or didn't found enough information to configure it correctly.
## Broadcom
## CSR
## EM Microelectronic Marin
## Nordic nRF5 series
## ST Micro
## Texas Instruments CC256x series
The Texas Instruments CC256x series is currently in its third iteration and provides a Classic-only (CC2560), a Dual-mode (CC2564), and a Classic + ANT model (CC2567). A variant of the Dual-mode chipset is also integrated into TI's WiLink 8 Wifi+Bluetooth combo modules of the WL183x, WL185x, WL187x, and WL189x series.
The CC256x chipset is connected via an UART connection and supports the H4, H5 (since third iteration), and eHCILL.
**SCO data** is routed to the I2S/PCM interface but can be configured with the [HCI_VS_Write_SCO_Configuration](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Write_SCO_Configuration_.280xFE10.29) command.
**Baud rate** can be set with [HCI_VS_Update_UART_HCI_Baudrate](http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands#HCI_VS_Update_UART_HCI_Baudrate_.280xFF36.29)
**BD Addr** can be set with [HCI_VS_Write_BD_Addr](2.2.1 HCI_VS_Write_BD_Addr (0xFC06)) although all chipsets have an official address stored.
**CC256x Init Scripts.** In order to use the CC256x chipset an initialization script must be obtained and converted into a C file for use with BTstack.
The Makefile at *chipset/cc256x/Makefile* is able to automatically download and convert the requested file. It does this by:
- Downloading one or more [BTS files](http://processors.wiki.ti.com/index.php/CC256x_Downloads) for your chipset.
- Running runnig the Python script:
<!-- -->
./convert_bts_init_scripts.py
**Update:** For the latest revision of the CC256x chipsets, the CC2560B
and CC2564B, TI decided to split the init script into a main part and
the BLE part. The conversion script has been updated to detect
*bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts*
if present and merges them into a single .c file.
**Update 2:** In May 2015, TI renamed the init scripts to match
the naming scheme previously used on Linux systems. The conversion
script has been updated to also detect *initscripts_TIInit_6.7.16_bt_spec_4.1.bts*
and integrates *initscripts_TIInit_6.7.16_ble_add-on.bts* if present.
**BTstack integration**: The common code for all CC256x chipsets is provided by *btstack_chipset_cc256x.c*. During the setup, *btstack_chipset_cc256x_instance* function is used to get a *btstack_control_t* instance and passed to *hci_init* function.
SCO Data can be route over HCI, so HFP Wide-Band Speech is supported.
## Toshiba

View File

@ -6,10 +6,11 @@ pages:
- [quick_start.md, Quick Start]
- [architecture.md, BTstack Architecture]
- [how_to.md, How to configure BTstack]
- [protocols.md, Supported Protocols]
- [profiles.md, Supported Profiles]
- [protocols.md, Protocols]
- [profiles.md, Profiles]
- [gatt_services.md, Implemented GATT Services]
- [examples/examples.md, Embedded Examples]
- [chipsets.md, Chipsets]
- [porting.md, Porting to Other Platforms]
- [integration.md, Integrating with Existing Systems]
- [appendix/apis.md, APIs]

View File

@ -130,15 +130,15 @@ enum STATE state = INIT;
static void dump_supported_codecs(void){
int i;
int mSBC_skipped = 0;
printf("Supported codecs:");
printf("Supported codecs: ");
for (i = 0; i < sizeof(codecs); i++){
switch(codecs[i]){
case HFP_CODEC_CVSD:
printf(" CVSD");
printf("CVSD");
break;
case HFP_CODEC_MSBC:
if (hci_extended_sco_link_supported()){
printf("mSBC");
printf(", mSBC");
} else {
mSBC_skipped = 1;
}

View File

@ -86,15 +86,15 @@ char cmd;
static void dump_supported_codecs(void){
int i;
int mSBC_skipped = 0;
printf("Supported codecs:");
printf("Supported codecs: ");
for (i = 0; i < sizeof(codecs); i++){
switch(codecs[i]){
case HFP_CODEC_CVSD:
printf(" CVSD");
printf("CVSD");
break;
case HFP_CODEC_MSBC:
if (hci_extended_sco_link_supported()){
printf("mSBC");
printf(", mSBC");
} else {
mSBC_skipped = 1;
}

View File

@ -66,7 +66,7 @@
#ifdef HAVE_POSIX_FILE_IO
#define SCO_WAV_FILENAME "sco_input.wav"
#define SCO_MSBC_OUT_FILENAME "sco_output.msbc"
#define SCO_MSBC_IN_FILENAME "sco_input.mscb"
#define SCO_MSBC_IN_FILENAME "sco_input.msbc"
#define SCO_WAV_DURATION_IN_SECONDS 15
#endif

View File

@ -44,6 +44,7 @@
#include "wav_util.h"
#include "btstack_util.h"
#include "btstack_debug.h"
static int wav_reader_fd;
static int bytes_per_sample = 2;
@ -164,7 +165,7 @@ int wav_writer_write_int16(int num_samples, int16_t * data){
int wav_reader_open(const char * filepath){
wav_reader_fd = open(filepath, O_RDONLY);
if (!wav_reader_fd) {
printf("Can't open file %s", filepath);
log_error("Can't open file %s", filepath);
return 1;
}
@ -173,6 +174,10 @@ int wav_reader_open(const char * filepath){
int num_channels = little_endian_read_16(buf, 22);
int block_align = little_endian_read_16(buf, 32);
if (num_channels != 1 && num_channels != 2) {
log_error("Unexpected num channels %d", num_channels);
return 1;
}
bytes_per_sample = block_align/num_channels;
if (bytes_per_sample > 2){
bytes_per_sample = bytes_per_sample/8;

View File

@ -34,4 +34,6 @@ spp_and_le_counter
spp_and_le_counter.h
spp_counter
spp_streamer
spp_streamer
spp_streamer
sco_input*
sco_output*

View File

@ -5,8 +5,8 @@ TOOLCHAIN = /usr/local/android-ndk
SYSROOT = $(TOOLCHAIN)/sysroot
GCC = $(TOOLCHAIN)/bin/arm-linux-androideabi-gcc
STRIP = $(TOOLCHAIN)/bin/arm-linux-androideabi-strip
CFLAGS = -march=armv7-a -mfloat-abi=softfp -I$(SYSROOT)/usr/include
LDFLAGS = -Wl,--fix-cortex-a8 -L$(SYSROOT)/usr/lib
CFLAGS = -march=armv7-a -mfloat-abi=softfp -I$(SYSROOT)/usr/include -fpie -fpic -fPIE -pie#
LDFLAGS = -Wl,--fix-cortex-a8 -L$(SYSROOT)/usr/lib -fpie -fpic -fPIE -pie
BTSTACK_ROOT = ../..

View File

@ -0,0 +1,98 @@
diff --git a/samples/bluetooth/hci_uart/flash_nrf51_pca10028.sh b/samples/bluetooth/hci_uart/flash_nrf51_pca10028.sh
new file mode 100755
index 0000000..d51907f
--- /dev/null
+++ b/samples/bluetooth/hci_uart/flash_nrf51_pca10028.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+nrfjprog --eraseall -f nrf51
+nrfjprog --program outdir/nrf51_pca10028/zephyr.hex -f nrf51
+nrfjprog --reset -f nrf51
diff --git a/samples/bluetooth/hci_uart/flash_nrf52_pca10040.sh b/samples/bluetooth/hci_uart/flash_nrf52_pca10040.sh
new file mode 100755
index 0000000..cc20145
--- /dev/null
+++ b/samples/bluetooth/hci_uart/flash_nrf52_pca10040.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+nrfjprog --eraseall -f nrf52
+nrfjprog --program outdir/nrf52_pca10040/zephyr.hex -f nrf52
+nrfjprog --reset -f nrf52
diff --git a/samples/bluetooth/hci_uart/nrf5.conf b/samples/bluetooth/hci_uart/nrf5.conf
index c3b362d..9fe511f 100644
--- a/samples/bluetooth/hci_uart/nrf5.conf
+++ b/samples/bluetooth/hci_uart/nrf5.conf
@@ -7,6 +7,6 @@ CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_BLUETOOTH=y
CONFIG_BLUETOOTH_HCI_RAW=y
CONFIG_BLUETOOTH_MAX_CONN=16
-CONFIG_UART_NRF5_BAUD_RATE=1000000
+CONFIG_UART_NRF5_BAUD_RATE=115200
CONFIG_UART_NRF5_FLOW_CONTROL=y
CONFIG_BLUETOOTH_CONTROLLER_ASSERT_HANDLER=y
diff --git a/samples/bluetooth/hci_uart/src/Makefile b/samples/bluetooth/hci_uart/src/Makefile
index b666967..8606b24 100644
--- a/samples/bluetooth/hci_uart/src/Makefile
+++ b/samples/bluetooth/hci_uart/src/Makefile
@@ -1 +1,2 @@
obj-y += main.o
+ccflags-y += -I../../../subsys/bluetooth/controller/ll
diff --git a/samples/bluetooth/hci_uart/src/main.c b/samples/bluetooth/hci_uart/src/main.c
index 76e75e1..70da655 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
@@ -354,6 +357,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 */
@@ -373,6 +388,12 @@ void main(void)
NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
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;
diff --git a/subsys/bluetooth/controller/ll/ctrl.h b/subsys/bluetooth/controller/ll/ctrl.h
index f9b092d..b950083 100644
--- a/subsys/bluetooth/controller/ll/ctrl.h
+++ b/subsys/bluetooth/controller/ll/ctrl.h
@@ -79,7 +79,7 @@
* Controller Interface Defines
****************************************************************************/
#define RADIO_BLE_VERSION_NUMBER (0x08)
-#define RADIO_BLE_COMPANY_ID (0xFFFF)
+#define RADIO_BLE_COMPANY_ID (0x0059) // Nordic Semiconductor ASA
#define RADIO_BLE_SUB_VERSION_NUMBER (0xFFFF)
#define RADIO_BLE_FEATURES (0x1F) /* LE Ping, Slave Initiated
* Feature request, Extended

View File

@ -65,4 +65,4 @@ rsync -a flash_nrf52_pca10040.sh ${HCI_UART}/flash_nrf52_pca10040.sh
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
grep -q -F ll_address_set ${HCI_UART}/src/main.c || cat hci_uart.patch | patch -d ${ZEPHYR_BASE} -p1

View File

@ -3,6 +3,7 @@ BTSTACK_ROOT = ../..
CORE += \
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c \
btstack_chipset_bcm.c \
btstack_chipset_cc256x.c \
btstack_chipset_csr.c \
btstack_chipset_em9301.c \
@ -16,7 +17,6 @@ CORE += \
main.c \
stdin_support.c \
# bluetooth_init_cc2564_2.14.c \
# btstack_chipset_bcm.c \
# TI-WL183x requires TIInit_11.8.32.c
@ -26,6 +26,9 @@ include ${BTSTACK_ROOT}/example/Makefile.inc
# fetch and convert TI init scripts
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
# fetch Broadcom init scripts
include ${BTSTACK_ROOT}/chipset/bcm/Makefile.inc
CFLAGS += -g -Wall -Werror \
-I$(BTSTACK_ROOT)/platform/embedded \
-I$(BTSTACK_ROOT)/platform/posix \
@ -62,4 +65,5 @@ endif
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
all: ${EXAMPLES}
all: BCM43430A1.hcd ${EXAMPLES}

View File

@ -66,6 +66,8 @@
#include "btstack_chipset_stlc2500d.h"
#include "btstack_chipset_tc3566x.h"
int is_bcm;
int btstack_main(int argc, const char * argv[]);
static hci_transport_config_uart_t config = {
@ -80,9 +82,24 @@ 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) break;
printf("BTstack up and running.\n");
break;
case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
// terminate, name 248 chars
packet[6+248] = 0;
printf("Local name: %s\n", &packet[6]);
if (is_bcm){
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
}
}
break;
default:
break;
}
}
static void sigint_handler(int param){
@ -131,7 +148,7 @@ static void local_version_information_callback(uint8_t * packet){
printf("- Manufacturer 0x%04x\n", manufacturer);
switch (manufacturer){
case COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
printf("Cambridge Silicon Radio CSR chipset.\n");
printf("Cambridge Silicon Radio - CSR chipset.\n");
use_fast_uart();
hci_set_chipset(btstack_chipset_csr_instance());
break;
@ -146,8 +163,11 @@ static void local_version_information_callback(uint8_t * packet){
#endif
break;
case COMPANY_ID_BROADCOM_CORPORATION:
printf("Broadcom chipset. Not supported yet\n");
// hci_set_chipset(btstack_chipset_bcm_instance());
printf("Broadcom - using BCM driver.\n");
hci_set_chipset(btstack_chipset_bcm_instance());
use_fast_uart();
is_bcm = 1;
break;
case COMPANY_ID_ST_MICROELECTRONICS:
printf("ST Microelectronics - using STLC2500d driver.\n");
@ -159,7 +179,7 @@ static void local_version_information_callback(uint8_t * packet){
hci_set_chipset(btstack_chipset_em9301_instance());
break;
case COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
printf("Nordic Semicondutor ASA nRF5 chipset.\n");
printf("Nordic Semiconductor nRF5 chipset.\n");
break;
default:
printf("Unknown manufacturer / manufacturer not supported yet.\n");
@ -177,7 +197,7 @@ 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-A900K0VK";
config.device_name = "/dev/tty.usbserial-A9OVNX5P";
// init HCI
const btstack_uart_block_t * uart_driver = btstack_uart_block_posix_instance();

View File

@ -312,3 +312,14 @@ int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
}
return result;
}
uint32_t btstack_atoi(const char *str){
uint32_t val = 0;
while (1){
char chr = *str;
if (!chr || chr < '0' || chr > '9')
return val;
val = (val * 10) + (chr - '0');
str++;
}
}

View File

@ -216,6 +216,14 @@ void uuid_add_bluetooth_prefix(uint8_t * uuid128, uint32_t short_uuid);
*/
int uuid_has_bluetooth_prefix(uint8_t * uuid128);
/**
* @brief Parse unsigned number
* @param str to parse
* @return value
*/
uint32_t btstack_atoi(const char *str);
#if defined __cplusplus
}
#endif

View File

@ -258,7 +258,7 @@ void btstack_cvsd_plc_process_data(btstack_cvsd_plc_state_t * state, int8_t * in
btstack_cvsd_plc_good_frame(state, in, out);
state->good_frames_nr++;
if (state->good_frames_nr == 1){
printf("First good frame at index %d\n", state->frame_count-1);
log_info("First good frame at index %d\n", state->frame_count-1);
}
}
}
@ -279,12 +279,12 @@ void btstack_cvsd_plc_mark_bad_frame(btstack_cvsd_plc_state_t * state, int8_t *
memcpy(out, in, size);
state->good_frames_nr++;
if (state->good_frames_nr == 1){
printf("First good frame at index %d\n", state->frame_count-1);
log_info("First good frame at index %d\n", state->frame_count-1);
}
}
}
void btstack_cvsd_dump_statistics(btstack_cvsd_plc_state_t * state){
printf("Good frames: %d\n", state->good_frames_nr);
printf("Bad frames: %d\n", state->bad_frames_nr);
log_info("Good frames: %d\n", state->good_frames_nr);
log_info("Bad frames: %d\n", state->bad_frames_nr);
}

View File

@ -155,22 +155,6 @@ void hfp_hf_drop_mSBC_if_eSCO_not_supported(uint8_t * codecs, uint8_t * codecs_n
memcpy(codecs, tmp_codecs, tmp_codec_nr);
}
#if 0
void hfp_set_codec(hfp_connection_t * hfp_connection, uint8_t *packet, uint16_t size){
// parse available codecs
int pos = 0;
int i;
for (i=0; i<size; i++){
pos+=8;
if (packet[pos] > hfp_connection->negotiated_codec){
hfp_connection->negotiated_codec = packet[pos];
}
}
printf("Negotiated Codec 0x%02x\n", hfp_connection->negotiated_codec);
}
#endif
// UTILS
int get_bit(uint16_t bitmap, int position){
return (bitmap >> position) & 1;
@ -1086,30 +1070,30 @@ void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree)
switch (hfp_connection->command){
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME:
log_info("format %s, ", hfp_connection->line_buffer);
hfp_connection->network_operator.format = atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->network_operator.format = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
break;
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT:
log_info("format %s \n", hfp_connection->line_buffer);
hfp_connection->network_operator.format = atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->network_operator.format = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
break;
case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS:
case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS:
case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE:
hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].state = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].state = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
break;
case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS:
hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
log_info("%d \n", hfp_connection->ag_indicators[hfp_connection->parser_item_index].status);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].status_changed = 1;
break;
case HFP_CMD_RETRIEVE_AG_INDICATORS:
hfp_connection->ag_indicators[hfp_connection->parser_item_index].min_range = atoi((char *)hfp_connection->line_buffer);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].min_range = btstack_atoi((char *)hfp_connection->line_buffer);
log_info("%s, ", hfp_connection->line_buffer);
break;
case HFP_CMD_AG_SENT_PHONE_NUMBER:
case HFP_CMD_AG_SENT_CALL_WAITING_NOTIFICATION_UPDATE:
case HFP_CMD_AG_SENT_CLIP_INFORMATION:
hfp_connection->bnip_type = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->bnip_type = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
break;
default:
break;
@ -1123,7 +1107,7 @@ void hfp_parse(hfp_connection_t * hfp_connection, uint8_t byte, int isHandsFree)
log_info("name %s\n", hfp_connection->line_buffer);
break;
case HFP_CMD_RETRIEVE_AG_INDICATORS:
hfp_connection->ag_indicators[hfp_connection->parser_item_index].max_range = atoi((char *)hfp_connection->line_buffer);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].max_range = btstack_atoi((char *)hfp_connection->line_buffer);
hfp_connection->parser_item_index++;
hfp_connection->ag_indicators_nr = hfp_connection->parser_item_index;
log_info("%s)\n", hfp_connection->line_buffer);
@ -1148,7 +1132,7 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
int value;
switch (hfp_connection->command){
case HFP_CMD_SET_GENERIC_STATUS_INDICATOR_STATUS:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
int i;
switch (hfp_connection->parser_item_index){
case 0:
@ -1178,7 +1162,7 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0;
break;
case 1:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->bnip_type = value;
break;
default:
@ -1189,19 +1173,19 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
case HFP_CMD_LIST_CURRENT_CALLS:
switch(hfp_connection->parser_item_index){
case 0:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->clcc_idx = value;
break;
case 1:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->clcc_dir = value;
break;
case 2:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->clcc_status = value;
break;
case 3:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->clcc_mpty = value;
break;
case 4:
@ -1209,7 +1193,7 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
hfp_connection->bnip_number[sizeof(hfp_connection->bnip_number)-1] = 0;
break;
case 5:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->bnip_type = value;
break;
default:
@ -1218,45 +1202,45 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
hfp_connection->parser_item_index++;
break;
case HFP_CMD_SET_MICROPHONE_GAIN:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->microphone_gain = value;
log_info("hfp parse HFP_CMD_SET_MICROPHONE_GAIN %d\n", value);
break;
case HFP_CMD_SET_SPEAKER_GAIN:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->speaker_gain = value;
log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value);
break;
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->ag_activate_voice_recognition = value;
log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value);
break;
case HFP_CMD_TURN_OFF_EC_AND_NR:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->ag_echo_and_noise_reduction = value;
log_info("hfp parse HFP_CMD_TURN_OFF_EC_AND_NR %d\n", value);
break;
case HFP_CMD_CHANGE_IN_BAND_RING_TONE_SETTING:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->remote_supported_features = store_bit(hfp_connection->remote_supported_features, HFP_AGSF_IN_BAND_RING_TONE, value);
log_info("hfp parse HFP_CHANGE_IN_BAND_RING_TONE_SETTING %d\n", value);
break;
case HFP_CMD_HF_CONFIRMED_CODEC:
hfp_connection->codec_confirmed = atoi((char*)hfp_connection->line_buffer);
hfp_connection->codec_confirmed = btstack_atoi((char*)hfp_connection->line_buffer);
log_info("hfp parse HFP_CMD_HF_CONFIRMED_CODEC %d\n", hfp_connection->codec_confirmed);
break;
case HFP_CMD_AG_SUGGESTED_CODEC:
hfp_connection->suggested_codec = atoi((char*)hfp_connection->line_buffer);
hfp_connection->suggested_codec = btstack_atoi((char*)hfp_connection->line_buffer);
log_info("hfp parse HFP_CMD_AG_SUGGESTED_CODEC %d\n", hfp_connection->suggested_codec);
break;
case HFP_CMD_SUPPORTED_FEATURES:
hfp_connection->remote_supported_features = atoi((char*)hfp_connection->line_buffer);
hfp_connection->remote_supported_features = btstack_atoi((char*)hfp_connection->line_buffer);
log_info("Parsed supported feature %d\n", hfp_connection->remote_supported_features);
break;
case HFP_CMD_AVAILABLE_CODECS:
log_info("Parsed codec %s\n", hfp_connection->line_buffer);
hfp_connection->remote_codecs[hfp_connection->parser_item_index] = (uint16_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->remote_codecs[hfp_connection->parser_item_index] = (uint16_t)btstack_atoi((char*)hfp_connection->line_buffer);
hfp_connection->parser_item_index++;
hfp_connection->remote_codecs_nr = hfp_connection->parser_item_index;
break;
@ -1267,14 +1251,14 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
break;
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
log_info("Parsed Indicator %d with status: %s\n", hfp_connection->parser_item_index+1, hfp_connection->line_buffer);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = atoi((char *) hfp_connection->line_buffer);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].status = btstack_atoi((char *) hfp_connection->line_buffer);
hfp_connection->parser_item_index++;
break;
case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE:
hfp_connection->parser_item_index++;
if (hfp_connection->parser_item_index != 4) break;
log_info("Parsed Enable indicators: %s\n", hfp_connection->line_buffer);
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->enable_status_update_for_ag_indicators = (uint8_t) value;
break;
case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES:
@ -1286,17 +1270,17 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS:
case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS:
log_info("Parsed Generic status indicator: %s\n", hfp_connection->line_buffer);
hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].uuid = (uint16_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->generic_status_indicators[hfp_connection->parser_item_index].uuid = (uint16_t)btstack_atoi((char*)hfp_connection->line_buffer);
hfp_connection->parser_item_index++;
hfp_connection->generic_status_indicators_nr = hfp_connection->parser_item_index;
break;
case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE:
// HF parses inital AG gen. ind. state
log_info("Parsed List generic status indicator %s state: ", hfp_connection->line_buffer);
hfp_connection->parser_item_index = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->parser_item_index = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
break;
case HFP_CMD_HF_INDICATOR_STATUS:
hfp_connection->parser_indicator_index = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->parser_indicator_index = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
log_info("Parsed HF indicator index %u", hfp_connection->parser_indicator_index);
break;
case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:
@ -1310,7 +1294,7 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
log_info("Parsed Enable AG indicator pos %u('%s') - ignore (mandatory)\n",
hfp_connection->parser_item_index, hfp_connection->ag_indicators[hfp_connection->parser_item_index].name);
} else {
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->ag_indicators[hfp_connection->parser_item_index].enabled = value;
log_info("Parsed Enable AG indicator pos %u('%s'): %u\n", hfp_connection->parser_item_index,
hfp_connection->ag_indicators[hfp_connection->parser_item_index].name, value);
@ -1319,11 +1303,11 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
break;
case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS:
// indicators are indexed starting with 1
hfp_connection->parser_item_index = atoi((char *)&hfp_connection->line_buffer[0]) - 1;
hfp_connection->parser_item_index = btstack_atoi((char *)&hfp_connection->line_buffer[0]) - 1;
log_info("Parsed status of the AG indicator %d, status ", hfp_connection->parser_item_index);
break;
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME:
hfp_connection->network_operator.mode = atoi((char *)&hfp_connection->line_buffer[0]);
hfp_connection->network_operator.mode = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
log_info("Parsed network operator mode: %d, ", hfp_connection->network_operator.mode);
break;
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT:
@ -1338,10 +1322,10 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
break;
case HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR:
hfp_connection->extended_audio_gateway_error = 1;
hfp_connection->extended_audio_gateway_error_value = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->extended_audio_gateway_error_value = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
break;
case HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR:
hfp_connection->enable_extended_audio_gateway_error_report = (uint8_t)atoi((char*)hfp_connection->line_buffer);
hfp_connection->enable_extended_audio_gateway_error_report = (uint8_t)btstack_atoi((char*)hfp_connection->line_buffer);
hfp_connection->ok_pending = 1;
hfp_connection->extended_audio_gateway_error = 0;
break;

View File

@ -1837,7 +1837,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
hfp_connection->ok_pending = 1;
break;
case HFP_CMD_RESPONSE_AND_HOLD_COMMAND:
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
log_info("HF Response and Hold: %u", value);
switch(value){
case HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD:
@ -1862,7 +1862,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
hfp_connection->send_error = 1;
break;
}
value = atoi((char *)&hfp_connection->line_buffer[0]);
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
switch (indicator->uuid){
case 1: // enhanced security
if (value > 1) {
@ -1939,7 +1939,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
hfp_connection->call_index = 0;
if (hfp_connection->line_buffer[1] != '\0'){
hfp_connection->call_index = atoi((char *)&hfp_connection->line_buffer[1]);
hfp_connection->call_index = btstack_atoi((char *)&hfp_connection->line_buffer[1]);
}
switch (hfp_connection->line_buffer[0]){

View File

@ -142,7 +142,6 @@ static void hfp_hf_emit_enhanced_call_status(btstack_packet_handler_t callback,
static int has_codec_negotiation_feature(hfp_connection_t * hfp_connection){
int hf = get_bit(hfp_supported_features, HFP_HFSF_CODEC_NEGOTIATION);
int ag = get_bit(hfp_connection->remote_supported_features, HFP_AGSF_CODEC_NEGOTIATION);
printf("local %d, remote %d\n", hf, ag);
return hf && ag;
}
@ -1005,7 +1004,7 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
case HFP_CMD_RESPONSE_AND_HOLD_STATUS:
hfp_connection->command = HFP_CMD_NONE;
// printf("Response and Hold status: %s\n", hfp_connection->line_buffer);
hfp_emit_event(hfp_callback, HFP_SUBEVENT_RESPONSE_AND_HOLD_STATUS, atoi((char *)&hfp_connection->line_buffer[0]));
hfp_emit_event(hfp_callback, HFP_SUBEVENT_RESPONSE_AND_HOLD_STATUS, btstack_atoi((char *)&hfp_connection->line_buffer[0]));
break;
case HFP_CMD_LIST_CURRENT_CALLS:
hfp_connection->command = HFP_CMD_NONE;
@ -1018,13 +1017,13 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
break;
case HFP_CMD_SET_SPEAKER_GAIN:
hfp_connection->command = HFP_CMD_NONE;
value = atoi((char*)hfp_connection->line_buffer);
value = btstack_atoi((char*)hfp_connection->line_buffer);
hfp_hf_speaker_gain = value;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_SPEAKER_VOLUME, value);
break;
case HFP_CMD_SET_MICROPHONE_GAIN:
hfp_connection->command = HFP_CMD_NONE;
value = atoi((char*)hfp_connection->line_buffer);
value = btstack_atoi((char*)hfp_connection->line_buffer);
hfp_hf_microphone_gain = value;
hfp_emit_event(hfp_callback, HFP_SUBEVENT_MICROPHONE_VOLUME, value);
break;

View File

@ -551,12 +551,12 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
break;
}
} else if (strncmp((char *)packet, HSP_HS_MICROPHONE_GAIN, strlen(HSP_HS_MICROPHONE_GAIN)) == 0){
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_HS_MICROPHONE_GAIN)]);
uint8_t gain = (uint8_t)btstack_atoi((char*)&packet[strlen(HSP_HS_MICROPHONE_GAIN)]);
ag_send_ok = 1;
emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain);
} else if (strncmp((char *)packet, HSP_HS_SPEAKER_GAIN, strlen(HSP_HS_SPEAKER_GAIN)) == 0){
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_HS_SPEAKER_GAIN)]);
uint8_t gain = (uint8_t)btstack_atoi((char*)&packet[strlen(HSP_HS_SPEAKER_GAIN)]);
ag_send_ok = 1;
emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain);
@ -583,7 +583,6 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
switch (event) {
case HCI_EVENT_CONNECTION_REQUEST:
printf("hsp HCI_EVENT_CONNECTION_REQUEST\n");
hci_event_connection_request_get_bd_addr(packet, sco_event_addr);
ag_establish_sco = 1;
break;

View File

@ -454,11 +454,11 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
} else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){
wait_ok = 0;
} else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 0){
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]);
uint8_t gain = (uint8_t)btstack_atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]);
emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain);
} else if (strncmp((char *)packet, HSP_SPEAKER_GAIN, strlen(HSP_SPEAKER_GAIN)) == 0){
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_SPEAKER_GAIN)]);
uint8_t gain = (uint8_t)btstack_atoi((char*)&packet[strlen(HSP_SPEAKER_GAIN)]);
emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain);
} else {
if (!hsp_hs_callback) return;

View File

@ -62,7 +62,7 @@
* D: 8 byte data block
* E: Extended Inquiry Result
* N: Name up to 248 chars, \0 terminated
* P: 16 byte Pairing code
* P: 16 byte data block. Pairing code, Simple Pairing Hash and Randomizer
* A: 31 bytes advertising data
* S: Service Record (Data Element Sequence)
* Q: 32 byte data block, e.g. for X and Y coordinates of P-256 public key
@ -386,6 +386,15 @@ const hci_cmd_t hci_user_passkey_request_negative_reply = {
OPCODE(OGF_LINK_CONTROL, 0x2f), "B"
};
/**
* @param bd_addr
* @param c Simple Pairing Hash C
* @param r Simple Pairing Randomizer R
*/
const hci_cmd_t hci_remote_oob_data_request_reply = {
OPCODE(OGF_LINK_CONTROL, 0x30), "BPP"
};
/**
* @param bd_addr
*/
@ -677,6 +686,12 @@ const hci_cmd_t hci_write_simple_pairing_mode = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x56), "1"
};
/**
*/
const hci_cmd_t hci_read_local_oob_data = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x57), ""
// return status, C, R
};
/**
* @param mode (0 = off, 1 = on)
@ -701,6 +716,14 @@ OPCODE(OGF_CONTROLLER_BASEBAND, 0x6d), "11"
// return: status
};
/**
*/
const hci_cmd_t hci_read_local_extended_ob_data = {
OPCODE(OGF_CONTROLLER_BASEBAND, 0x7d), ""
// return status, C_192, R_192, R_256, C_256
};
/**
* Testing Commands
*/

View File

@ -112,16 +112,19 @@ extern const hci_cmd_t hci_read_buffer_size;
extern const hci_cmd_t hci_read_le_host_supported;
extern const hci_cmd_t hci_read_link_policy_settings;
extern const hci_cmd_t hci_read_link_supervision_timeout;
extern const hci_cmd_t hci_read_local_extended_oob_data;
extern const hci_cmd_t hci_read_local_name;
extern const hci_cmd_t hci_read_local_version_information;
extern const hci_cmd_t hci_read_local_oob_data;
extern const hci_cmd_t hci_read_local_supported_commands;
extern const hci_cmd_t hci_read_local_supported_features;
extern const hci_cmd_t hci_read_local_version_information;
extern const hci_cmd_t hci_read_num_broadcast_retransmissions;
extern const hci_cmd_t hci_read_remote_supported_features_command;
extern const hci_cmd_t hci_read_rssi;
extern const hci_cmd_t hci_reject_connection_request;
extern const hci_cmd_t hci_remote_name_request;
extern const hci_cmd_t hci_remote_name_request_cancel;
extern const hci_cmd_t hci_remote_oob_data_request_reply;
extern const hci_cmd_t hci_remote_oob_data_request_negative_reply;
extern const hci_cmd_t hci_reset;
extern const hci_cmd_t hci_role_discovery;

4
test/hfp/.gitignore vendored
View File

@ -1,4 +1,6 @@
hfp_hf_client_test
hfp_ag_client_test
hfp_hf_parser_test
hfp_ag_parser_test
hfp_ag_parser_test
cvsd_plc_test
results/*

View File

@ -61,7 +61,7 @@ EXAMPLES = hfp_ag_parser_test hfp_ag_client_test hfp_hf_parser_test hfp_hf_clien
all: ${EXAMPLES}
clean:
rm -rf *.o $(EXAMPLES) $(CLIENT_EXAMPLES) *.dSYM *.wav
rm -rf *.o $(EXAMPLES) $(CLIENT_EXAMPLES) *.dSYM *.wav results/*
hfp_ag_parser_test: ${COMMON_OBJ} hfp_gsm_model.o hfp_ag.o hfp.o hfp_ag_parser_test.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
@ -79,6 +79,7 @@ cvsd_plc_test: ${COMMON_OBJ} btstack_cvsd_plc.o wav_util.o cvsd_plc_test.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
test: all
mkdir -p results
./hfp_ag_parser_test
./hfp_ag_client_test
./hfp_hf_parser_test

View File

@ -117,7 +117,7 @@ static void introduce_bad_frames_to_wav_file(const char * in_filename, const cha
}
static void process_wav_file_with_plc(const char * in_filename, const char * out_filename){
printf("\nProcess %s -> %s\n", in_filename, out_filename);
// printf("\nProcess %s -> %s\n", in_filename, out_filename);
btstack_cvsd_plc_init(&plc_state);
wav_writer_open(out_filename, 1, 8000);
wav_reader_open(in_filename);
@ -133,10 +133,10 @@ static void process_wav_file_with_plc(const char * in_filename, const char * out
}
static void mark_bad_frames_wav_file(const char * in_filename, const char * out_filename){
printf("\nMark bad frame %s -> %s\n", in_filename, out_filename);
// printf("\nMark bad frame %s -> %s\n", in_filename, out_filename);
btstack_cvsd_plc_init(&plc_state);
wav_writer_open(out_filename, 1, 8000);
wav_reader_open(in_filename);
CHECK_EQUAL(wav_writer_open(out_filename, 1, 8000), 0);
CHECK_EQUAL(wav_reader_open(in_filename), 0);
while (wav_reader_read_int8(audio_samples_per_frame, audio_frame_in)){
int8_t audio_frame_out[audio_samples_per_frame];
@ -161,31 +161,31 @@ TEST(CVSD_PLC, CountEqBytes){
TEST(CVSD_PLC, TestLiveWavFile){
int corruption_step = 10;
introduce_bad_frames_to_wav_file("data/input/sco_input.wav", "data/sco_input.wav", 0);
introduce_bad_frames_to_wav_file("data/input/sco_input.wav", "data/sco_input_with_bad_frames.wav", corruption_step);
introduce_bad_frames_to_wav_file("data/sco_input.wav", "results/sco_input.wav", 0);
introduce_bad_frames_to_wav_file("data/sco_input.wav", "results/sco_input_with_bad_frames.wav", corruption_step);
mark_bad_frames_wav_file("data/sco_input.wav", "data/sco_input_detected_frames.wav");
process_wav_file_with_plc("data/sco_input.wav", "data/sco_input_after_plc.wav");
process_wav_file_with_plc("data/sco_input_with_bad_frames.wav", "data/sco_input_with_bad_frames_after_plc.wav");
mark_bad_frames_wav_file("results/sco_input.wav", "results/sco_input_detected_frames.wav");
process_wav_file_with_plc("results/sco_input.wav", "results/sco_input_after_plc.wav");
process_wav_file_with_plc("results/sco_input_with_bad_frames.wav", "results/sco_input_with_bad_frames_after_plc.wav");
}
TEST(CVSD_PLC, TestFanfareFile){
int corruption_step = 10;
introduce_bad_frames_to_wav_file("data/input/fanfare_mono.wav", "data/fanfare_mono.wav", 0);
introduce_bad_frames_to_wav_file("data/fanfare_mono.wav", "data/fanfare_mono_with_bad_frames.wav", corruption_step);
introduce_bad_frames_to_wav_file("data/input/fanfare_mono.wav", "results/fanfare_mono.wav", 0);
introduce_bad_frames_to_wav_file("results/fanfare_mono.wav", "results/fanfare_mono_with_bad_frames.wav", corruption_step);
mark_bad_frames_wav_file("data/fanfare_mono.wav", "data/fanfare_mono_detected_frames.wav");
process_wav_file_with_plc("data/fanfare_mono.wav", "data/fanfare_mono_after_plc.wav");
process_wav_file_with_plc("data/fanfare_mono_with_bad_frames.wav", "data/fanfare_mono_with_bad_frames_after_plc.wav");
mark_bad_frames_wav_file("results/fanfare_mono.wav", "results/fanfare_mono_detected_frames.wav");
process_wav_file_with_plc("results/fanfare_mono.wav", "results/fanfare_mono_after_plc.wav");
process_wav_file_with_plc("results/fanfare_mono_with_bad_frames.wav", "results/fanfare_mono_with_bad_frames_after_plc.wav");
}
TEST(CVSD_PLC, TestSineWave){
int corruption_step = 10;
create_sine_wav("data/sine_test.wav");
introduce_bad_frames_to_wav_file("data/sine_test.wav", "data/sine_test_with_bad_frames.wav", corruption_step);
create_sine_wav("results/sine_test.wav");
introduce_bad_frames_to_wav_file("results/sine_test.wav", "results/sine_test_with_bad_frames.wav", corruption_step);
process_wav_file_with_plc("data/sine_test.wav", "data/sine_test_after_plc.wav");
process_wav_file_with_plc("data/sine_test_with_bad_frames.wav", "data/sine_test_with_bad_frames_after_plc.wav");
process_wav_file_with_plc("results/sine_test.wav", "results/sine_test_after_plc.wav");
process_wav_file_with_plc("results/sine_test_with_bad_frames.wav", "results/sine_test_with_bad_frames_after_plc.wav");
}
int main (int argc, const char * argv[]){