port: add posix-h4-nxp

This commit is contained in:
Matthias Ringwald 2022-07-07 00:03:59 +02:00
parent f37aba7b8c
commit cc528b9d66
9 changed files with 1003 additions and 2 deletions

View File

@ -12,7 +12,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- HCI_ACL_CHUNK_SIZE_ALIGNMENT allows to keep HCI transport writes aligned
- GAP: support additional LE PHYs for scanning and outgoing connections
- HFP: provide SCO packet types and rx/tx packet lengths in HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED
- Port for Renesas RA6M4 with DA14531
- example: gatt_streamer_server and le_streamer_client report DLE and PHY changes
- gatt_client: queue requests with gatt_client_request_to_send_gatt_query and gatt_client_request_to_write_without_response
- esp32: warn about unsuitable sdkconfig
@ -20,6 +19,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- esp32: allow to disable default audio i2s driver via component config
- esp32: support esp-idf v5.x audio driver
- esp32: btstack_stdio_init configures buffered output, required for stdin support
- nxp: support for bootloader version v1, e.g. NXP 88W8997
- Port for Renesas RA6M4 with DA14531
- Port for NXP Controller on POSIX (posix-h4-nxp)
## Removed
- AVDTP Source: avdtp_source_stream_send_media_payload, use avdtp_source_stream_send_media_payload_rtp instead
@ -39,12 +41,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Changed
- GAP: add gap_set_peer_privacy_mode with default LE_PRIVACY_MODE_DEVICE
- bluetooth: indicated identity address in resolved address type names
- chipset/bcm: look for PatchRAM file DEVICE_NAME...hcd
- btstack_audio: added get_samplerate function to help with audio sample rate synchronization
- btstack_flash_bank: write empty tag instead of overwriting existing tag with ENABLE_TLV_FLASH_WRITE_ONCE
- esp32: drop support for Makefile projects from esp-idf 3.x
- esp32: replace deprecated btstack_run_loop_freertos API calls
- sco_demo_util: replace hfp_msbc by hfp_codec
- chipset/bcm: look for PatchRAM file DEVICE_NAME...hcd
## Release v1.5.5

View File

