Merge branch 'develop' of https://github.com/bluekitchen/btstack into develop

This commit is contained in:
Milanka Ringwald 2018-09-24 10:57:20 +02:00
commit 1c5286ef85
47 changed files with 1911 additions and 144 deletions

View File

@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- GATT Client: stop timer on disconnect - fixes use after free / crash
- L2CAP: Use valid signaling identifier for L2CAP Connection Parameter Update Request
### Added
- A2DP Source: Support stream reconfiguration (a2dp_source_reconfigure_stream_sampling_frequency)
## Changes August 2018
### Added

View File

@ -62,8 +62,10 @@ No build server | [posix-h4-da14585](https://github.com/bluekitchen/btstack/tree
No build server | [posix-h5](https://github.com/bluekitchen/btstack/tree/develop/port/posix-h5) | Unix-based system connected to Bluetooth module via H5 over serial port
No build server | [posix-h5-bcm](https://github.com/bluekitchen/btstack/tree/develop/port/posix-h5) | Unix-based system connected to Broadcom/Cypress Bluetooth module via H5 over serial port
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badges/port-libusb-develop.svg">](https://buildbot.bluekitchen-gmbh.com/btstack/#/builders/port-libusb-develop) | [libusb](https://github.com/bluekitchen/btstack/tree/develop/port/libusb) | Unix-based system with dedicated USB Bluetooth dongle
No build server | [libusb-intel](https://github.com/bluekitchen/btstack/tree/develop/port/libusb-inttel) | Unix-based system with Intel Wireless 8260/8265 Controller
No build server | [windows-h4](https://github.com/bluekitchen/btstack/tree/develop/port/windows-h4) | Win32-based system connected to Bluetooth module via serial port
No build server | [windows-winusb](https://github.com/bluekitchen/btstack/tree/develop/port/windows-winusb) | Win32-based system with dedicated USB Bluetooth dongle
No build server | [windows-winusb-intel](https://github.com/bluekitchen/btstack/tree/develop/port/windows-winusb-intel) | Win32-based system with Intel Wireless 8260/8265 Controller
No build server | [raspi](https://github.com/bluekitchen/btstack/tree/develop/port/raspi) | Raspberry Pi 3 or Raspberry Pi Zero W with built-in BCM4343 Bluetooth/Wifi Controller
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badges/port-daemon-develop.svg">](https://buildbot.bluekitchen-gmbh.com/btstack/#/builders/port-daemon-develop) | [daemon](https://github.com/bluekitchen/btstack/tree/develop/port/daemon) | TCP and Unix domain named socket client-server architecture supporting multiple clients
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badges/java-develop.svg">](https://buildbot.bluekitchen-gmbh.com/btstack/#/builders/java-develop) | [java](https://github.com/bluekitchen/btstack/tree/develop/platform/daemon/binding/java) | Java wrapper for daemon
@ -84,6 +86,7 @@ Cypress CYW20704 | Dual mode | H4, H5, USB | Probably |
Dialog Semiconductor DA14581, DA14585 | LE | H4, SPI | n.a. | da14581 | Official HCI firmware used
Espressif ESP32 | Dual mode | VHCI | Not yet | | SoC with Bluetooth and Wifi
EM 9301, 9304 | LE | SPI | n.a. | em9301 | Custom HCI SPI implementation
Intel Dual Wireless 8260, 8265 | Dual mode | USB | Probably | intel | Firmware size: 400 kB
Nordic nRF | LE | H4 | n.a. | | Requires custom HCI firmware
STM STLC2500D | Classic | H4 | No (didn't try) | stlc2500d | Custom deep sleep management not supported
Toshiba TC35661 | Dual mode | H4 | No | tc3566 |

View File

@ -64,6 +64,7 @@ Dialog DA14585 | LE | H4, SPI | No | n.a.
Espressif ESP32 | Dual mode | VHCI | Yes | Not yet | Yes | Yes | | SoC with Bluetooth and Wifi
EM 9301 | LE | SPI, H4 | No | n.a. | No | No | em9301 | Custom HCI SPI implementation
EM 9304 | LE | SPI, H4 | Yes | n.a. | Yes | Yes | em9301 | Custom HCI SPI implementation
Intel Dual Wireless 8260, 8265 | Dual mode | USB | Yes | Probably | Don't know | Don't know | intel | Firmware size: 400 kB
Nordic nRF | LE | H4 | Fixed Random | n.a. | Yes | Yes | | Requires 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 | No | No | tc3566 | Only -007/009 models provide full HCI. See below
@ -173,6 +174,10 @@ EM9304 is used by the 'stm32-l053r8-em9304' port in BTstack. The port.c file als
**BTstack integration**: The common code for the EM9304 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.
## Intel Dual Wireless 8260, 8265
Wifi/Bluetooth combo cards mainly used in mobile computers. The Bluetooth part requires the upload of a firmware file and a configuration file. SCO, DLE, Multiple roles not tested.
## Nordic nRF5 series
The Single-Mode LE chipsets from the Nordic nRF5 series chipsets usually 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. Since the chipset can be programmed, it can also be loaded with a firmware that provides a regular HCI H4 interface for a Host.

2
chipset/intel/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.ddc
*.sfi

View File

@ -0,0 +1,28 @@
#
# Makefile to download firmware and config files for Intel Wireless chipsets from Linux firmware tree
#
# Supported:
# - Intel Wireless 8260
# - Intel Wireless 8265
LINUX_FIRMWARE_URL = https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/
INTEL_FILES = \
ibt-11-5.ddc \
ibt-11-5.sfi \
ibt-12-16.ddc \
ibt-12-16.sfi
all-intel: $(INTEL_FILES)
%.sfi:
@echo Downloading $@
@curl -O -L $(LINUX_FIRMWARE_URL)/intel/$@
%.ddc:
@echo Downloading $@
@curl -O -L $(LINUX_FIRMWARE_URL)/intel/$@
clean-intel:
rm -f $(INTEL_FILES)

View File

@ -0,0 +1,430 @@
#define __BTSTACK_FILE__ "btstack_chipset_intel_firmware.c"
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "btstack_chipset_intel_firmware.h"
#include "hci_cmd.h"
#include "bluetooth.h"
#include "hci_dump.h"
#include "btstack_event.h"
#include "btstack_debug.h"
#include "btstack_util.h"
#include "btstack_run_loop.h"
// Vendor specific structs
typedef struct {
uint8_t status;
uint8_t hw_platform;
uint8_t hw_variant;
uint8_t hw_revision;
uint8_t fw_variant;
uint8_t fw_revision;
uint8_t fw_build_num;
uint8_t fw_build_ww;
uint8_t fw_build_yy;
uint8_t fw_patch_num;
} intel_version_t;
typedef struct {
uint8_t status;
uint8_t otp_format;
uint8_t otp_content;
uint8_t otp_patch;
uint16_t dev_revid;
uint8_t secure_boot;
uint8_t key_from_hdr;
uint8_t key_type;
uint8_t otp_lock;
uint8_t api_lock;
uint8_t debug_lock;
bd_addr_t otp_bdaddr;
uint8_t min_fw_build_nn;
uint8_t min_fw_build_cw;
uint8_t min_fw_build_yy;
uint8_t limited_cce;
uint8_t unlocked_state;
} intel_boot_params_t;
// Vendor sepcific commands
static const hci_cmd_t hci_intel_read_version = {
0xfc05, ""
};
static const hci_cmd_t hci_intel_read_secure_boot_params = {
0xfc0d, ""
};
static const hci_cmd_t hci_intel_reset_param = {
0xfc01, "11111111"
};
static const hci_cmd_t hci_intel_set_event_mask = {
0xfc52, "11111111"
};
static const hci_cmd_t hci_intel_fc9f = {
0xfc9f, "1"
};
// state
const char * firmware_path = ".";
const hci_transport_t * transport;
static int state = 0;
static uint8_t hci_outgoing[300];
static uint8_t fw_buffer[300];
static uint8_t hw_variant;
static uint16_t dev_revid;
static FILE * fw_file;
static uint32_t fw_offset;
static void (*done)(int result);
// functions
static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){
hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size);
return transport->send_packet(packet_type, (uint8_t *) packet, size);
}
static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
uint8_t * packet = hci_outgoing;
uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
}
static int transport_send_cmd(const hci_cmd_t *cmd, ...){
va_list argptr;
va_start(argptr, cmd);
int res = transport_send_cmd_va_arg(cmd, argptr);
va_end(argptr);
return res;
}
static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint16_t len){
little_endian_store_16(hci_outgoing, 0, 0xfc09);
hci_outgoing[2] = 1 + len;
hci_outgoing[3] = fragment_type;
memcpy(&hci_outgoing[4], data, len);
uint16_t size = 3 + 1 + len;
return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size);
}
static int transport_send_intel_ddc(const uint8_t * data, uint16_t len){
little_endian_store_16(hci_outgoing, 0, 0xfc8b);
hci_outgoing[2] = len;
memcpy(&hci_outgoing[3], data, len);
uint16_t size = 3 + len;
return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size);
}
static void state_machine(uint8_t * packet);
// read data from fw file and send it via intel_secure + update state
static int intel_send_fragment(uint8_t fragment_type, uint16_t len){
int res = fread(fw_buffer, 1, len, fw_file);
log_info("offset %6u, read %3u -> res %d", fw_offset, len, res);
fw_offset += res;
state++;
return transport_send_intel_secure(fragment_type, fw_buffer, len);
}
// read data from ddc file and send iva intel ddc command
// @returns -1 on eof
static int intel_send_ddc(void){
int res;
// read len
res = fread(fw_buffer, 1, 1, fw_file);
log_info("offset %6u, read 1 -> res %d", fw_offset, res);
if (res == 0) return -1;
uint8_t len = fw_buffer[0];
fw_offset += 1;
res = fread(&fw_buffer[1], 1, len, fw_file);
log_info("offset %6u, read %u -> res %d", fw_offset, 1, res);
return transport_send_intel_ddc(fw_buffer, 1 + len);
}
static void dump_intel_version(intel_version_t * version){
log_info("status 0x%02x", version->status);
log_info("hw_platform 0x%02x", version->hw_platform);
log_info("hw_variant 0x%02x", version->hw_variant);
log_info("hw_revision 0x%02x", version->hw_revision);
log_info("fw_variant 0x%02x", version->fw_variant);
log_info("fw_revision 0x%02x", version->fw_revision);
log_info("fw_build_num 0x%02x", version->fw_build_num);
log_info("fw_build_ww 0x%02x", version->fw_build_ww);
log_info("fw_build_yy 0x%02x", version->fw_build_yy);
log_info("fw_patch_num 0x%02x", version->fw_patch_num);
}
static void dump_intel_boot_params(intel_boot_params_t * boot_params){
bd_addr_t addr;
reverse_bd_addr(boot_params->otp_bdaddr, addr);
log_info("Device revision: %u", dev_revid);
log_info("Secure Boot: %s", boot_params->secure_boot ? "enabled" : "disabled");
log_info("OTP lock: %s", boot_params->otp_lock ? "enabled" : "disabled");
log_info("API lock: %s", boot_params->api_lock ? "enabled" : "disabled");
log_info("Debug lock: %s", boot_params->debug_lock ? "enabled" : "disabled");
log_info("Minimum firmware build %u week %u %u", boot_params->min_fw_build_nn, boot_params->min_fw_build_cw, 2000 + boot_params->min_fw_build_yy);
log_info("OTC BD_ADDR: %s", bd_addr_to_str(addr));
}
static int vendor_firmware_complete_received;
static int waiting_for_command_complete;
static void state_machine(uint8_t * packet){
intel_version_t * version;
intel_boot_params_t * boot_params;
int res;
uint16_t buffer_offset;
bd_addr_t addr;
char fw_path[300];
if (packet){
// firmware upload complete event?
if (packet[0] == 0xff && packet[2] == 0x06) {
vendor_firmware_complete_received = 1;
}
// command complete
if (packet[0] == 0x0e){
waiting_for_command_complete = 0;
}
}
switch (state){
case 0:
state++;
transport_send_cmd(&hci_reset);
break;
case 1:
// check if HCI Reset was supported
if (packet[0] == 0x0e && packet[1] == 0x04 && packet[3] == 0x03 && packet[4] == 0x0c && packet[5] == 0x00){
log_info("HCI Reset was successful, no need for firmware upload / or not an Intel chipset");
(*done)(0);
break;
}
// Read Intel Version
state++;
transport_send_cmd(&hci_intel_read_version);
break;
case 2:
version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
dump_intel_version(version);
hw_variant = version->hw_variant;
// fw_variant = 0x06 bootloader mode / 0x23 operational mode
if (version->fw_variant == 0x23) {
(*done)(0);
break;
}
if (version->fw_variant != 0x06){
log_error("unknown fw_variant 0x%02x", version->fw_variant);
break;
}
// Read Intel Secure Boot Params
state++;
transport_send_cmd(&hci_intel_read_secure_boot_params);
break;
case 3:
boot_params = (intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet);
dump_intel_boot_params(boot_params);
reverse_bd_addr(boot_params->otp_bdaddr, addr);
dev_revid = little_endian_read_16((uint8_t*)&boot_params->dev_revid, 0);
// assert commmand complete is required
if (boot_params->limited_cce != 0) break;
// firmware file
snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.sfi", firmware_path, hw_variant, dev_revid);
log_info("Open firmware %s", fw_path);
printf("Firwmare %s\n", fw_path);
// open firmware file
fw_offset = 0;
fw_file = fopen(fw_path, "rb");
if (!fw_file){
log_error("can't open file %s", fw_path);
(*done)(1);
return;
}
vendor_firmware_complete_received = 0;
// send CCS segment - offset 0
intel_send_fragment(0x00, 128);
break;
case 4:
// send public key / part 1 - offset 128
intel_send_fragment(0x03, 128);
break;
case 5:
// send public key / part 2 - offset 384
intel_send_fragment(0x03, 128);
break;
case 6:
// skip 4 bytes
res = fread(fw_buffer, 1, 4, fw_file);
log_info("read res %d", res);
fw_offset += res;
// send signature / part 1 - offset 388
intel_send_fragment(0x02, 128);
break;
case 7:
// send signature / part 2 - offset 516
intel_send_fragment(0x02, 128);
break;
case 8:
// send firmware chunks - offset 644
// chunk len must be 4 byte aligned
// multiple commands can be combined
buffer_offset = 0;
do {
res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file);
log_info("fw_offset %6u, buffer_offset %u, read %3u -> res %d", fw_offset, buffer_offset, 3, res);
fw_offset += res;
if (res == 0 ){
// EOF
log_info("End of file");
fclose(fw_file);
fw_file = NULL;
state++;
break;
}
int param_len = fw_buffer[buffer_offset + 2];
buffer_offset += 3;
if (param_len){
res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file);
fw_offset += res;
buffer_offset += res;
}
} while ((buffer_offset & 3) != 0);
if (buffer_offset == 0) break;
waiting_for_command_complete = 1;
transport_send_intel_secure(0x01, fw_buffer, buffer_offset);
break;
case 9:
// expect Vendor Specific Event 0x06
if (!vendor_firmware_complete_received) break;
printf("Firmware upload complete\n");
log_info("Vendor Event 0x06 - firmware complete");
// Reset Params - constants from Windows Intel driver
state++;
transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00);
break;
case 10:
// expect Vendor Specific Event 0x02
if (packet[0] != 0xff) break;
if (packet[2] != 0x02) break;
printf("Firmware operational\n");
log_info("Vendor Event 0x02 - firmware operational");
// Read Intel Version
state++;
transport_send_cmd(&hci_intel_read_version);
break;
case 11:
version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
dump_intel_version(version);
// ddc config
snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.ddc", firmware_path, hw_variant, dev_revid);
log_info("Open DDC %s", fw_path);
// open ddc file
fw_offset = 0;
fw_file = fopen(fw_path, "rb");
if (!fw_file){
log_error("can't open file %s", fw_path);
(*done)(1);
return;
}
// load ddc
state++;
/* fall through */
case 12:
res = intel_send_ddc();
if (res == 0) break;
// DDC download complete
state++;
log_info("Load DDC Complete");
// Set Intel event mask 0xfc52
state++;
transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
break;
case 13:
// 9F FC 01 00
state++;
transport_send_cmd(&hci_intel_fc9f, 0x00);
break;
case 14:
(*done)(0);
break;
default:
break;
}
}
static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
UNUSED(packet_type);
// we also get events with packet_type ACL from the controller
hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
switch (hci_event_packet_get_type(packet)){
case HCI_EVENT_COMMAND_COMPLETE:
case HCI_EVENT_VENDOR_SPECIFIC:
state_machine(packet);
break;
default:
break;
}
}
void btstack_chipset_intel_set_firmware_path(const char * path){
firmware_path = path;
}
void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){
done = callback;
transport = hci_transport;;
// transport->init(NULL);
transport->register_packet_handler(&transport_packet_handler);
transport->open();
// get started
state = 0;
state_machine(NULL);
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2018 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
/*
* btstack_chipset_intel_firmware.c
*
* Adapter to use Intel-based chipsets with BTstack
*
*/
#ifndef __BTSTACK_CHIPSET_INTEL_FIRMWARE_H
#define __BTSTACK_CHIPSET_INTEL_FIRMWARE_H
#include "hci_transport.h"
#if defined __cplusplus
extern "C" {
#endif
/**
* @brief Download firmware via hci_transport
* @param transport
* @param done callback. 0 = Success
*/
void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*done)(int result));
/**
* @brief Set path to firmware files
* @param firmware_path defeaults to "."
*/
void btstack_chipset_intel_set_firmware_path(const char * firmware_path);
#if defined __cplusplus
}
#endif
#endif

