mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-26 21:35:16 +00:00
Merge branch 'develop' of https://github.com/bluekitchen/btstack into develop
This commit is contained in:
commit
1c5286ef85
@ -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
|
||||
|
@ -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 |
|
||||
|
@ -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
2
chipset/intel/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.ddc
|
||||
*.sfi
|
28
chipset/intel/Makefile.inc
Normal file
28
chipset/intel/Makefile.inc
Normal 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)
|
||||
|
430
chipset/intel/btstack_chipset_intel_firmware.c
Normal file
430
chipset/intel/btstack_chipset_intel_firmware.c
Normal 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);
|
||||
}
|
71
chipset/intel/btstack_chipset_intel_firmware.h
Normal file
71
chipset/intel/btstack_chipset_intel_firmware.h
Normal 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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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){
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
2
port/daemon/src/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.ddc
|
||||
*.sfi
|
@ -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 $@
|
||||
|
@ -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 \
|
||||
|
@ -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
72
port/libusb-intel/.gitignore
vendored
Normal 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
|
53
port/libusb-intel/Makefile
Normal file
53
port/libusb-intel/Makefile
Normal 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}
|
||||
|
86
port/libusb-intel/README.md
Normal file
86
port/libusb-intel/README.md
Normal 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!
|
36
port/libusb-intel/btstack_config.h
Normal file
36
port/libusb-intel/btstack_config.h
Normal 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
204
port/libusb-intel/main.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
39
port/windows-winusb-intel/.gitignore
vendored
Normal 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*
|
39
port/windows-winusb-intel/Makefile
Normal file
39
port/windows-winusb-intel/Makefile
Normal 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}
|
43
port/windows-winusb-intel/README.md
Normal file
43
port/windows-winusb-intel/README.md
Normal 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
|
||||
|
33
port/windows-winusb-intel/btstack_config.h
Normal file
33
port/windows-winusb-intel/btstack_config.h
Normal 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
|
193
port/windows-winusb-intel/main.c
Normal file
193
port/windows-winusb-intel/main.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
17
src/hci.c
17
src/hci.c
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user