@ -0,0 +1,302 @@
/*
* Copyright (C) 2023 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 BLUEKITCHEN
* GMBH 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
*
*/
#define BTSTACK_FILE__ "btstack_chipset_nxp.c"
#include "btstack_chipset_nxp.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include <stdio.h>
#ifdef _MSC_VER
// ignore deprecated warning for fopen
#pragma warning(disable : 4996)
#endif
// Firmware download protocol constants
#define NXP_V1_FW_REQ_PKT 0xa5
#define NXP_V1_CHIP_VER_PKT 0xaa
#define NXP_V3_FW_REQ_PKT 0xa7
#define NXP_V3_CHIP_VER_PKT 0xab
#define NXP_ACK_V1 0x5a
#define NXP_NAK_V1 0xbf
#define NXP_ACK_V3 0x7a
#define NXP_NAK_V3 0x7b
#define NXP_CRC_ERROR_V3 0x7c
// chip ids
#define NXP_CHIP_ID_W9098 0x5c03
#define NXP_CHIP_ID_IW416 0x7201
#define NXP_CHIP_ID_IW612 0x7601
#define NXP_MAX_RESEND_COUNT 5
// prototypes
static void nxp_w4_fw_req(void);
static void nxp_done(void);
static void nxp_prepare_chunk(void);
static void nxp_send_chunk(btstack_timer_source_t * ts);
static void nxp_done_with_status(uint8_t status);
// globals
static void (*nxp_download_complete)(uint8_t status);
static const btstack_uart_t * nxp_uart_driver;
static btstack_timer_source_t nxp_timer;
static bool nxp_have_firmware;
static const uint8_t * nxp_fw_data;
static uint32_t nxp_fw_size;
static uint32_t nxp_fw_offset;
static uint8_t nxp_response_buffer[5];
static const uint8_t nxp_ack_buffer_v1[] = {NXP_ACK_V1 };
static const uint8_t nxp_ack_buffer_v3[] = {NXP_ACK_V3, 0x92 };
static uint16_t nxp_fw_request_len;
static uint8_t nxp_fw_resend_count;
static uint8_t nxp_output_buffer[2048 + 1];
#ifdef HAVE_POSIX_FILE_IO
static char nxp_firmware_path[1000];
static FILE * nxp_firmware_file;
static void nxp_load_firmware(void) {
if (nxp_firmware_file == NULL){
log_info("chipset-bcm: open file %s", nxp_firmware_path);
nxp_firmware_file = fopen(nxp_firmware_path, "rb");
if (nxp_firmware_file != NULL){
nxp_have_firmware = true;
}
}
}
static uint16_t nxp_read_firmware(uint16_t bytes_to_read, uint8_t * buffer) {
size_t bytes_read = fread(buffer, 1, bytes_to_read, nxp_firmware_file);
return bytes_read;
}
static void nxp_unload_firmware(void) {
btstack_assert(nxp_firmware_file != NULL);
fclose(nxp_firmware_file);
nxp_firmware_file = NULL;
}
#else
void nxp_load_firmware(void){
nxp_have_firmware = true;
}
// read bytes from firmware file
static uint16_t nxp_read_firmware(uint16_t bytes_to_read, uint8_t * buffer){
if (nxp_fw_request_len > nxp_fw_size - nxp_fw_offset){
printf("fw_request_len %u > remaining file len %u\n", nxp_fw_request_len, nxp_fw_size - nxp_fw_offset);
return nxp_fw_size - nxp_fw_offset;
}
memcpy(buffer, &nxp_fw_data[nxp_fw_offset], bytes_to_read);
nxp_fw_offset += nxp_fw_request_len;
return bytes_to_read;
}
static void nxp_unload_firmware(void) {
}
#endif
// first two uint16_t should xor to 0xffff
static bool nxp_valid_packet(void){
switch (nxp_response_buffer[0]){
case NXP_V1_FW_REQ_PKT:
case NXP_V1_CHIP_VER_PKT:
return ((nxp_response_buffer[1] ^ nxp_response_buffer[3]) == 0xff) && ((nxp_response_buffer[2] ^ nxp_response_buffer [4]) == 0xff);
case NXP_V3_FW_REQ_PKT:
case NXP_V3_CHIP_VER_PKT:
// TODO: check crc-7
return true;
default:
return false;
}
}
static void nxp_start(){
// start to read
nxp_fw_resend_count = 0;
nxp_fw_offset = 0;
nxp_have_firmware = false;
nxp_uart_driver->set_block_received(&nxp_w4_fw_req);
nxp_uart_driver->receive_block(nxp_response_buffer, 5);
log_info("nxp_start: wait for 0x%02x", NXP_V1_FW_REQ_PKT);
}
static void nxp_send_ack_v1(void (*done_handler)(void)){
nxp_uart_driver->set_block_sent(done_handler);
nxp_uart_driver->send_block(nxp_ack_buffer_v1, sizeof(nxp_ack_buffer_v1));
}
static void nxp_send_ack_v3(void (*done_handler)(void)){
nxp_uart_driver->set_block_sent(done_handler);
nxp_uart_driver->send_block(nxp_ack_buffer_v3, sizeof(nxp_ack_buffer_v3));
}
static void nxp_prepare_chunk(void){
// delay chunk send by 5 ms
btstack_run_loop_set_timer_handler(&nxp_timer, nxp_send_chunk);
btstack_run_loop_set_timer(&nxp_timer, 5);
btstack_run_loop_add_timer(&nxp_timer);
}
static void nxp_dummy(void){
}
static void nxp_w4_fw_req(void){
// validate checksum
if (nxp_valid_packet()){
printf("RECV: ");
printf_hexdump(nxp_response_buffer, sizeof(nxp_response_buffer));
switch (nxp_response_buffer[0]){
case NXP_V1_FW_REQ_PKT:
// get firmware
if (nxp_have_firmware == false){
nxp_load_firmware();
}
if (nxp_have_firmware == false){
printf("No firmware found, abort\n");
break;
}
nxp_fw_request_len = little_endian_read_16(nxp_response_buffer, 1);
printf("RECV: NXP_V1_FW_REQ_PKT, len %u\n", nxp_fw_request_len);
if (nxp_fw_request_len == 0){
printf("last chunk sent!\n");
nxp_unload_firmware();
nxp_send_ack_v1(nxp_done);
} else {
nxp_send_ack_v1(nxp_prepare_chunk);
}
return;
case NXP_V1_CHIP_VER_PKT:
printf("RECV: NXP_V1_CHIP_VER_PKT, id = 0x%x02, revision = 0x%02x\n", nxp_response_buffer[0], nxp_response_buffer[1]);
nxp_send_ack_v1(nxp_dummy);
break;
case NXP_V3_CHIP_VER_PKT:
printf("RECV: NXP_V3_CHIP_VER_PKT , id = 0x%04x, loader 0x%02x\n", little_endian_read_16(nxp_response_buffer, 1), nxp_response_buffer[3]);
nxp_send_ack_v3(nxp_dummy);
break;
default:
printf("RECV: unknown packet type 0x%02x\n", nxp_response_buffer[0]);
break;
}
nxp_start();
}
// drop byte and read another byte
memmove(&nxp_response_buffer[0], &nxp_response_buffer[1], 4);
nxp_uart_driver->receive_block(&nxp_response_buffer[4], 1);
}
static void nxp_send_chunk(btstack_timer_source_t * ts){
if ((nxp_fw_request_len & 1) == 0){
// update sttate
nxp_fw_offset += nxp_fw_request_len;
nxp_fw_resend_count = 0;
// read next firmware chunk
uint16_t bytes_read = nxp_read_firmware(nxp_fw_request_len, nxp_output_buffer);
if (bytes_read < nxp_fw_request_len){
printf("only %u of %u bytes available, abort.\n", bytes_read, nxp_fw_request_len);
nxp_done_with_status(ERROR_CODE_HARDWARE_FAILURE);
return;
}
} else {
// resend last chunk if request len is odd
if (nxp_fw_resend_count >= NXP_MAX_RESEND_COUNT){
printf("Resent last block %u times, abort.", nxp_fw_resend_count);
nxp_done_with_status(ERROR_CODE_HARDWARE_FAILURE);
return;
}
nxp_fw_resend_count++;
}
printf("SEND: firmware %08x - %u bytes (%u. try)\n", nxp_fw_offset, nxp_fw_request_len, nxp_fw_resend_count + 1);
nxp_uart_driver->set_block_received(&nxp_w4_fw_req);
nxp_uart_driver->receive_block(nxp_response_buffer, 5);
nxp_uart_driver->set_block_sent(nxp_dummy);
nxp_uart_driver->send_block(nxp_output_buffer, nxp_fw_request_len);
}
static void nxp_done_with_status(uint8_t status){
printf("DONE!\n");
(*nxp_download_complete)(status);
}
static void nxp_done(void){
nxp_done_with_status(ERROR_CODE_SUCCESS);
}
void btstack_chipset_nxp_set_v1_firmware_path(const char * firmware_path){
btstack_strcpy(nxp_firmware_path, sizeof(nxp_firmware_path), firmware_path);
}
void btstack_chipset_nxp_set_firmware(const uint8_t * fw_data, uint32_t fw_size){
nxp_fw_data = fw_data;
nxp_fw_size = fw_size;
}
void btstack_chipset_nxp_download_firmware_with_uart(const btstack_uart_t *uart_driver, void (*done)(uint8_t status)) {
nxp_uart_driver = uart_driver;
nxp_download_complete = done;
int res = nxp_uart_driver->open();
if (res) {
log_error("uart_block init failed %u", res);
nxp_download_complete(res);
}
nxp_start();
}
static void chipset_init(const void *transport_config){
UNUSED(transport_config);
}
static btstack_chipset_t btstack_chipset_nxp = {
.name = "NXP",
.init = chipset_init,
.next_command = NULL,
.set_baudrate_command = NULL,
.set_bd_addr_command = NULL
};
const btstack_chipset_t *btstack_chipset_nxp_instance(void){
return &btstack_chipset_nxp;
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2023 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 BLUEKITCHEN
* GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
/*
* btstack_chipset_nxp
*
* Adapter to use NXP/Marvel-based chipsets with BTstack
*/
#ifndef BTSTACK_CHIPSET_MARVEL_H
#define BTSTACK_CHIPSET_MARVEL_H
#if defined __cplusplus
extern "C" {
#endif
#include "bluetooth.h"
#include "btstack_chipset.h"
#include "btstack_uart.h"
#include <stdint.h>
/**
* @brief Set path to firmware file for Controller with v1 bootloader, e.g. 88W8997
* @note used for systems with HAVE_POSIX_FILE_IO
* @param path
*/
void btstack_chipset_nxp_set_v1_firmware_path(const char * firmware_path);
/**
* @brieft Provide firmware as data
* @note used for systems without HAVE_POSIX_FILE_IO
* @param fw_data
* @param fw_size
*/
void btstack_chipset_nxp_set_firmware(const uint8_t * fw_data, uint32_t fw_size);
/**
* @brief Download firmware via uart_driver
* @param uart_driver -- already initialized
* @param done callback. 0 = Success
*/
void btstack_chipset_nxp_download_firmware_with_uart(const btstack_uart_t *uart_driver, void (*done)(uint8_t status));
/**
* Get chipset instance for NXP chipsets
*/
const btstack_chipset_t *btstack_chipset_nxp_instance(void);
#if defined __cplusplus
}
#endif
#endif // BTSTACK_CHIPSET_NXP_H

19
chipset/nxp/nxp.cmake Normal file
View File

@ -0,0 +1,19 @@
# CMake file to download and UART firmware files for NXP Bluetooth/Wifi Controllers
# 88W8997
set(NXP_8997_PATH https://github.com/nxp-imx/imx-firmware/raw/lf-6.1.1_1.0.0/nxp/FwImage_8997)
set(NXP_8997_FILE uartuart8997_bt_v4.bin)
message("NXP 88W8997: Download ${NXP_8997_FILE}")
file(DOWNLOAD ${NXP_8997_PATH}/${NXP_8997_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${NXP_8997_FILE})
# IW416
set(NXP_IW416_PATH https://github.com/nxp-imx/imx-firmware/raw/lf-6.1.1_1.0.0/nxp/FwImage_IW416_SD)
set(NXP_IW416_FILE uartiw416_bt_v0.bin)
message("NXP IW416: Download ${NXP_IW416_FILE}")
file(DOWNLOAD ${NXP_IW416_PATH}/${NXP_IW416_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${NXP_IW416_FILE})
# IW612
set(NXP_IW612_PATH https://github.com/nxp-imx/imx-firmware/raw/lf-6.1.1_1.0.0/nxp/FwImage_IW612_SD)
set(NXP_IW612_FILE uartspi_n61x_v1.bin.se)
message("NXP IW612: Download ${NXP_IW612_FILE}")
file(DOWNLOAD ${NXP_IW612_PATH}/${NXP_IW612_PATH} ${CMAKE_CURRENT_BINARY_DIR}/${NXP_IW612_FILE})

102
port/posix-h4-nxp/.gitignore vendored Normal file
View File

@ -0,0 +1,102 @@
a2dp_sink_demo
a2dp_source_demo
ancs_client_demo
ancs_client_demo.h
att_delayed_read_response
att_delayed_read_response.h
att_delayed_response
att_delayed_response.h
audio_duplex
avrcp_browsing_client
BCM43430A1.hcd
ble_central_test
ble_peripheral
ble_peripheral_sm_minimal
ble_peripheral_test
bluetooth_init_cc256*
bluetooth_init_cc2560_2.44.c
bluetooth_init_cc2560a_2.14.c
bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c
bluetooth_init_cc2564_2.14.c
bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c
bluetooth_init_cc2567_2.4.c
bluetooth_init_cc2567_2.8.c
bnep_test
classic_test
dut_mode_classic
gap_dedicated_bonding
gap_inquiry
gap_inquiry_and_bond
gap_le_advertisements
gap_link_keys
gatt_battery_query
gatt_battery_query.h
gatt_browser
gatt_browser.h
gatt_counter
gatt_counter.h
gatt_heart_rate_client
gatt_streamer_server
gatt_streamer_server.h
hfp_ag_demo
hfp_hf_demo
hid_host_demo
hid_keyboard_demo
hid_mouse_demo
hog_keyboard_demo
hog_keyboard_demo.h
hog_mouse_demo
hog_mouse_demo.h
hsp_ag_demo
hsp_ag_test
hsp_hs_demo
hsp_hs_test
l2cap_test
le_counter
le_counter.h
le_credit_based_flow_control_mode_client
le_credit_based_flow_control_mode_server
le_credit_based_flow_control_mode_server.h
le_streamer
le_streamer.h
le_streamer_and_counter_client
le_streamer_and_counter_client.h
le_streamer_client
led_counter
mesh_node_demo
mesh_node_demo.h
mod_player
nordic_spp_le_counter
nordic_spp_le_counter.h
nordic_spp_le_streamer
nordic_spp_le_streamer.h
pan_lwip_http_server
pbap_client_demo
profile.h
sco_input.msbc
sco_input.wav
sco_output.msbc
sdp_bnep_query
sdp_general_query
sdp_rfcomm_query
sine_player
sm_pairing_central
sm_pairing_central.h
sm_pairing_peripheral
sm_pairing_peripheral.h
spp_and_gatt_counter
spp_and_gatt_counter.h
spp_and_gatt_streamer
spp_and_gatt_streamer.h
spp_and_le_counter
spp_and_le_counter.h
spp_and_le_streamer
spp_and_le_streamer.h
spp_counter
spp_streamer
spp_streamer_client
TIInit_12.10.28.c
TIInit_12.8.32.c
ublox_spp_le_counter
ublox_spp_le_counter.h
CC256*

View File

@ -0,0 +1,177 @@
cmake_minimum_required (VERSION 3.18)
project(BTstack-posix-nxp)
SET(BTSTACK_ROOT ${CMAKE_SOURCE_DIR}/../..)
# extra compiler warnings
if ("${CMAKE_C_COMPILER_ID}" MATCHES ".*Clang.*")
# using Clang
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused-variable -Wswitch-default -Werror")
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
# using GCC
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused-but-set-variable -Wunused-variable -Wswitch-default -Werror")
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
endif()
# pkgconfig
find_package(PkgConfig QUIET)
# portaudio
if (PgConfig_FOUND)
pkg_check_modules(PORTAUDIO REQUIRED portaudio-2.0)
if(PORTAUDIO_FOUND)
message("HAVE_PORTAUDIO")
include_directories(${PORTAUDIO_INCLUDE_DIRS})
link_directories(${PORTAUDIO_LIBRARY_DIRS})
link_libraries(${PORTAUDIO_LIBRARIES})
# CMake 3.12 - add_compile_definitions(HAVE_PORTAUDIO)
SET(CMAKE_C_FLAGS "-DHAVE_PORTAUDIO")
endif()
endif()
# to generate .h from .gatt files
find_package (Python REQUIRED COMPONENTS Interpreter)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# local dir for btstack_config.h after build dir to avoid using .h from Makefile
include_directories(.)
include_directories(${BTSTACK_ROOT}/3rd-party/micro-ecc)
include_directories(${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include)
include_directories(${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include)
include_directories(${BTSTACK_ROOT}/3rd-party/lc3-google/include)
include_directories(${BTSTACK_ROOT}/3rd-party/md5)
include_directories(${BTSTACK_ROOT}/3rd-party/hxcmod-player)
include_directories(${BTSTACK_ROOT}/3rd-party/hxcmod-player/mod)
include_directories(${BTSTACK_ROOT}/3rd-party/lwip/core/src/include)
include_directories(${BTSTACK_ROOT}/3rd-party/lwip/dhcp-server)
include_directories(${BTSTACK_ROOT}/3rd-party/rijndael)
include_directories(${BTSTACK_ROOT}/3rd-party/yxml)
include_directories(${BTSTACK_ROOT}/3rd-party/tinydir)
include_directories(${BTSTACK_ROOT}/src)
include_directories(${BTSTACK_ROOT}/chipset/nxp)
include_directories(${BTSTACK_ROOT}/platform/embedded)
include_directories(${BTSTACK_ROOT}/platform/lwip)
include_directories(${BTSTACK_ROOT}/platform/lwip/port)
include_directories(${BTSTACK_ROOT}/platform/posix)
file(GLOB SOURCES_SRC "${BTSTACK_ROOT}/src/*.c" "${BTSTACK_ROOT}/example/sco_demo_util.c")
file(GLOB SOURCES_BLE "${BTSTACK_ROOT}/src/ble/*.c")
file(GLOB SOURCES_BLUEDROID "${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce/*.c" "${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce/*.c")
file(GLOB SOURCES_CLASSIC "${BTSTACK_ROOT}/src/classic/*.c")
file(GLOB SOURCES_MESH "${BTSTACK_ROOT}/src/mesh/*.c")
file(GLOB SOURCES_GATT "${BTSTACK_ROOT}/src/ble/gatt-service/*.c")
file(GLOB SOURCES_UECC "${BTSTACK_ROOT}/3rd-party/micro-ecc/uECC.c")
file(GLOB SOURCES_HXCMOD "${BTSTACK_ROOT}/3rd-party/hxcmod-player/*.c" "${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods/*.c")
file(GLOB SOURCES_MD5 "${BTSTACK_ROOT}/3rd-party/md5/md5.c")
file(GLOB SOURCES_RIJNDAEL "${BTSTACK_ROOT}/3rd-party/rijndael/rijndael.c")
file(GLOB SOURCES_YXML "${BTSTACK_ROOT}/3rd-party/yxml/yxml.c")
file(GLOB SOURCES_POSIX "${BTSTACK_ROOT}/platform/posix/*.c")
file(GLOB SOURCES_NXP "${BTSTACK_ROOT}/chipset/nxp/*.c")
file(GLOB SOURCES_LC3_GOOGLE "${BTSTACK_ROOT}/3rd-party/lc3-google/src/*.c")
file(GLOB SOURCES_PORT "*.c")
set(LWIP_CORE_SRC
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/def.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/inet_chksum.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/init.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ip.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/mem.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/memp.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/netif.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/pbuf.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/tcp.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/tcp_in.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/tcp_out.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/timeouts.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/udp.c
)
set (LWIP_IPV4_SRC
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/acd.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/dhcp.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/etharp.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/icmp.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/ip4.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/ip4_addr.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/core/ipv4/ip4_frag.c
)
set (LWIP_NETIF_SRC
${BTSTACK_ROOT}/3rd-party/lwip/core/src/netif/ethernet.c
)
set (LWIP_HTTPD
${BTSTACK_ROOT}/3rd-party/lwip/core/src/apps/http/altcp_proxyconnect.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/apps/http/fs.c
${BTSTACK_ROOT}/3rd-party/lwip/core/src/apps/http/httpd.c
)
set (LWIP_DHCPD
${BTSTACK_ROOT}/3rd-party/lwip/dhcp-server/dhserver.c
)
set (LWIP_PORT
${BTSTACK_ROOT}/platform/lwip/port/sys_arch.c
${BTSTACK_ROOT}//platform/lwip/bnep_lwip.c
)
set (SOURCES_LWIP ${LWIP_CORE_SRC} ${LWIP_IPV4_SRC} ${LWIP_NETIF_SRC} ${LWIP_HTTPD} ${LWIP_DHCPD} ${LWIP_PORT})
file(GLOB SOURCES_BLE_OFF "${BTSTACK_ROOT}/src/ble/le_device_db_memory.c")
list(REMOVE_ITEM SOURCES_BLE ${SOURCES_BLE_OFF})
file(GLOB SOURCES_POSIX_OFF "${BTSTACK_ROOT}/platform/posix/le_device_db_fs.c")
list(REMOVE_ITEM SOURCES_POSIX ${SOURCES_POSIX_OFF})
set(SOURCES
${SOURCES_BLE}
${SOURCES_BLUEDROID}
${SOURCES_CLASSIC}
${SOURCES_GATT}
${SOURCES_HXCMOD}
${SOURCES_LIBUSB}
${SOURCES_MD5}
${SOURCES_MESH}
${SOURCES_NXP}
${SOURCES_PORT}
${SOURCES_RIJNDAEL}
${SOURCES_SRC}
${SOURCES_CSR}
${SOURCES_UECC}
${SOURCES_POSIX}
${SOURCES_YXML}
)
list(SORT SOURCES)
# create static lib
add_library(btstack STATIC ${SOURCES})
# Add NXP Support
include(${BTSTACK_ROOT}/chipset/nxp/nxp.cmake)
# get list of examples, skipping mesh_node_demo
include(../../example/CMakeLists.txt)
set (EXAMPLES ${EXAMPLES_GENERAL} ${EXAMPLES_CLASSIC_ONLY} ${EXAMPLES_LE_ONLY} ${EXAMPLES_DUAL_MODE})
list(REMOVE_DUPLICATES EXAMPLES)
list(REMOVE_ITEM EXAMPLES "mesh_node_demo")
# create targets
foreach(EXAMPLE ${EXAMPLES})
# get c file
set (SOURCES_EXAMPLE ${BTSTACK_ROOT}/example/${EXAMPLE}.c)
# add GATT DB creation
if ( "${EXAMPLES_GATT_FILES}" MATCHES ${EXAMPLE} )
message("example ${EXAMPLE} -- with GATT DB")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLE}.h
DEPENDS ${BTSTACK_ROOT}/example/${EXAMPLE}.gatt
COMMAND ${Python_EXECUTABLE}
ARGS ${BTSTACK_ROOT}/tool/compile_gatt.py ${BTSTACK_ROOT}/example/${EXAMPLE}.gatt ${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLE}.h
)
list(APPEND SOURCES_EXAMPLE ${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLE}.h)
else()
message("example ${EXAMPLE}")
endif()
add_executable(${EXAMPLE} ${SOURCES_EXAMPLE})
target_link_libraries(${EXAMPLE} btstack)
endforeach(EXAMPLE)

View File

@ -0,0 +1,31 @@
# BTstack Port for POSIX Systems with NXP/Marvel H4 Bluetooth Controller
## Configuration
Most Bluetooth Bluetooth Controllers connected via UART/H4 require some special configuration, e.g. to set the UART baud rate, and/or require firmware patches during startup.
In this port, we've show how a NXP/Marvell Controller can be configured for use with BTstack. It's unclear if the required firmware file for older Controllers,
e.g. 88W8997, can be detected during the firmware upload. This port selects the firmware for NXP 88W8997.
For newer Controllers, e.g. IW416 or IW612, the firmware can be selected automatically.
## Compilation
BTstack's posix-h4-nxp port does not have additional dependencies. You can directly run cmake and then your default build system. E.g. with Ninja:
mkdir build
cd build
cmake -G Ninja ..
ninja
## Running the examples
Please reset the Controller first. On start, BTstack prints the path to the packet log.
$ ./gatt_counter
Packet Log: /tmp/hci_dump.pklg
BTstack counter 0001
BTstack up and running on 00:1A:7D:DA:71:13.
## ToDo
- increase baud rate for firmware upload
- skip firmware upload if firmware already present
- increase baud rate for application
- send SCO audio

View File

@ -0,0 +1,63 @@
//
// btstack_config.h for generic POSIX H4 port
//
// Documentation: https://bluekitchen-gmbh.com/btstack/#how_to/
//
#ifndef BTSTACK_CONFIG_H
#define BTSTACK_CONFIG_H
// Port related features
#define HAVE_ASSERT
#define HAVE_BTSTACK_STDIN
#define HAVE_EM9304_PATCH_CONTAINER
#define HAVE_MALLOC
#define HAVE_POSIX_FILE_IO
#define HAVE_POSIX_TIME
// BTstack features that can be enabled
#define ENABLE_ATT_DELAYED_RESPONSE
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
#define ENABLE_HFP_WIDE_BAND_SPEECH
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
#define ENABLE_LE_CENTRAL
#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_PRINTF_HEXDUMP
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
#define ENABLE_SOFTWARE_AES128
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof benep heade, avoid memcpy
#define NVM_NUM_DEVICE_DB_ENTRIES 16
#define NVM_NUM_LINK_KEYS 16
// Mesh Configuration
#define ENABLE_MESH
#define ENABLE_MESH_ADV_BEARER
#define ENABLE_MESH_GATT_BEARER
#define ENABLE_MESH_PB_ADV
#define ENABLE_MESH_PB_GATT
#define ENABLE_MESH_PROVISIONER
#define ENABLE_MESH_PROXY_SERVER
#define MAX_NR_MESH_SUBNETS 2
#define MAX_NR_MESH_TRANSPORT_KEYS 16
#define MAX_NR_MESH_VIRTUAL_ADDRESSES 16
// allow for one NetKey update
#define MAX_NR_MESH_NETWORK_KEYS (MAX_NR_MESH_SUBNETS+1)
#endif

218
port/posix-h4-nxp/main.c Normal file
View File

@ -0,0 +1,218 @@
/*
* Copyright (C) 2023 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 BLUEKITCHEN
* GMBH 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
*
*/
#define BTSTACK_FILE__ "main.c"
// *****************************************************************************
//
// minimal setup for HCI code
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "btstack_config.h"
#include "ble/le_device_db_tlv.h"
#include "btstack_chipset_nxp.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_memory.h"
#include "btstack_run_loop_posix.h"
#include "btstack_signal.h"
#include "btstack_stdin.h"
#include "btstack_tlv_posix.h"
#include "btstack_uart.h"
#include "classic/btstack_link_key_db_tlv.h"
#include "hci.h"
#include "hci_dump.h"
#include "hci_dump_posix_fs.h"
#include "hci_transport_h4.h"
#define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl;
static btstack_tlv_posix_t tlv_context;
static bd_addr_t local_addr;
static int main_argc;
static const char ** main_argv;
static const btstack_uart_t * uart_driver;
static btstack_uart_config_t uart_config;
// shutdown
static bool shutdown_triggered;
int btstack_main(int argc, const char * argv[]);
static void local_version_information_handler(uint8_t * packet);
static hci_transport_config_uart_t transport_config = {
HCI_TRANSPORT_CONFIG_UART,
115200,
0, // main baudrate
0, // flow control
NULL,
};
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;
switch (hci_event_packet_get_type(packet)){
case BTSTACK_EVENT_STATE:
switch(btstack_event_state_get_state(packet)){
case HCI_STATE_WORKING:
gap_local_bd_addr(local_addr);
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
btstack_strcpy(tlv_db_path, sizeof(tlv_db_path), TLV_DB_PATH_PREFIX);
btstack_strcat(tlv_db_path, sizeof(tlv_db_path), bd_addr_to_str_with_delimiter(local_addr, '-'));
btstack_strcat(tlv_db_path, sizeof(tlv_db_path), TLV_DB_PATH_POSTFIX);
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path);
btstack_tlv_set_instance(tlv_impl, &tlv_context);
#ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif
#ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif
break;
case HCI_STATE_OFF:
btstack_tlv_posix_deinit(&tlv_context);
if (!shutdown_triggered) break;
// reset stdin
btstack_stdin_reset();
log_info("Good bye, see you.\n");
exit(0);
break;
default:
break;
}
break;
default:
break;
}
}
static void trigger_shutdown(void){
printf("CTRL-C - SIGINT received, shutting down..\n");
log_info("sigint_handler: shutting down");
shutdown_triggered = true;
hci_power_control(HCI_POWER_OFF);
}
static int led_state = 0;
void hal_led_toggle(void){
led_state = 1 - led_state;
printf("LED State %u\n", led_state);
}
static void nxp_phase2(uint8_t status){
if (status){
printf("Download firmware failed\n");
return;
}
printf("Phase 2: Main app\n");
// init HCI
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver);
hci_init(transport, (void*) &transport_config);
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// register callback for CTRL-c
btstack_signal_register_callback(SIGINT, &trigger_shutdown);
// setup app
btstack_main(main_argc, main_argv);
}
int main(int argc, const char * argv[]){
/// GET STARTED with BTstack ///
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
// log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path);
// pick serial port
transport_config.device_name = "/dev/tty.usbserial-A506WORJ"; // DVK-ST60-2230C / 88W8997
// transport_config.device_name = "/dev/tty.usbserial-FT1XBGIM"; // murata m.2 adapter
// accept path from command line
if (argc >= 3 && strcmp(argv[1], "-u") == 0){
transport_config.device_name = argv[2];
argc -= 2;
memmove((void *) &argv[1], &argv[3], (argc-1) * sizeof(char *));
}
printf("H4 device: %s\n", transport_config.device_name);
uart_driver = btstack_uart_posix_instance();
// extract UART config from transport config
uart_config.baudrate = transport_config.baudrate_init;
uart_config.flowcontrol = transport_config.flowcontrol;
uart_config.device_name = transport_config.device_name;
uart_driver->init(&uart_config);
main_argc = argc;
main_argv = argv;
const char * firmware_v1 = "uartuart8997_bt_v4.bin";
printf("Phase 1: Download firmware '%s'\n", firmware_v1);
btstack_chipset_nxp_set_v1_firmware_path(firmware_v1);
btstack_chipset_nxp_download_firmware_with_uart(uart_driver, &nxp_phase2);
// go
btstack_run_loop_execute();
return 0;
}