View File

@ -5,6 +5,7 @@ VPATH += ${BTSTACK_ROOT}/src/ble/gatt-service
VPATH += ${BTSTACK_ROOT}/src/classic
VPATH += ${BTSTACK_ROOT}/example
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player
VPATH += ${BTSTACK_ROOT}/3rd-party/md5
VPATH += ${BTSTACK_ROOT}/3rd-party/micro-ecc
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder//srce
@ -14,6 +15,7 @@ CFLAGS += -I${BTSTACK_ROOT}/src/ble
CFLAGS += -I${BTSTACK_ROOT}/src/classic
CFLAGS += -I${BTSTACK_ROOT}/src
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/hxcmod-player
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/md5
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/micro-ecc
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include
@ -192,7 +194,7 @@ ant_test: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ant_test.c
sdp_rfcomm_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${PAN_OBJ} ${SDP_CLIENT} sdp_rfcomm_query.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
pbap_client_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} obex_iterator.c goep_client.c pbap_client.c pbap_client_demo.c
pbap_client_demo: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} md5.o obex_iterator.c goep_client.c pbap_client.c pbap_client_demo.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
sdp_general_query: ${CORE_OBJ} ${COMMON_OBJ} ${CLASSIC_OBJ} ${SDP_CLIENT} sdp_general_query.c

View File

@ -213,9 +213,9 @@ typedef struct {
static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
avrcp_track_t tracks[] = {
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345},
};
int current_track_index;
avrcp_play_status_info_t play_info;
@ -432,7 +432,7 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui
#ifndef HAVE_BTSTACK_STDIN
if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
if (status != ERROR_CODE_SUCCESS){
printf("Could not perform command, status 0x%2x\n", status);
@ -448,7 +448,10 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui
}
if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
switch (packet[2]){
printf("A2DP Meta %x\n", hci_event_a2dp_meta_get_subevent_code(packet));
switch (hci_event_a2dp_meta_get_subevent_code(packet)){
case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
@ -464,7 +467,6 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui
break;
case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
printf("A2DP Source: Received SBC codec configuration.\n");
sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
@ -475,17 +477,13 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui
sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency);
btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD,
sbc_configuration.block_length, sbc_configuration.subbands,
sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
sbc_configuration.max_bitpool_value,
sbc_configuration.channel_mode);
// status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
// if (status != ERROR_CODE_SUCCESS){
// printf("Could not perform command, status 0x%2x\n", status);
// }
break;
}
@ -503,12 +501,16 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui
}
printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
printf("A2DP Source: Start playing mod, a2dp cid 0x%02x.\n", media_tracker.a2dp_cid);
media_tracker.stream_opened = 1;
data_source = STREAM_MOD;
status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case A2DP_SUBEVENT_STREAM_RECONFIGURED:
status = a2dp_subevent_stream_reconfigured_get_status(packet);
printf("A2DP Source: Reconfigured, status 0x%02x\n", status);
break;
case A2DP_SUBEVENT_STREAM_STARTED:
play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
if (media_tracker.avrcp_cid){
@ -643,8 +645,8 @@ static void show_usage(void){
bd_addr_t iut_address;
gap_local_bd_addr(iut_address);
printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
printf("b - AVDTP Source create connection to addr %s\n", device_addr_string);
printf("B - AVDTP Source disconnect\n");
printf("b - A2DP Source create connection to addr %s\n", device_addr_string);
printf("B - A2DP Source disconnect\n");
printf("c - AVRCP Target create connection to addr %s\n", device_addr_string);
printf("C - AVRCP Target disconnect\n");
@ -653,6 +655,8 @@ static void show_usage(void){
printf("z - start streaming '%s'\n", mod_name);
}
printf("p - pause streaming\n");
printf("w - reconfigure stream for 44100 Hz\n");
printf("e - reconfigure stream for 48000 Hz\n");
printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
printf("---\n");
@ -663,10 +667,10 @@ static void stdin_process(char cmd){
switch (cmd){
case 'b':
status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
printf("%c - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
break;
case 'B':
printf("%c - AVDTP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid);
printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid);
status = a2dp_source_disconnect(media_tracker.a2dp_cid);
break;
case 'c':
@ -707,6 +711,26 @@ static void stdin_process(char cmd){
status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case 'w':
if (!media_tracker.stream_opened) break;
if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
printf("Stream cannot be reconfigured while playing, please pause stream first\n");
break;
}
printf("%c - Reconfigure for 44100 Hz.\n", cmd);
status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100);
break;
case 'e':
if (!media_tracker.stream_opened) break;
if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
printf("Stream cannot be reconfigured while playing, please pause stream first\n");
break;
}
printf("%c - Reconfigure for 48000 Hz.\n", cmd);
status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000);
break;
default:
show_usage();
return;

View File

@ -70,7 +70,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
static bd_addr_t remote_addr;
// MBP2016 "F4-0F-24-3B-1B-E1"
// Nexus 7 "30-85-A9-54-2E-78"
static const char * remote_addr_string = "BC:EC:5D:E6:15:03";
// iPhone SE "BC:EC:5D:E6:15:03"
// PTS "001BDC080AA5"
static char * remote_addr_string = "001BDC080AA5";
static btstack_packet_callback_registration_t hci_event_callback_registration;
static uint16_t pbap_cid;
@ -90,6 +92,7 @@ static void show_usage(void){
printf("d - get phonebook size\n");
printf("e - pull phonebook\n");
printf("f - disconnnect\n");
printf("p - authenticate using password '0000'\n");
printf("\n");
}
@ -116,6 +119,9 @@ static void stdin_process(char c){
case 'f':
pbap_disconnect(pbap_cid);
break;
case 'p':
pbap_authentication_password(pbap_cid, "0000");
break;
default:
show_usage();
break;
@ -148,6 +154,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case PBAP_SUBEVENT_OPERATION_COMPLETED:
printf("[+] Operation complete\n");
break;
case PBAP_SUBEVENT_AUTHENTICATION_REQUEST:
printf("[?] Authentication requested\n");
break;
case PBAP_SUBEVENT_PHONEBOOK_SIZE:
status = pbap_subevent_phonebook_size_get_status(packet);
if (status){

View File

@ -94,6 +94,10 @@
#include "rfcomm_service_db.h"
#include "socket_connection.h"
#ifdef HAVE_INTEL_USB
#include "btstack_chipset_intel_firmware.h"
#endif
#ifdef ENABLE_BLE
#include "ble/gatt_client.h"
#include "ble/att_server.h"
@ -204,7 +208,7 @@ static void stop_power_off_timer(void);
static client_state_t * client_for_connection(connection_t *connection);
static void hci_emit_system_bluetooth_enabled(uint8_t enabled);
static void stack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size);
static void btstack_server_configure_stack(void);
// MARK: globals
@ -212,7 +216,15 @@ static void stack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
static hci_transport_config_uart_t hci_transport_config_uart;
#endif
// used for stack configuration
static const hci_transport_t * transport;
static void * config = NULL;
static btstack_control_t * control;
#ifdef HAVE_INTEL_USB
static int intel_firmware_loaded;
#endif
static btstack_timer_source_t timeout;
static uint8_t timeout_active = 0;
static int power_management_sleep = 0;
@ -862,6 +874,16 @@ void daemon_gatt_serialize_characteristic_descriptor(gatt_client_characteristic_
#endif
#ifdef HAVE_INTEL_USB
static void btstack_server_intel_firmware_done(int result){
intel_firmware_loaded = 1;
// setup stack
btstack_server_configure_stack();
// start power up
hci_power_control(HCI_POWER_ON);
}
#endif
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){
bd_addr_t addr;
@ -912,7 +934,12 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
start_power_off_timer();
} else if (!power_management_sleep) {
stop_power_off_timer();
#ifdef HAVE_INTEL_USB
// before staring up the stack, load intel firmware
btstack_chipset_intel_download_firmware(transport, &btstack_server_intel_firmware_done);
#else
hci_power_control(HCI_POWER_ON);
#endif
}
break;
case BTSTACK_GET_VERSION:
@ -1929,6 +1956,60 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
static char hostname[30];
static void btstack_server_configure_stack(void){
// init HCI
hci_init(transport, config);
if (btstack_link_key_db){
hci_set_link_key_db(btstack_link_key_db);
}
if (control){
hci_set_control(control);
}
// hostname for POSIX systems
gethostname(hostname, 30);
hostname[29] = '\0';
gap_set_local_name(hostname);
#ifdef HAVE_PLATFORM_IPHONE_OS
// iPhone doesn't use SSP yet as there's no UI for it yet and auto accept is not an option
gap_ssp_set_enable(0);
#endif
// register for HCI events
hci_event_callback_registration.callback = &stack_packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(&stack_packet_handler);
timeout.process = daemon_no_connections_timeout;
#ifdef ENABLE_RFCOMM
log_info("config.h: ENABLE_RFCOMM\n");
rfcomm_init();
#endif
#ifdef ENABLE_SDP
sdp_init();
#endif
#ifdef ENABLE_BLE
sm_init();
sm_event_callback_registration.callback = &stack_packet_handler;
sm_add_event_handler(&sm_event_callback_registration);
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
// GATT Client
gatt_client_init();
// GATT Server - empty attribute database
att_server_init(NULL, NULL, NULL);
#endif
}
int btstack_server_run(int tcp_flag){
if (tcp_flag){
@ -1957,7 +2038,6 @@ int btstack_server_run(int tcp_flag){
socket_connection_init();
btstack_control_t * control = NULL;
void * config = NULL;
const btstack_uart_block_t * uart_block_implementation = NULL;
(void) uart_block_implementation;
@ -2027,58 +2107,10 @@ int btstack_server_run(int tcp_flag){
log_info("BTStack Server started\n");
log_info("version %s, build %s", BTSTACK_VERSION, BTSTACK_DATE);
// init HCI
hci_init(transport, config);
if (btstack_link_key_db){
hci_set_link_key_db(btstack_link_key_db);
}
if (control){
hci_set_control(control);
}
#ifndef HAVE_INTEL_USB
btstack_server_configure_stack();
#endif
// hostname for POSIX systems
gethostname(hostname, 30);
hostname[29] = '\0';
gap_set_local_name(hostname);
#ifdef HAVE_PLATFORM_IPHONE_OS
// iPhone doesn't use SSP yet as there's no UI for it yet and auto accept is not an option
gap_ssp_set_enable(0);
#endif
// register for HCI events
hci_event_callback_registration.callback = &stack_packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(&stack_packet_handler);
timeout.process = daemon_no_connections_timeout;
#ifdef ENABLE_RFCOMM
log_info("config.h: ENABLE_RFCOMM\n");
rfcomm_init();
#endif
#ifdef ENABLE_SDP
sdp_init();
#endif
#ifdef ENABLE_BLE
sm_init();
sm_event_callback_registration.callback = &stack_packet_handler;
sm_add_event_handler(&sm_event_callback_registration);
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
// GATT Client
gatt_client_init();
// GATT Server - empty attribute database
att_server_init(NULL, NULL, NULL);
#endif
#ifdef USE_LAUNCHD
socket_connection_create_launchd();
#else

View File

@ -227,6 +227,9 @@ static int sco_out_addr;
static int usb_path_len;
static uint8_t usb_path[USB_MAX_PATH_LEN];
// transport interface state
static int usb_transport_open;
#ifdef ENABLE_SCO_OVER_HCI
static void sco_ring_init(void){
@ -921,6 +924,8 @@ static void usb_sco_stop(void){
static int usb_open(void){
int r;
if (usb_transport_open) return 0;
handle_packet = NULL;
// default endpoint addresses
@ -1113,6 +1118,8 @@ static int usb_open(void){
usb_timer_active = 1;
}
usb_transport_open = 1;
return 0;
}
@ -1120,6 +1127,8 @@ static int usb_close(void){
int c;
int completed = 0;
if (!usb_transport_open) return 0;
log_info("usb_close");
switch (libusb_state){
@ -1252,6 +1261,7 @@ static int usb_close(void){
libusb_state = LIB_USB_CLOSED;
handle = NULL;
usb_transport_open = 0;
return 0;
}

View File

@ -251,6 +251,8 @@ static int usb_acl_out_active;
static uint8_t hci_event_in_buffer[2 + 255];
static uint8_t hci_acl_in_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE];
// transport interface state
static int usb_transport_open;
#ifdef ENABLE_SCO_OVER_HCI
@ -531,7 +533,17 @@ static void usb_process_acl_in(btstack_data_source_t *ds, btstack_data_source_ca
// IO_INCOMPLETE -> wait for completed
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
} else {
log_error("usb_process_acl_in: error writing");
log_error("usb_process_acl_in: error reading");
// Reset Pipe
err = WinUsb_ResetPipe(usb_interface_0_handle, acl_in_addr);
log_info("WinUsb_ResetPipe: result %u", (int) err);
if (err){
log_info("WinUsb_ResetPipe error %u", (int) GetLastError());
}
// re-submit transfer
usb_submit_acl_in_transfer();
}
return;
}
@ -1068,6 +1080,8 @@ static BOOL usb_lookup_symbols(void){
// returns 0 on success, -1 otherwise
static int usb_open(void){
if (usb_transport_open) return 0;
int r = -1;
#ifdef ENABLE_SCO_OVER_HCI
@ -1190,13 +1204,20 @@ static int usb_open(void){
SetupDiDestroyDeviceInfoList(hDevInfo);
log_info("usb_open: done");
log_info("usb_open: done, r = %x", r);
if (r == 0){
// opened
usb_transport_open = 1;
}
return r;
}
static int usb_close(void){
if (!usb_transport_open == 0) return 0;
// remove data sources
btstack_run_loop_remove_data_source(&usb_data_source_command_out);
btstack_run_loop_remove_data_source(&usb_data_source_event_in);
@ -1236,6 +1257,10 @@ static int usb_close(void){
// free everything
usb_free_resources();
// transport closed
usb_transport_open = 0;
return 0;
}

View File

@ -6,13 +6,14 @@ AC_INIT([BTstack], 0.1)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE
AC_ARG_WITH(hci-transport, [AS_HELP_STRING([--with-hci-transport=transportType], [Specify BT type to use: h4, usb])], HCI_TRANSPORT=$withval, HCI_TRANSPORT="h4")
AC_ARG_WITH(uart-device, [AS_HELP_STRING([--with-uart-device=uartDevice], [Specify BT UART device to use])], UART_DEVICE=$withval, UART_DEVICE="DEFAULT")
AC_ARG_WITH(uart-speed, [AS_HELP_STRING([--with-uart-speed=uartSpeed], [Specify BT UART speed to use])], UART_SPEED=$withval, UART_SPEED="115200")
AC_ARG_ENABLE(launchd, [AS_HELP_STRING([--enable-launchd],[Compiles BTdaemon for use by launchd])], USE_LAUNCHD=$enableval, USE_LAUNCHD="no")
AC_ARG_WITH(vendor-id, [AS_HELP_STRING([--with-vendor-id=vendorID], [Specify USB BT Dongle vendorID])], USB_VENDOR_ID=$withval, USB_VENDOR_ID="0")
AC_ARG_WITH(product-id, [AS_HELP_STRING([--with-product-id=productID], [Specify USB BT Dongle productID])], USB_PRODUCT_ID=$withval, USB_PRODUCT_ID="0")
AC_ARG_WITH(hci-transport, [AS_HELP_STRING([--with-hci-transport=transportType], [Specify BT type to use: h4, usb])], HCI_TRANSPORT=$withval, HCI_TRANSPORT="h4")
AC_ARG_WITH(uart-device, [AS_HELP_STRING([--with-uart-device=uartDevice], [Specify BT UART device to use])], UART_DEVICE=$withval, UART_DEVICE="DEFAULT")
AC_ARG_WITH(uart-speed, [AS_HELP_STRING([--with-uart-speed=uartSpeed], [Specify BT UART speed to use])], UART_SPEED=$withval, UART_SPEED="115200")
AC_ARG_WITH(vendor-id, [AS_HELP_STRING([--with-vendor-id=vendorID], [Specify USB BT Dongle vendorID])], USB_VENDOR_ID=$withval, USB_VENDOR_ID="0")
AC_ARG_WITH(product-id, [AS_HELP_STRING([--with-product-id=productID], [Specify USB BT Dongle productID])], USB_PRODUCT_ID=$withval, USB_PRODUCT_ID="0")
AC_ARG_ENABLE(launchd, [AS_HELP_STRING([--enable-launchd], [Compiles BTdaemon for use by launchd])], USE_LAUNCHD=$enableval, USE_LAUNCHD="no")
AC_ARG_ENABLE(intel-usb, [AS_HELP_STRING([--enable-intel-usb], [Enable Intel firmware support ])], ENABLE_INTEL_USB=$enableval, ENABLE_INTEL_USB="no")
# BUILD/HOST/TARGET
AC_CANONICAL_HOST
@ -176,6 +177,12 @@ if test "x$HCI_TRANSPORT" = xUSB; then
echo "#define HAVE_TRANSPORT_USB" >> btstack_config.h
echo "#define USB_PRODUCT_ID $USB_PRODUCT_ID" >> btstack_config.h
echo "#define USB_VENDOR_ID $USB_VENDOR_ID" >> btstack_config.h
if test "x$ENABLE_INTEL_USB" = xyes; then
echo "#define HAVE_INTEL_USB" >> btstack_config.h
FIRMWARE_FILES="\${INTEL_FILES}"
USB_SOURCES+=" btstack_chipset_intel_firmware.c"
fi
else
UART_SOURCES=btstack_uart_block_$UART_BLOCK.o
echo "#define HAVE_TRANSPORT_H4" >> btstack_config.h
@ -189,6 +196,7 @@ fi
echo >> btstack_config.h
echo "#endif" >> btstack_config.h
AC_SUBST(FIRMWARE_FILES)
AC_SUBST(REMOTE_DEVICE_DB_SOURCES)
AC_SUBST(USB_SOURCES)
AC_SUBST(UART_SOURCES)

2
port/daemon/src/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.ddc
*.sfi

View File

@ -6,6 +6,7 @@ CC = @CC@
LDFLAGS = @LDFLAGS@
CFLAGS = @CFLAGS@ \
-I ${BTSTACK_ROOT}/3rd-party/micro-ecc \
-I ${BTSTACK_ROOT}/chipset/intel \
-I $(BTSTACK_ROOT)/platform/daemon/src \
-I $(BTSTACK_ROOT)/platform/daemon/src \
-I $(BTSTACK_ROOT)/platform/posix \
@ -18,6 +19,7 @@ USB_CFLAGS = @USB_CFLAGS@
USB_LDFLAGS = @USB_LDFLAGS@
VPATH += ${BTSTACK_ROOT}/3rd-party/micro-ecc
VPATH += ${BTSTACK_ROOT}/chipset/intel
VPATH += ${BTSTACK_ROOT}/platform/daemon/src
VPATH += ${BTSTACK_ROOT}/platform/corefoundation
VPATH += ${BTSTACK_ROOT}/platform/libusb
@ -80,9 +82,12 @@ BTdaemon_SOURCES = \
.m.o:
$(CC) $(CFLAGS) -c -o $@ $<
# libBTstack.a
all: libBTstack.$(BTSTACK_LIB_EXTENSION) BTdaemon libBTstackServer.$(BTSTACK_LIB_EXTENSION)
# Intel Firmware files
include ${BTSTACK_ROOT}/chipset/intel/Makefile.inc
all: @FIRMWARE_FILES@
libBTstack.$(BTSTACK_LIB_EXTENSION): $(libBTstack_SOURCES)
$(BTSTACK_ROOT)/tool/get_version.sh
$(CC) $(CFLAGS) $^ $(LDFLAGS) $(BTSTACK_LIB_LDFLAGS) -o $@

View File

@ -15,6 +15,7 @@ COMPONENT_ADD_INCLUDEDIRS := \
3rd-party/bluedroid/encoder/include \
3rd-party/hxcmod-player \
3rd-party/hxcmod-player/mods \
3rd-party/md5 \
src/classic \
src/ble/gatt-service \
src/ble \
@ -29,6 +30,7 @@ COMPONENT_SRCDIRS := \
3rd-party/bluedroid/encoder/srce \
3rd-party/hxcmod-player \
3rd-party/hxcmod-player/mods \
3rd-party/md5 \
src/ble/gatt-service \
src/ble \
src/classic \

View File

@ -39,6 +39,7 @@ dirs_to_copy = [
'src',
'3rd-party/bluedroid',
'3rd-party/hxcmod-player',
'3rd-party/md5',
'platform/freertos',
'platform/embedded',
'tool'

72
port/libusb-intel/.gitignore vendored Normal file
View File

@ -0,0 +1,72 @@
a2dp_sink_demo
a2dp_source_demo
ancs_client_demo
ancs_client_demo.h
avdtp_sink.sbc
avdtp_sink.wav
avdtp_sink_demo
avdtp_source_demo
avrcp_browsing_client
ble_central_test
ble_peripheral_test
bnep_test
classic_test
dut_mode_classic
gap_dedicated_bonding
gap_inquiry
gap_inquiry_and_bond
gap_le_advertisements
gatt_battery_query
gatt_battery_query.h
gatt_browser
gatt_browser.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_hs_demo
l2cap_test
le_counter
le_counter.h
le_counter_work
le_data_channel_client
le_data_channel_server
le_data_channel_server.h
le_streamer
le_streamer.h
le_streamer_client
led_counter
panu_demo
pbap_client_demo
profile.h
sco_input*
sco_output*
sdp_bnep_query
sdp_general_query
sdp_rfcomm_query
sm_pairing_central
sm_pairing_central.h
sm_pairing_peripheral
sm_pairing_peripheral.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
att_delayed_response
att_delayed_response.h
*.ddc
*.sfi
gap_link_keys
mod_player
gatt_heart_rate_client

View File

@ -0,0 +1,53 @@
# Makefile for libusb based examples
BTSTACK_ROOT = ../..
CORE += main.c btstack_stdin_posix.c btstack_tlv_posix.c
COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c le_device_db_fs.c btstack_link_key_db_fs.c wav_util.c btstack_network_posix.c
COMMON += btstack_audio_portaudio.c btstack_chipset_intel_firmware.c
include ${BTSTACK_ROOT}/example/Makefile.inc
include ${BTSTACK_ROOT}/chipset/intel/Makefile.inc
CFLAGS += -g -std=c99 -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wunused-parameter -Wredundant-decls -Wsign-compare
# CFLAGS += -Werror
# CFLAGS += -pedantic
# only LLVM
# CFLAGS += -Wnewline-eof
# CFLAGS += -Wc11-extensions
# CFLAGS += -Wgnu-empty-initializer
CFLAGS += -I${BTSTACK_ROOT}/platform/posix \
-I${BTSTACK_ROOT}/platform/embedded \
-I${BTSTACK_ROOT}/3rd-party/tinydir \
-I${BTSTACK_ROOT}/chipset/intel
VPATH += ${BTSTACK_ROOT}/platform/embedded
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/platform/libusb
VPATH += ${BTSTACK_ROOT}/chipset/csr
VPATH += ${BTSTACK_ROOT}/chipset/intel
# use pkg-config
CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
# use pkg-config for portaudio
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO
# LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
# hard coded flags for portaudio in /usr/local/lib
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
clean: clean-intel
clean_src:
rm -rf * ${BTSTACK_ROOT}/src/*.o
rm -rf * ${BTSTACK_ROOT}/src/classic/*.o
rm -rf * ${BTSTACK_ROOT}/src/ble/*.o
rm -rf * ${BTSTACK_ROOT}/platform/embedded/*.o
all: all-intel ${EXAMPLES}

View File

@ -0,0 +1,86 @@
# BTstack Port for POSIX Systems with Intel Wireless 8260/8265 Controllers
Same as port/libusb, but customized for Intel Wireless 8260 and 8265 Controllers.
These controller require firmware upload and configuration to work. Firmware and config is downloaded from the Linux firmware repository.
## Compilation
Requirements:
- [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/)
- [libusb-1.0](http://libusb.info)
On a recent Debian-based system, all you need is:
apt-get install gcc git libusb-1.0 pkg-config
When everything is ready, you compile all examples with:
make
## Environment
On Linux, the USB Bluetooth dongle is usually not accessible to a regular user. You can either:
- run the examples as root
- add a udev rule for your dongle to extend access rights to user processes
To add an udev rule, please create `/etc/udev/rules.d/btstack.rules` and add this
# Match all devices from CSR
SUBSYSTEM=="usb", ATTRS{idVendor}=="0a12", MODE="0666"
# Match DeLOCK Bluetooth 4.0 dongle
SUBSYSTEM=="usb", ATTRS{idVendor}=="0a5c", ATTRS{device}=="21e8", MODE="0666"
# Match Asus BT400
SUBSYSTEM=="usb", ATTRS{idVendor}=="0b05", ATTRS{device}=="17cb", MODE="0666"
# Match Laird BT860 / Cypress Semiconductor CYW20704A2
SUBSYSTEM=="usb", ATTRS{idVendor}=="04b4", ATTRS{device}=="f901", MODE="0666"
# Match Intel Wireless 8260 8265
SUBSYSTEM=="usb", ATTRS{idVendor}=="8027", ATTRS{device}=="0a2b, MODE="0666"
On macOS, the OS will try to use a plugged-in Bluetooth Controller if one is available.
It's best to to tell the OS to always use the internal Bluetooth Contoller.
For this, execute:
sudo nvram bluetoothHostControllerSwitchBehavior=never
and then reboot to activate the change.
## Running the examples
BTstack's HCI USB transport will try to find a suitable Bluetooth module and use it.
On start, BTstack will try to find a suitable Bluetooth module. It will also print the path to the packet log as well as the USB path.
$ ./le_counter
Packet Log: /tmp/hci_dump.pklg
USB Path: 03-01-04-03
Firwmare ./ibt-12-16.sfi
Firmware upload complete
Firmware operational
Done 1
BTstack counter 0001
USB Path: 03-01-04-03
BTstack up and running on F8:34:41:D5:BE:6F.
If you want to run multiple examples at the same time, it helps to fix the path to the used Bluetooth module by passing -u usb-path to the executable.
Example running le_streamer and le_streamer_client in two processes, using Bluetooth dongles at USB path 6 and 4:
./le_streamer -u 6
Specified USB Path: 06
Packet Log: /tmp/hci_dump_6.pklg
USB Path: 06
BTstack up and running on 00:1A:7D:DA:71:13.
To start the streaming, please run the le_streamer_client example on other device, or use some GATT Explorer, e.g. LightBlue, BLExplr.
$ ./le_streamer_client -u 4
Specified USB Path: 04
Packet Log: /tmp/hci_dump_4.pklg
USB Path: 04
BTstack up and running on 00:1A:7D:DA:71:13.
Start scanning!

View File

@ -0,0 +1,36 @@
//
// btstack_config.h for libusb port
//
#ifndef __BTSTACK_CONFIG
#define __BTSTACK_CONFIG
// Port related features
#define HAVE_MALLOC
#define HAVE_POSIX_FILE_IO
#define HAVE_BTSTACK_STDIN
#define HAVE_POSIX_TIME
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_HFP_WIDE_BAND_SPEECH
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_CHANNELS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_ATT_DELAYED_RESPONSE
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy
#endif

204
port/libusb-intel/main.c Normal file
View File

@ -0,0 +1,204 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#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 "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_link_key_db_fs.h"
#include "btstack_memory.h"
#include "btstack_run_loop.h"
#include "btstack_run_loop_posix.h"
#include "hal_led.h"
#include "hci.h"
#include "hci_dump.h"
#include "btstack_stdin.h"
#include "btstack_audio.h"
#include "btstack_tlv_posix.h"
#include "btstack_chipset_intel_firmware.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 hci_transport_t * transport;
int btstack_main(int argc, const char * argv[]);
static btstack_packet_callback_registration_t hci_event_callback_registration;
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
if (packet_type != HCI_EVENT_PACKET) return;
switch (hci_event_packet_get_type(packet)){
case BTSTACK_EVENT_STATE:
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
gap_local_bd_addr(local_addr);
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
strcat(tlv_db_path, bd_addr_to_str(local_addr));
strcat(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);
break;
default:
break;
}
}
static void sigint_handler(int param){
UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n");
log_info("sigint_handler: shutting down");
// reset anyway
btstack_stdin_reset();
// power down
hci_power_control(HCI_POWER_OFF);
hci_close();
log_info("Good bye, see you.\n");
exit(0);
}
static int led_state = 0;
void hal_led_toggle(void){
led_state = 1 - led_state;
printf("LED State %u\n", led_state);
}
static void intel_firmware_done(int result){
printf("Done %x\n", result);
// init HCI
hci_init(transport, NULL);
#ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_fs_instance());
#endif
#ifdef HAVE_PORTAUDIO
btstack_audio_set_instance(btstack_audio_portaudio_get_instance());
#endif
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// setup app
btstack_main(main_argc, main_argv);
}
#define USB_MAX_PATH_LEN 7
int main(int argc, const char * argv[]){
uint8_t usb_path[USB_MAX_PATH_LEN];
int usb_path_len = 0;
const char * usb_path_string = NULL;
if (argc >= 3 && strcmp(argv[1], "-u") == 0){
// parse command line options for "-u 11:22:33"
usb_path_string = argv[2];
printf("Specified USB Path: ");
while (1){
char * delimiter;
int port = strtol(usb_path_string, &delimiter, 16);
usb_path[usb_path_len] = port;
usb_path_len++;
printf("%02x ", port);
if (!delimiter) break;
if (*delimiter != ':' && *delimiter != '-') break;
usb_path_string = delimiter+1;
}
printf("\n");
argc -= 2;
memmove(&argv[1], &argv[3], (argc-1) * sizeof(char *));
}
/// GET STARTED with BTstack ///
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
if (usb_path_len){
hci_transport_usb_set_path(usb_path_len, usb_path);
}
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
char pklg_path[100];
strcpy(pklg_path, "/tmp/hci_dump");
if (usb_path_len){
strcat(pklg_path, "_");
strcat(pklg_path, usb_path_string);
}
strcat(pklg_path, ".pklg");
printf("Packet Log: %s\n", pklg_path);
hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER);
// setup USB Transport
transport = hci_transport_usb_instance();
btstack_chipset_intel_download_firmware(transport, &intel_firmware_done);
// handle CTRL-c
signal(SIGINT, sigint_handler);
// go
btstack_run_loop_execute();
return 0;
}

View File

@ -104,6 +104,7 @@ VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods
VPATH += ${BTSTACK_ROOT}/3rd-party/md5
VPATH += ${BTSTACK_ROOT}/3rd-party/micro-ecc
VPATH += ${BTSTACK_ROOT}/platform/embedded
VPATH += ${BTSTACK_ROOT}/src/ble/gatt-service/
@ -119,6 +120,7 @@ PROJ_CFLAGS += \
-I${BTSTACK_ROOT}/example \
-I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include \
-I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include \
-I${BTSTACK_ROOT}/3rd-party/md5 \
-I${BTSTACK_ROOT}/3rd-party/micro-ecc \
-I${BTSTACK_ROOT}/3rd-party/hxcmod-player \
@ -226,7 +228,7 @@ SRCS += $(CVSD_PLC_OBJ)
SRCS += $(HXCMOD_PLAYER_OBJ)
SRCS += $(HFP_OBJ)
SRCS += hsp_hs.o hsp_ag.o
SRCS += obex_iterator.o goep_client.o pbap_client.o
SRCS += obex_iterator.o goep_client.o pbap_client.o md5.o
# Enable assertion checking for development
PROJ_CFLAGS+=-DMXC_ASSERT_ENABLE

View File

@ -15,6 +15,7 @@ CFLAGS += -I$(BTSTACK_ROOT)/src/
CFLAGS += -I$(BTSTACK_ROOT)/ble
CFLAGS += -I$(BTSTACK_ROOT)/platform/daemon/src
CFLAGS += -I$(BTSTACK_ROOT)/platform/posix
CFLAGS += -I$(BTSTACK_ROOT)/3rd-party/md5
CFLAGS += -I.
VPATH += $(BTSTACK_ROOT)/src
@ -23,6 +24,7 @@ VPATH += $(BTSTACK_ROOT)/src/classic
VPATH += $(BTSTACK_ROOT)/platform/posix
VPATH += $(BTSTACK_ROOT)/platform/daemon/src
VPATH += $(BTSTACK_ROOT)/platform/daemon/example
VPATH += $(BTSTACK_ROOT)/3rd-party/md5
libBTstack_OBJS = \
btstack.o \
@ -41,9 +43,11 @@ libBTstack_OBJS = \
BTdaemon_OBJS = $(libBTstack_OBJS) \
ad_parser.o \
att_dispatch.o \
btstack_link_key_db_memory.o \
btstack_link_key_db_tlv.o \
btstack_memory.o \
btstack_memory_pool.o \
btstack_tlv.o \
btstack_tlv_posix.o \
btstack_crypto.o \
daemon.o \
gatt_client.o \
@ -52,7 +56,8 @@ BTdaemon_OBJS = $(libBTstack_OBJS) \
btstack_uart_block_posix.o \
l2cap.o \
l2cap_signaling.o \
le_device_db_memory.o \
le_device_db_tlv.o \
md5.o \
rfcomm.o \
rfcomm_service_db_hash.o \
sdp_server.o \

View File

@ -23,6 +23,8 @@
#define HCI_ACL_PAYLOAD_SIZE 1021
#define MAX_NR_LE_DEVICE_DB_ENTRIES 1
#define NVM_NUM_DEVICE_DB_ENTRIES 16
// Daemon configuration
#define ENABLE_SDP
#define ENABLE_RFCOMM

View File

@ -38,6 +38,7 @@ VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods
VPATH += ${BTSTACK_ROOT}/3rd-party/md5
VPATH += ${BTSTACK_ROOT}/3rd-party/segger-rtt
VPATH += ${BTSTACK_ROOT}/chipset/cc256x
VPATH += ${BTSTACK_ROOT}/example
@ -158,6 +159,7 @@ hfp_msbc.c \
hsp_hs.c \
hsp_ag.c \
hid_device.c \
md5.c \
rfcomm.c \
sco_demo_util.c \
btstack_hid_parser.c \
@ -235,10 +237,11 @@ C_INCLUDES += -I${BTSTACK_ROOT}/src/ble/gatt-service
C_INCLUDES += -I${BTSTACK_ROOT}/src/classic
C_INCLUDES += -I${BTSTACK_ROOT}/src
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/micro-ecc
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/bluedroid/descoder/include
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/hxcmod-player
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/md5
C_INCLUDES += -I${BTSTACK_ROOT}/3rd-party/segger-rtt
C_INCLUDES += -I${BTSTACK_ROOT}/platform/embedded
C_INCLUDES += -I${BTSTACK_ROOT}/chipset/cc256x

View File

@ -78,6 +78,7 @@
<listOptionValue builtIn="false" value="../btstack/3rd-party/bluedroid/decoder/include"/>
<listOptionValue builtIn="false" value="../btstack/3rd-party/hxcmod-player/mods"/>
<listOptionValue builtIn="false" value="../btstack/3rd-party/hxcmod-player"/>
<listOptionValue builtIn="false" value="../btstack/3rd-party/md5"/>
</option>
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.1206315366" name="Defined symbols (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DEBUG"/>

39
port/windows-winusb-intel/.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
ancs_client_demo
ancs_client_demo.h
ble_central_test
ble_peripheral_test
bnep_test
classic_test
gap_dedicated_bonding
gap_inquiry
gap_inquiry_and_bond
gap_le_advertisements
gap_le_advertisements
gatt_battery_query
gatt_browser
hfp_ag_demo
hfp_hf_demo
hsp_ag_demo
hsp_hs_demo
l2cap_test
le_counter
le_counter.h
le_streamer
le_streamer
le_streamer.h
led_counter
panu_demo
profile.h
sdp_bnep_query
sdp_general_query
sdp_rfcomm_query
sm_pairing_central
sm_pairing_peripheral
sm_pairing_peripheral.h
spp_and_le_counter
spp_and_le_counter.h
spp_counter
spp_streamer
spp_streamer
sco_input*
sco_output*

View File

@ -0,0 +1,39 @@
# Makefile for windows WinUSB based examples
BTSTACK_ROOT = ../..
CORE += main.c btstack_stdin_windows.c
COMMON += hci_transport_h2_winusb.c btstack_run_loop_windows.c le_device_db_fs.c btstack_link_key_db_fs.c wav_util.c
COMMON += btstack_chipset_intel_firmware.c
include ${BTSTACK_ROOT}/example/Makefile.inc
include ${BTSTACK_ROOT}/chipset/intel/Makefile.inc
# CC = gcc-fsf-4.9
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wpedantic
# CFLAGS += -Werror
CFLAGS += -I${BTSTACK_ROOT}/platform/windows \
-I${BTSTACK_ROOT}/platform/posix \
-I${BTSTACK_ROOT}/chipset/intel \
-I${BTSTACK_ROOT}/platform/embedded \
-I${BTSTACK_ROOT}/3rd-party/tinydir
VPATH += ${BTSTACK_ROOT}/platform/embedded
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/platform/windows
VPATH += ${BTSTACK_ROOT}/chipset/csr
VPATH += ${BTSTACK_ROOT}/chipset/intel
# use pkg-config for portaudio
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO
# LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
# hard coded flags for portaudio in /usr/local/lib
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
LDFLAGS += -lsetupapi -lwinusb
clean: clean-intel
all: all-intel ${EXAMPLES}

View File

@ -0,0 +1,43 @@
# BTstack port for Windows Systems with Intel Wireless 8260/8265 Controllers
Same as port/windows-winusb, but customized for Intel Wireless 8260 and 8265 Controllers.
These controller require firmware upload and configuration to work. Firmware and config is downloaded from the Linux firmware repository.
## Access to Bluetooth USB Dongle with Zadig
To allow libusb or WinUSB to access an USB Bluetooth dongle, you need to install a special device driver to make it accessible to user space processes.
It works like this:
- Download [Zadig](http://zadig.akeo.ie)
- Start Zadig
- Select Options -> “List all devices”
- Select USB Bluetooth dongle in the big pull down list
- Select WinUSB (libusb) in the right pull pull down list
- Select “Replace Driver”
## Toolchain
The port requires a Unix-like toolchain. We successfully used [mingw-w64](https://mingw-w64.org/doku.php) to compile and run the examples. mingw64-w64 is based on [MinGW](mingw.org), which '...provides a complete Open Source programming tool set which is suitable for the development of native MS-Windows applications, and which do not depend on any 3rd-party C-Runtime DLLs.'
We've used the Msys2 package available from the [downloads page](https://mingw-w64.org/doku.php/download) on Windows 10, 64-bit and use the MSYS2 MinGW 32-bit start menu item to compile 32-bit binaries that run on both 32/64-bit systems.
In the MSYS2 shell, you can install git, python, and, winpty with pacman:
$ pacman -S git
$ pacman -S python
$ pacman -S winpty
## Compilation
With mingw64-w64 installed, just go to the port/windows-winusb directory and run make
$ cd btstack/port/windows-winusb
$ make
## Console Output
When running the examples in the MSYS2 shell, the console input (via btstack_stdin_support) doesn't work. It works in the older MSYS and also the regular CMD.exe environment. Another option is to install WinPTY and then start the example via WinPTY like this:
$ winpty ./spp_and_le_counter.exe

View File

@ -0,0 +1,33 @@
//
// btstack_config.h for libusb port
//
#ifndef __BTSTACK_CONFIG
#define __BTSTACK_CONFIG
// Port related features
#define HAVE_MALLOC
#define HAVE_POSIX_FILE_IO
#define HAVE_BTSTACK_STDIN
#define HAVE_POSIX_TIME
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_HFP_WIDE_BAND_SPEECH
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_CHANNELS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy
#endif

View File

@ -0,0 +1,193 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#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 "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_link_key_db_fs.h"
#include "btstack_memory.h"
#include "btstack_run_loop.h"
#include "btstack_run_loop_windows.h"
#include "hal_led.h"
#include "hci.h"
#include "hci_dump.h"
#include "btstack_stdin.h"
#include "btstack_chipset_intel_firmware.h"
int btstack_main(int argc, const char * argv[]);
static btstack_packet_callback_registration_t hci_event_callback_registration;
static int main_argc;
static const char ** main_argv;
static const hci_transport_t * transport;
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;
bd_addr_t addr;
gap_local_bd_addr(addr);
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
}
static void sigint_handler(int param){
UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n");
log_info("sigint_handler: shutting down");
// reset anyway
btstack_stdin_reset();
// power down
hci_power_control(HCI_POWER_OFF);
hci_close();
log_info("Good bye, see you.\n");
exit(0);
}
static int led_state = 0;
void hal_led_toggle(void){
led_state = 1 - led_state;
printf("LED State %u\n", led_state);
}
static void intel_firmware_done(int result){
printf("Done %x\n", result);
// init HCI
hci_init(transport, NULL);
#ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_fs_instance());
#endif
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// setup app
btstack_main(main_argc, main_argv);
}
#define USB_MAX_PATH_LEN 7
int main(int argc, const char * argv[]){
// Prevent stdout buffering
setvbuf(stdout, NULL, _IONBF, 0);
main_argc = argc;
main_argv = argv;
printf("BTstack/windows-winusb booting up\n");
#if 0
int usb_path_len = 0;
uint8_t usb_path[USB_MAX_PATH_LEN];
if (argc >= 3 && strcmp(argv[1], "-u") == 0){
// parse command line options for "-u 11:22:33"
const char * port_str = argv[2];
printf("Specified USB Path: ");
while (1){
char * delimiter;
int port = strtol(port_str, &delimiter, 16);
usb_path[usb_path_len] = port;
usb_path_len++;
printf("%02x ", port);
if (!delimiter) break;
if (*delimiter != ':' && *delimiter != '-') break;
port_str = delimiter+1;
}
printf("\n");
}
#endif
/// GET STARTED with BTstack ///
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_windows_get_instance());
// if (usb_path_len){
// hci_transport_usb_set_path(usb_path_len, usb_path);
// }
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
#if 1
char pklg_path[100];
strcpy(pklg_path, "hci_dump");
#if 0
if (usb_path_len){
strcat(pklg_path, "_");
strcat(pklg_path, argv[2]);
}
#endif
strcat(pklg_path, ".pklg");
printf("Packet Log: %s\n", pklg_path);
hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER);
#else
hci_dump_open(NULL, HCI_DUMP_STDOUT);
#endif
// handle CTRL-c
signal(SIGINT, sigint_handler);
// setup USB Transport
transport = hci_transport_usb_instance();
btstack_chipset_intel_download_firmware(hci_transport_usb_instance(), &intel_firmware_done);
// go
btstack_run_loop_execute();
return 0;
}

View File

@ -4,15 +4,17 @@ BTSTACK_ROOT = ../..
CORE += main.c btstack_stdin_windows.c
COMMON += hci_transport_h2_winusb.c btstack_run_loop_windows.c le_device_db_fs.c btstack_link_key_db_fs.c wav_util.c
COMMON += btstack_chipset_intel_firmware.c
include ${BTSTACK_ROOT}/example/Makefile.inc
# CC = gcc-fsf-4.9
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wpedantic
# CFLAGS += -Werror
CFLAGS += -I${BTSTACK_ROOT}/platform/windows \
-I${BTSTACK_ROOT}/platform/posix \
-I${BTSTACK_ROOT}/chipset/intel \
-I${BTSTACK_ROOT}/platform/embedded \
-I${BTSTACK_ROOT}/3rd-party/tinydir
@ -20,6 +22,7 @@ VPATH += ${BTSTACK_ROOT}/platform/embedded
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/platform/windows
VPATH += ${BTSTACK_ROOT}/chipset/csr
VPATH += ${BTSTACK_ROOT}/chipset/intel
# use pkg-config for portaudio
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO

View File

@ -61,10 +61,14 @@
#include "hci.h"
#include "hci_dump.h"
#include "btstack_stdin.h"
#include "btstack_chipset_intel_firmware.h"
int btstack_main(int argc, const char * argv[]);
static btstack_packet_callback_registration_t hci_event_callback_registration;
static int main_argc;
static const char ** main_argv;
static const hci_transport_t * transport;
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
@ -98,12 +102,39 @@ void hal_led_toggle(void){
}
static void intel_firmware_done(int result){
printf("Done %x\n", result);
// close
transport->close();
//
// init HCI
hci_init(transport, NULL);
#ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_fs_instance());
#endif
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// setup app
btstack_main(main_argc, main_argv);
}
#define USB_MAX_PATH_LEN 7
int main(int argc, const char * argv[]){
// Prevent stdout buffering
setvbuf(stdout, NULL, _IONBF, 0);
main_argc = argc;
main_argv = argv;
printf("BTstack/windows-winusb booting up\n");
#if 0
@ -153,22 +184,12 @@ int main(int argc, const char * argv[]){
hci_dump_open(NULL, HCI_DUMP_STDOUT);
#endif
// init HCI
hci_init(hci_transport_usb_instance(), NULL);
#ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_fs_instance());
#endif
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// handle CTRL-c
signal(SIGINT, sigint_handler);
// setup app
btstack_main(argc, argv);
// setup USB Transport
transport = hci_transport_usb_instance();
btstack_chipset_intel_download_firmware(hci_transport_usb_instance(), &intel_firmware_done);
// go
btstack_run_loop_execute();

View File

@ -2056,6 +2056,16 @@ typedef uint8_t sm_key_t[16];
*/
#define PBAP_SUBEVENT_PHONEBOOK_SIZE 0x04
/**
* @format 1211
* @param subevent_code
* @param goep_cid
* @param user_id_required
* @param full_access
*/
#define PBAP_SUBEVENT_AUTHENTICATION_REQUEST 0x05
// HID Meta Event Group
/**

View File

@ -6534,6 +6534,34 @@ static inline uint16_t pbap_subevent_phonebook_size_get_phoneboook_size(const ui
return little_endian_read_16(event, 6);
}
/**
* @brief Get field goep_cid from event PBAP_SUBEVENT_AUTHENTICATION_REQUEST
* @param event packet
* @return goep_cid
* @note: btstack_type 2
*/
static inline uint16_t pbap_subevent_authentication_request_get_goep_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field user_id_required from event PBAP_SUBEVENT_AUTHENTICATION_REQUEST
* @param event packet
* @return user_id_required
* @note: btstack_type 1
*/
static inline uint8_t pbap_subevent_authentication_request_get_user_id_required(const uint8_t * event){
return event[5];
}
/**
* @brief Get field full_access from event PBAP_SUBEVENT_AUTHENTICATION_REQUEST
* @param event packet
* @return full_access
* @note: btstack_type 1
*/
static inline uint8_t pbap_subevent_authentication_request_get_full_access(const uint8_t * event){
return event[6];
}
/**
* @brief Get field hid_cid from event HID_SUBEVENT_CONNECTION_OPENED
* @param event packet

View File

@ -334,8 +334,11 @@ int sscanf_bd_addr(const char * addr_string, bd_addr_t addr){
result = 1;
break;
}
char separator = *addr_string++;
if (separator != ':' && separator != '-' && separator != ' ') break;
// skip supported separators
char next_char = *addr_string;
if (next_char == ':' || next_char == '-' || next_char == ' ') {
addr_string++;
}
}
if (result){

View File

@ -39,7 +39,6 @@
#define __BTSTACK_FILE__ "a2dp_source.c"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -200,6 +199,20 @@ static void a2dp_signaling_emit_control_command(btstack_packet_handler_t callbac
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void a2dp_signaling_emit_reconfigured(btstack_packet_handler_t callback, uint16_t cid, uint8_t local_seid, uint8_t status){
if (!callback) return;
uint8_t event[7];
int pos = 0;
event[pos++] = HCI_EVENT_A2DP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = A2DP_SUBEVENT_STREAM_RECONFIGURED;
little_endian_store_16(event, pos, cid);
pos += 2;
event[pos++] = local_seid;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
@ -365,6 +378,11 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
avdtp_source_set_configuration(cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid, sc.local_stream_endpoint->remote_configuration_bitmap, sc.local_stream_endpoint->remote_configuration);
break;
}
case A2DP_W2_RECONFIGURE_WITH_SEID:
log_info("A2DP reconfigured");
a2dp_signaling_emit_reconfigured(a2dp_source_context.a2dp_callback, cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), 0);
app_state = A2DP_STREAMING_OPENED;
break;
case A2DP_W2_OPEN_STREAM_WITH_SEID:{
log_info("A2DP open stream ");
app_state = A2DP_W4_OPEN_STREAM_WITH_SEID;
@ -474,6 +492,51 @@ uint8_t a2dp_source_disconnect(uint16_t a2dp_cid){
return avdtp_disconnect(a2dp_cid, &a2dp_source_context);
}
uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t a2dp_cid, uint32_t sampling_frequency){
// UNUSED(sampling_frequency);
log_info("a2dp_source_reconfigure_stream");
memcpy(sc.local_stream_endpoint->reconfigure_media_codec_sbc_info, sc.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, 4);
// update sampling frequency
uint8_t config = sc.local_stream_endpoint->reconfigure_media_codec_sbc_info[0] & 0x0f;
switch (sampling_frequency){
case 48000:
config |= (AVDTP_SBC_48000 << 4);
break;
case 44100:
config |= (AVDTP_SBC_44100 << 4);
break;
case 32000:
config |= (AVDTP_SBC_32000 << 4);
break;
case 16000:
config |= (AVDTP_SBC_16000 << 4);
break;
default:
log_error("Unsupported sampling frequency %u", sampling_frequency);
return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
}
sc.local_stream_endpoint->reconfigure_media_codec_sbc_info[0] = config;
avdtp_capabilities_t new_configuration;
new_configuration.media_codec.media_type = AVDTP_AUDIO;
new_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
new_configuration.media_codec.media_codec_information_len = 4;
new_configuration.media_codec.media_codec_information = sc.local_stream_endpoint->reconfigure_media_codec_sbc_info;
// sttart reconfigure
app_state = A2DP_W2_RECONFIGURE_WITH_SEID;
return avdtp_source_reconfigure(
a2dp_cid,
avdtp_stream_endpoint_seid(sc.local_stream_endpoint),
sc.active_remote_sep->seid,
1 << AVDTP_MEDIA_CODEC,
new_configuration
);
}
uint8_t a2dp_source_start_stream(uint16_t a2dp_cid, uint8_t local_seid){
return avdtp_start_stream(a2dp_cid, local_seid, &a2dp_source_context);
}

View File

@ -47,7 +47,7 @@
#define __A2DP_SOURCE_H
#include <stdint.h>
#include "avdtp.h"
#include "classic/avdtp.h"
#if defined __cplusplus
extern "C" {
@ -109,6 +109,13 @@ void a2dp_source_register_packet_handler(btstack_packet_handler_t callback);
*/
uint8_t a2dp_source_establish_stream(bd_addr_t remote, uint8_t local_seid, uint16_t * out_a2dp_cid);
/**
* @brief Reconfigure stream.
* @param local_seid ID assigned to a local stream endpoint
* @param sampling_frequency New sampling frequency to use. Cannot be called while stream is active
*/
uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t a2dp_cid, uint32_t sampling_frequency);
/**
* @brief Start stream.
* @param a2dp_cid A2DP channel identifyer.

View File

@ -387,6 +387,12 @@ uint8_t goep_client_create_connection(btstack_packet_handler_t handler, bd_addr_
return 0;
}
uint32_t goep_client_get_pbap_supported_features(uint16_t goep_cid){
UNUSED(goep_cid);
goep_client_t * context = goep_client;
return context->pbap_supported_features;
}
uint8_t goep_client_disconnect(uint16_t goep_cid){
UNUSED(goep_cid);
goep_client_t * context = goep_client;
@ -468,6 +474,10 @@ void goep_client_add_header_application_parameters(uint16_t goep_cid, uint16_t l
goep_client_add_header(goep_cid, OBEX_HEADER_APPLICATION_PARAMETERS, length, data);
}
void goep_client_add_header_challenge_response(uint16_t goep_cid, uint16_t length, const uint8_t * data){
goep_client_add_header(goep_cid, OBEX_HEADER_AUTHENTICATION_RESPONSE, length, data);
}
void goep_client_add_header_name(uint16_t goep_cid, const char * name){
UNUSED(goep_cid);
goep_client_t * context = goep_client;
@ -501,7 +511,6 @@ int goep_client_execute(uint16_t goep_cid){
goep_client_t * context = goep_client;
uint8_t * buffer = goep_client_get_outgoing_buffer(context);
uint16_t pos = big_endian_read_16(buffer, 1);
printf_hexdump(buffer, pos);
if (context->l2cap_psm){
// return l2cap_send_prepared(context->bearer_cid, pos);
return l2cap_send(context->bearer_cid, buffer, pos);

View File

@ -93,6 +93,11 @@ void goep_client_request_can_send_now(uint16_t goep_cid);
*/
uint8_t goep_client_get_request_opcode(uint16_t goep_cid);
/**
* brief Get PBAP Supported Features found in SDP record during conenct
*/
uint32_t goep_client_get_pbap_supported_features(uint16_t goep_cid);
/**
* @brief Set Connection ID used for newly created requests
* @param gope_cid
@ -161,10 +166,18 @@ void goep_client_add_header_count(uint16_t goep_cid, uint32_t count);
* @brief Add application parameters header to current request
* @param goep_cid
* @param lenght of application parameters
* @param daa
* @param data
*/
void goep_client_add_header_application_parameters(uint16_t goep_cid, uint16_t length, const uint8_t * data);
/**
* @brief Add application parameters header to current request
* @param goep_cid
* @param lenght of challenge response
* @param data
*/
void goep_client_add_header_challenge_response(uint16_t goep_cid, uint16_t length, const uint8_t * data);
// int goep_client_add_body_static(uint16_t goep_cid, uint32_t length, uint8_t * data);
// int goep_client_add_body_dynamic(uint16_t goep_cid, uint32_t length, void (*data_callback)(uint32_t offset, uint8_t * buffer, uint32_t len));

View File

@ -46,29 +46,34 @@
#define OBEX_OPCODE_SESSION 0x87
#define OBEX_OPCODE_ABORT 0xFF
#define OBEX_OPCODE_FINAL_BIT_MASK 0x80
#define OBEX_RESP_SUCCESS 0xA0
#define OBEX_RESP_CONTINUE 0x90
#define OBEX_RESP_CANCELED 0xC1
#define OBEX_RESP_BAD_REQUEST 0xC0
#define OBEX_RESP_UNAUTHORIZED 0xC1
#define OBEX_RESP_FORBIDDEN 0xC3
#define OBEX_RESP_NOT_FOUND 0xC4
#define OBEX_RESP_REFUSED 0xC6
#define OBEX_HEADER_BODY 0x48
#define OBEX_HEADER_END_OF_BODY 0x49
#define OBEX_HEADER_COUNT 0xC0
#define OBEX_HEADER_NAME 0x01
#define OBEX_HEADER_TYPE 0x42
#define OBEX_HEADER_LENGTH 0xC3
#define OBEX_HEADER_TIME_ISO_8601 0x44
#define OBEX_HEADER_TIME_4_BYTE 0xC4
#define OBEX_HEADER_DESCRIPTION 0x05
#define OBEX_HEADER_TARGET 0x46
#define OBEX_HEADER_HTTP 0x47
#define OBEX_HEADER_WHO 0x4A
#define OBEX_HEADER_OBJECT_CLASS 0x4F
#define OBEX_HEADER_APPLICATION_PARAMETERS 0x4C
#define OBEX_HEADER_CONNECTION_ID 0xCb
#define OBEX_HEADER_BODY 0x48
#define OBEX_HEADER_END_OF_BODY 0x49
#define OBEX_HEADER_COUNT 0xC0
#define OBEX_HEADER_NAME 0x01
#define OBEX_HEADER_TYPE 0x42
#define OBEX_HEADER_LENGTH 0xC3
#define OBEX_HEADER_TIME_ISO_8601 0x44
#define OBEX_HEADER_TIME_4_BYTE 0xC4
#define OBEX_HEADER_DESCRIPTION 0x05
#define OBEX_HEADER_TARGET 0x46
#define OBEX_HEADER_HTTP 0x47
#define OBEX_HEADER_WHO 0x4A
#define OBEX_HEADER_OBJECT_CLASS 0x4F
#define OBEX_HEADER_APPLICATION_PARAMETERS 0x4C
#define OBEX_HEADER_CONNECTION_ID 0xCB
#define OBEX_HEADER_AUTHENTICATION_CHALLENGE 0x4D
#define OBEX_HEADER_AUTHENTICATION_RESPONSE 0x4E
#define OBEX_OPCODE_FINAL_BIT_MASK 0x80
#define OBEX_VERSION 0x14
@ -115,5 +120,7 @@
#define PBAP_APPLICATION_PARAMETER_VCARD_SELECTOR_OPERATOR 0x0E
// ResetNewMissedCalls - 0x0F - 1 byte
#define PBAP_APPLICATION_PARAMETER_RESET_NEW_MISSED_CALLS 0x0F
// PbapSupportedFeatures - 0x10 - 4 bytes
#define PBAP_APPLICATION_PARAMETER_PBAP_SUPPORTED_FEATURES 0x10
#endif

View File

@ -156,10 +156,11 @@ const uint8_t * obex_iterator_get_data(const obex_iterator_t * context){
}
void obex_dump_packet(uint8_t request_opcode, uint8_t * packet, uint16_t size){
// printf("RCV: '");
// printf_hexdump(packet, size);
obex_iterator_t it;
printf("Opcode: 0x%02x\n", packet[0]);
printf("OBEX Opcode: 0x%02x\n", request_opcode);
int header_offset = request_opcode == OBEX_OPCODE_CONNECT ? 7 : 3;
printf("OBEX Header: ");
printf_hexdump(packet, header_offset);
for (obex_iterator_init_with_response_packet(&it, request_opcode, packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
printf("HI: %x - ", hi);

View File

@ -74,6 +74,7 @@
#include "bluetooth_sdp.h"
#include "classic/sdp_client_rfcomm.h"
#include "btstack_event.h"
#include "md5.h"
#include "classic/obex.h"
#include "classic/obex_iterator.h"
@ -90,6 +91,8 @@ typedef enum {
PBAP_W4_GOEP_CONNECTION,
PBAP_W2_SEND_CONNECT_REQUEST,
PBAP_W4_CONNECT_RESPONSE,
PBAP_W4_USER_AUTHENTICATION,
PBAP_W2_SEND_AUTHENTICATED_CONNECT,
PBAP_CONNECT_RESPONSE_RECEIVED,
PBAP_CONNECTED,
//
@ -116,6 +119,9 @@ typedef struct pbap_client {
btstack_packet_handler_t client_handler;
const char * current_folder;
uint16_t set_path_offset;
uint8_t authentication_options;
uint16_t authentication_nonce[16];
const char * authentication_password;
} pbap_client_t;
static pbap_client_t _pbap_client;
@ -183,19 +189,70 @@ static void pbap_client_emit_phonebook_size_event(pbap_client_t * context, uint8
context->client_handler(HCI_EVENT_PACKET, context->cid, &event[0], pos);
}
static void pbap_client_emit_authentication_event(pbap_client_t * context, uint8_t options){
// split options
uint8_t user_id_required = options & 1 ? 1 : 0;
uint8_t full_access = options & 2 ? 1 : 0;
uint8_t event[7];
int pos = 0;
event[pos++] = HCI_EVENT_PBAP_META;
pos++; // skip len
event[pos++] = PBAP_SUBEVENT_AUTHENTICATION_REQUEST;
little_endian_store_16(event,pos,context->cid);
pos+=2;
event[pos++] = user_id_required;
event[pos++] = full_access;
if (pos != sizeof(event)) log_error("pbap_client_emit_authentication_event size %u", pos);
context->client_handler(HCI_EVENT_PACKET, context->cid, &event[0], pos);
}
static const uint8_t collon = (uint8_t) ':';
static void pbap_handle_can_send_now(void){
uint8_t path_element[20];
uint16_t path_element_start;
uint16_t path_element_len;
uint8_t application_parameters[20];
uint8_t challenge_response[36];
int i;
MD5_CTX md5_ctx;
switch (pbap_client->state){
case PBAP_W2_SEND_CONNECT_REQUEST:
goep_client_create_connect_request(pbap_client->goep_cid, OBEX_VERSION, 0, OBEX_MAX_PACKETLEN_DEFAULT);
goep_client_add_header_target(pbap_client->goep_cid, 16, pbap_uuid);
// Add PbapSupportedFeatures
application_parameters[0] = PBAP_APPLICATION_PARAMETER_PBAP_SUPPORTED_FEATURES;
application_parameters[1] = 4;
big_endian_store_32(application_parameters, 2, goep_client_get_pbap_supported_features(pbap_client->goep_cid));
goep_client_add_header_application_parameters(pbap_client->goep_cid, 6, &application_parameters[0]);
pbap_client->state = PBAP_W4_CONNECT_RESPONSE;
goep_client_execute(pbap_client->goep_cid);
return;
break;
case PBAP_W2_SEND_AUTHENTICATED_CONNECT:
goep_client_create_connect_request(pbap_client->goep_cid, OBEX_VERSION, 0, OBEX_MAX_PACKETLEN_DEFAULT);
goep_client_add_header_target(pbap_client->goep_cid, 16, pbap_uuid);
// setup authentication challenge response
i = 0;
challenge_response[i++] = 0; // Tag Digest
challenge_response[i++] = 16; // Len
// calculate md5
MD5_Init(&md5_ctx);
MD5_Update(&md5_ctx, pbap_client->authentication_nonce, 16);
MD5_Update(&md5_ctx, &collon, 1);
MD5_Update(&md5_ctx, pbap_client->authentication_password, strlen(pbap_client->authentication_password));
MD5_Final(&challenge_response[i], &md5_ctx);
i += 16;
challenge_response[i++] = 2; // Tag Nonce
challenge_response[i++] = 16; // Len
memcpy(&challenge_response[i], pbap_client->authentication_nonce, 16);
i += 16;
goep_client_add_header_challenge_response(pbap_client->goep_cid, i, challenge_response);
pbap_client->state = PBAP_W4_CONNECT_RESPONSE;
goep_client_execute(pbap_client->goep_cid);
break;
case PBAP_W2_SEND_DISCONNECT_REQUEST:
goep_client_create_disconnect_request(pbap_client->goep_cid);
pbap_client->state = PBAP_W4_DISCONNECT_RESPONSE;
@ -257,6 +314,38 @@ static void pbap_handle_can_send_now(void){
}
}
static void pbap_parse_authentication_challenge(pbap_client_t * context, const uint8_t * challenge_data, uint16_t challenge_len){
// printf("Challenge: ");
// printf_hexdump(challenge_data, challenge_len);
int i;
// uint8_t charset_code = 0;
for (i=0 ; i<challenge_len ; ){
int tag = challenge_data[i];
int len = challenge_data[i + 1];
i += 2;
switch (tag) {
case 0:
if (len != 0x10) {
log_error("Invalid OBEX digest len %u", len);
return;
}
memcpy(context->authentication_nonce, &challenge_data[i], 16);
// printf("Nonce: ");
// printf_hexdump(context->authentication_nonce, 16);
break;
case 1:
context->authentication_options = challenge_data[i];
// printf("Options %u\n", context->authentication_options);
break;
case 2:
// TODO: handle charset
// charset_code = challenge_data[i];
break;
}
i += len;
}
}
static void pbap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel); // ok: there is no channel
@ -303,24 +392,37 @@ static void pbap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *
break;
case GOEP_DATA_PACKET:
// TODO: handle chunked data
#if 0
obex_dump_packet(goep_client_get_request_opcode(pbap_client->goep_cid), packet, size);
#if 1
// obex_dump_packet(goep_client_get_request_opcode(pbap_client->goep_cid), packet, size);
#endif
switch (pbap_client->state){
case PBAP_W4_CONNECT_RESPONSE:
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(pbap_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
if (hi == OBEX_HEADER_CONNECTION_ID){
goep_client_set_connection_id(pbap_client->goep_cid, obex_iterator_get_data_32(&it));
}
}
if (packet[0] == OBEX_RESP_SUCCESS){
pbap_client->state = PBAP_CONNECTED;
pbap_client_emit_connected_event(pbap_client, 0);
} else {
log_info("pbap: obex connect failed, result 0x%02x", packet[0]);
pbap_client->state = PBAP_INIT;
pbap_client_emit_connected_event(pbap_client, OBEX_CONNECT_FAILED);
switch (packet[0]){
case OBEX_RESP_SUCCESS:
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(pbap_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
if (hi == OBEX_HEADER_CONNECTION_ID){
goep_client_set_connection_id(pbap_client->goep_cid, obex_iterator_get_data_32(&it));
}
}
pbap_client->state = PBAP_CONNECTED;
pbap_client_emit_connected_event(pbap_client, 0);
break;
case OBEX_RESP_UNAUTHORIZED:
for (obex_iterator_init_with_response_packet(&it, goep_client_get_request_opcode(pbap_client->goep_cid), packet, size); obex_iterator_has_more(&it) ; obex_iterator_next(&it)){
uint8_t hi = obex_iterator_get_hi(&it);
if (hi == OBEX_HEADER_AUTHENTICATION_CHALLENGE){
pbap_parse_authentication_challenge(pbap_client, obex_iterator_get_data(&it), obex_iterator_get_data_len(&it));
}
}
pbap_client->state = PBAP_W4_USER_AUTHENTICATION;
pbap_client_emit_authentication_event(pbap_client, pbap_client->authentication_options);
break;
default:
log_info("pbap: obex connect failed, result 0x%02x", packet[0]);
pbap_client->state = PBAP_INIT;
pbap_client_emit_connected_event(pbap_client, OBEX_CONNECT_FAILED);
break;
}
break;
case PBAP_W4_DISCONNECT_RESPONSE:
@ -451,3 +553,12 @@ uint8_t pbap_set_phonebook(uint16_t pbap_cid, const char * path){
goep_client_request_can_send_now(pbap_client->goep_cid);
return 0;
}
uint8_t pbap_authentication_password(uint16_t pbap_cid, const char * password){
UNUSED(pbap_cid);
if (pbap_client->state != PBAP_W4_USER_AUTHENTICATION) return BTSTACK_BUSY;
pbap_client->state = PBAP_W2_SEND_AUTHENTICATED_CONNECT;
pbap_client->authentication_password = password;
goep_client_request_can_send_now(pbap_client->goep_cid);
return 0;
}

View File

@ -60,6 +60,13 @@ void pbap_client_init(void);
*/
uint8_t pbap_connect(btstack_packet_handler_t handler, bd_addr_t addr, uint16_t * out_cid);
/**
* @brief Provide password for OBEX Authentication after receiving PBAP_SUBEVENT_AUTHENTICATION_REQUEST
* @param pbap_cid
* @param password (null terminated string) - not copied, needs to stay valid until connection completed
*/
uint8_t pbap_authentication_password(uint16_t pbap_cid, const char * password);
/**
* @brief Disconnects PBAP connection with given identifier.
* @param pbap_cid

View File

@ -1826,6 +1826,8 @@ static void event_handler(uint8_t *packet, int size){
hci_con_handle_t handle;
hci_connection_t * conn;
int i;
int create_connection_cmd;
#ifdef ENABLE_CLASSIC
uint8_t link_type;
#endif
@ -1954,9 +1956,18 @@ static void event_handler(uint8_t *packet, int size){
hci_stack->num_cmd_packets = packet[3] ? 1 : 0;
// check command status to detected failed outgoing connections
if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_create_connection) ||
HCI_EVENT_IS_COMMAND_STATUS(packet, hci_le_create_connection)) {
create_connection_cmd = 0;
#ifdef ENABLE_CLASSIC
if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_create_connection)){
create_connection_cmd = 1;
}
#endif
#ifdef ENABLE_LE_CENTRAL
if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_le_create_connection)){
create_connection_cmd = 1;
}
#endif
if (create_connection_cmd) {
uint8_t status = hci_event_command_status_get_status(packet);
conn = hci_connection_for_bd_addr_and_type(hci_stack->outgoing_addr, hci_stack->outgoing_addr_type);
log_info("command status (create connection), status %x, connection %p, addr %s, type %x", status, conn, bd_addr_to_str(hci_stack->outgoing_addr), hci_stack->outgoing_addr_type);