Lower baudrate

This commit is contained in:
Carsten Schmiemann 2024-06-30 18:24:27 +02:00
parent 0e174ca570
commit 74ced478e0
23 changed files with 2576 additions and 2118 deletions

View file

@ -55,7 +55,7 @@ class SnifferBREDR:
# Constructor # Constructor
def __init__(self, def __init__(self,
serial_port=None, serial_port=None,
serial_baud=921600, serial_baud=460800,
show_summary=True, show_summary=True,
start_wireshark=False, start_wireshark=False,
save_pcap=True, save_pcap=True,
@ -187,7 +187,7 @@ class SnifferBREDR:
# Defaults # Defaults
serial_port = '/dev/ttyUSB0' serial_port = '/dev/ttyUSB0'
serial_baud = 921600 serial_baud = 460800
@click.command() @click.command()

View file

@ -1,4 +1,9 @@
# *BrakTooth* ESP32 BR/EDR Active Sniffer/Injector # Fork informations
This is a 1:1 fork of the following project.
My version has a lowered baudrate for host communication because of cheap ESP DevBoards.
## *BrakTooth* ESP32 BR/EDR Active Sniffer/Injector
> Simple "Monitor mode" for Bluetooth Classic. Sniff or inject BR/EDR Baseband packets in ESP32 BT connections. > Simple "Monitor mode" for Bluetooth Classic. Sniff or inject BR/EDR Baseband packets in ESP32 BT connections.

View file

@ -49,31 +49,29 @@
#include "btstack_chipset_em9301.h" #include "btstack_chipset_em9301.h"
#include "btstack_debug.h" #include "btstack_debug.h"
#include <stddef.h> /* NULL */ #include <stddef.h> /* NULL */
#include <string.h> /* memcpy */ #include <string.h> /* memcpy */
#include "hci.h" #include "hci.h"
// should go to some common place // should go to some common place
#define OPCODE(ogf, ocf) (ocf | ogf << 10) #define OPCODE(ogf, ocf) (ocf | ogf << 10)
#define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27) #define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27)
#define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28) #define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28)
#define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29) #define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29)
#define HCI_OPCODE_EM_CPU_RESET (0xFC32) #define HCI_OPCODE_EM_CPU_RESET (0xFC32)
/** /**
* @param bd_addr * @param bd_addr
*/ */
const hci_cmd_t hci_vendor_em_set_public_address = { const hci_cmd_t hci_vendor_em_set_public_address = {
0xFC02, "B" 0xFC02, "B"};
};
/** /**
* @param baud_rate_index * @param baud_rate_index
*/ */
const hci_cmd_t hci_vendor_em_set_uart_baudrate = { const hci_cmd_t hci_vendor_em_set_uart_baudrate = {
0xFC07, "1" 0xFC07, "1"};
};
/** /**
* @param transmitter_test_mode * @param transmitter_test_mode
@ -82,216 +80,227 @@ const hci_cmd_t hci_vendor_em_set_uart_baudrate = {
* @param packet_payload_type * @param packet_payload_type
*/ */
const hci_cmd_t hci_vendor_em_transmitter_test = { const hci_cmd_t hci_vendor_em_transmitter_test = {
0xFC11, "1111" 0xFC11, "1111"};
};
/** /**
*/ */
const hci_cmd_t hci_vendor_em_transmitter_test_end = { const hci_cmd_t hci_vendor_em_transmitter_test_end = {
0xFC12, "" 0xFC12, ""};
};
/** /**
* @param patch_index * @param patch_index
*/ */
const hci_cmd_t hci_vendor_em_patch_query = { const hci_cmd_t hci_vendor_em_patch_query = {
0xFC34, "2" 0xFC34, "2"};
};
/** /**
* Change the state of the selected memory. * Change the state of the selected memory.
* @param memory_attribute * @param memory_attribute
*/ */
const hci_cmd_t hci_vendor_em_set_memory_mode = { const hci_cmd_t hci_vendor_em_set_memory_mode = {
0xFC2B, "1" 0xFC2B, "1"};
};
/** /**
* @param sleep_option_settings * @param sleep_option_settings
*/ */
const hci_cmd_t hci_vendor_em_set_sleep_options = { const hci_cmd_t hci_vendor_em_set_sleep_options = {
0xFC2D, "1" 0xFC2D, "1"};
};
// baudrate to index for hci_vendor_em_set_uart_baudrate // baudrate to index for hci_vendor_em_set_uart_baudrate
static const uint32_t baudrates[] = { static const uint32_t baudrates[] = {
0, 0,
0, 0,
0, 0,
9600, 9600,
14400, 14400,
19200, 19200,
28800, 28800,
38400, 38400,
57600, 57600,
76800, 76800,
115200, 115200,
230400, 230400,
460800, 460800,
921600, 460800,
1843200, 1843200,
}; };
#ifdef HAVE_EM9304_PATCH_CONTAINER #ifdef HAVE_EM9304_PATCH_CONTAINER
extern const uint8_t container_blob_data[]; extern const uint8_t container_blob_data[];
extern const uint32_t container_blob_size; extern const uint32_t container_blob_size;
static uint32_t container_blob_offset = 0; static uint32_t container_blob_offset = 0;
static uint32_t container_end; // current container static uint32_t container_end; // current container
static uint16_t patch_sequence_number; static uint16_t patch_sequence_number;
static int em_cpu_reset_sent; static int em_cpu_reset_sent;
static enum { static enum {
UPLOAD_IDLE, UPLOAD_IDLE,
UPLOAD_ACTIVE, UPLOAD_ACTIVE,
} upload_state; } upload_state;
// CRC32 implementation using 4-bit lookup table created by pycrc v0.9.1, https://pycrc.org // CRC32 implementation using 4-bit lookup table created by pycrc v0.9.1, https://pycrc.org
// ./pycrc.py --model crc-32 --algorithm table-driven --table-idx-width=4 --generate c // ./pycrc.py --model crc-32 --algorithm table-driven --table-idx-width=4 --generate c
static const uint32_t crc32_table[16] = { static const uint32_t crc32_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
};
static uint32_t btstack_crc32(const uint8_t *buf, uint16_t size){ static uint32_t btstack_crc32(const uint8_t *buf, uint16_t size)
{
uint16_t pos; uint16_t pos;
uint32_t crc = 0xffffffff; uint32_t crc = 0xffffffff;
for (pos=0 ; pos<size ; pos++){ for (pos = 0; pos < size; pos++)
int tbl_idx = crc ^ buf[pos]; {
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); int tbl_idx = crc ^ buf[pos];
tbl_idx = crc ^ (buf[pos] >> 4); crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4); tbl_idx = crc ^ (buf[pos] >> 4);
} crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
}
return ~crc; return ~crc;
} }
#endif #endif
static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer)
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02)); {
hci_cmd_buffer[2] = 0x06; little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02));
reverse_bd_addr(addr, &hci_cmd_buffer[3]); hci_cmd_buffer[2] = 0x06;
reverse_bd_addr(addr, &hci_cmd_buffer[3]);
} }
static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer)
{
// lookup baudrates // lookup baudrates
int i; int i;
int found = 0; int found = 0;
for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){ for (i = 0; i < sizeof(baudrates) / sizeof(uint32_t); i++)
if (baudrates[i] == baudrate){ {
if (baudrates[i] == baudrate)
{
found = i; found = i;
break; break;
} }
} }
if (!found){ if (!found)
{
log_error("Baudrate %u not found in table", baudrate); log_error("Baudrate %u not found in table", baudrate);
return; return;
} }
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07)); little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07));
hci_cmd_buffer[2] = 0x01; hci_cmd_buffer[2] = 0x01;
hci_cmd_buffer[3] = i; hci_cmd_buffer[3] = i;
} }
#ifdef HAVE_EM9304_PATCH_CONTAINER #ifdef HAVE_EM9304_PATCH_CONTAINER
static void chipset_init(const void * config){ static void chipset_init(const void *config)
{
UNUSED(config); UNUSED(config);
container_blob_offset = 0; container_blob_offset = 0;
em_cpu_reset_sent = 0; em_cpu_reset_sent = 0;
upload_state = UPLOAD_IDLE; upload_state = UPLOAD_IDLE;
} }
static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){ static btstack_chipset_result_t chipset_next_command(uint8_t *hci_cmd_buffer)
{
log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size); log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size);
if (container_blob_offset >= container_blob_size) { if (container_blob_offset >= container_blob_size)
if (0 == em_cpu_reset_sent){ {
// send EM CPU Reset if (0 == em_cpu_reset_sent)
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET); {
hci_cmd_buffer[2] = 0; // send EM CPU Reset
em_cpu_reset_sent = 1; little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET);
return BTSTACK_CHIPSET_VALID_COMMAND; hci_cmd_buffer[2] = 0;
} else { em_cpu_reset_sent = 1;
return BTSTACK_CHIPSET_DONE; return BTSTACK_CHIPSET_VALID_COMMAND;
} }
} else
{
return BTSTACK_CHIPSET_DONE;
}
}
uint32_t tag; uint32_t tag;
uint16_t bytes_to_upload; uint16_t bytes_to_upload;
uint32_t crc; uint32_t crc;
uint32_t container_size; uint32_t container_size;
switch (upload_state){ switch (upload_state)
case UPLOAD_IDLE: {
// check for 'em93' tag case UPLOAD_IDLE:
tag = little_endian_read_32(container_blob_data, container_blob_offset); // check for 'em93' tag
if (0x656d3933 != tag) { tag = little_endian_read_32(container_blob_data, container_blob_offset);
log_error("Expected 0x656d3933 ('em934') but got %08x", (int) tag); if (0x656d3933 != tag)
return BTSTACK_CHIPSET_DONE; {
} log_error("Expected 0x656d3933 ('em934') but got %08x", (int)tag);
// fetch info for current container return BTSTACK_CHIPSET_DONE;
container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4); }
container_end = container_blob_offset + container_size; // fetch info for current container
// start uploading (<= 59 bytes) container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4);
patch_sequence_number = 1; container_end = container_blob_offset + container_size;
bytes_to_upload = btstack_min(59, container_end - container_blob_offset); // start uploading (<= 59 bytes)
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); patch_sequence_number = 1;
log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u", bytes_to_upload = btstack_min(59, container_end - container_blob_offset);
(int) container_blob_data[container_blob_offset+9], crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
(int) container_blob_data[container_blob_offset+10], log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u",
(int) little_endian_read_16(container_blob_data, container_blob_offset+12), (int)container_blob_data[container_blob_offset + 9],
(int) little_endian_read_16(container_blob_data, container_blob_offset+14), (int)container_blob_data[container_blob_offset + 10],
(int) container_size); (int)little_endian_read_16(container_blob_data, container_blob_offset + 12),
// build command (int)little_endian_read_16(container_blob_data, container_blob_offset + 14),
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START); (int)container_size);
hci_cmd_buffer[2] = 5 + bytes_to_upload; // build command
hci_cmd_buffer[3] = 0; // upload to iRAM1 little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START);
little_endian_store_32(hci_cmd_buffer, 4, crc); hci_cmd_buffer[2] = 5 + bytes_to_upload;
memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload); hci_cmd_buffer[3] = 0; // upload to iRAM1
container_blob_offset += bytes_to_upload; little_endian_store_32(hci_cmd_buffer, 4, crc);
if (container_blob_offset < container_end){ memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload);
upload_state = UPLOAD_ACTIVE; container_blob_offset += bytes_to_upload;
} if (container_blob_offset < container_end)
return BTSTACK_CHIPSET_VALID_COMMAND; {
case UPLOAD_ACTIVE: upload_state = UPLOAD_ACTIVE;
// Upload next segement }
bytes_to_upload = btstack_min(58, container_end - container_blob_offset); return BTSTACK_CHIPSET_VALID_COMMAND;
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload); case UPLOAD_ACTIVE:
// build command // Upload next segement
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE); bytes_to_upload = btstack_min(58, container_end - container_blob_offset);
hci_cmd_buffer[2] = 6 + bytes_to_upload; crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++); // build command
little_endian_store_32(hci_cmd_buffer, 5, crc); little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE);
memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload); hci_cmd_buffer[2] = 6 + bytes_to_upload;
container_blob_offset += bytes_to_upload; little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++);
if (container_blob_offset >= container_end){ little_endian_store_32(hci_cmd_buffer, 5, crc);
log_info("container done maybe another one"); memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload);
upload_state = UPLOAD_IDLE; container_blob_offset += bytes_to_upload;
} if (container_blob_offset >= container_end)
return BTSTACK_CHIPSET_VALID_COMMAND; {
default: log_info("container done maybe another one");
btstack_assert(false); upload_state = UPLOAD_IDLE;
break; }
return BTSTACK_CHIPSET_VALID_COMMAND;
default:
btstack_assert(false);
break;
} }
return BTSTACK_CHIPSET_DONE; return BTSTACK_CHIPSET_DONE;
} }
#endif #endif
static const btstack_chipset_t btstack_chipset_em9301 = { static const btstack_chipset_t btstack_chipset_em9301 = {
"EM9301", "EM9301",
#ifdef HAVE_EM9304_PATCH_CONTAINER #ifdef HAVE_EM9304_PATCH_CONTAINER
chipset_init, chipset_init,
chipset_next_command, chipset_next_command,
#else #else
NULL, NULL,
NULL, NULL,
#endif #endif
chipset_set_baudrate_command, chipset_set_baudrate_command,
chipset_set_bd_addr_command, chipset_set_bd_addr_command,
}; };
// MARK: public API // MARK: public API
const btstack_chipset_t * btstack_chipset_em9301_instance(void){ const btstack_chipset_t *btstack_chipset_em9301_instance(void)
return &btstack_chipset_em9301; {
return &btstack_chipset_em9301;
} }

View file

@ -47,56 +47,59 @@
#include "btstack_config.h" #include "btstack_config.h"
#include "btstack_chipset_stlc2500d.h" #include "btstack_chipset_stlc2500d.h"
#include <stddef.h> /* NULL */ #include <stddef.h> /* NULL */
#include <stdio.h> #include <stdio.h>
#include <string.h> /* memcpy */ #include <string.h> /* memcpy */
#include "hci.h" #include "hci.h"
#include "btstack_debug.h" #include "btstack_debug.h"
// should go to some common place // should go to some common place
#define OPCODE(ogf, ocf) (ocf | ogf << 10) #define OPCODE(ogf, ocf) (ocf | ogf << 10)
static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer)
{
// map baud rate to predefined settings // map baud rate to predefined settings
int preset = 0; int preset = 0;
switch (baudrate){ switch (baudrate)
case 57600: {
preset = 0x0e; case 57600:
break; preset = 0x0e;
case 115200: break;
preset = 0x10; case 115200:
break; preset = 0x10;
case 230400: break;
preset = 0x12; case 230400:
break; preset = 0x12;
case 460800: break;
preset = 0x13; case 460800:
break; preset = 0x13;
case 921600: break;
preset = 0x14; case 460800:
break; preset = 0x14;
case 1843200: break;
preset = 0x16; case 1843200:
break; preset = 0x16;
case 2000000: break;
preset = 0x19; case 2000000:
break; preset = 0x19;
case 3000000: break;
preset = 0x1b; case 3000000:
break; preset = 0x1b;
case 4000000: break;
preset = 0x1f; case 4000000:
break; preset = 0x1f;
default: break;
log_error("stlc2500d_baudrate_cmd baudrate %u not supported", baudrate); default:
return; log_error("stlc2500d_baudrate_cmd baudrate %u not supported", baudrate);
return;
} }
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0xfc)); little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0xfc));
hci_cmd_buffer[2] = 0x01; hci_cmd_buffer[2] = 0x01;
hci_cmd_buffer[3] = preset; hci_cmd_buffer[3] = preset;
} }
static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer)
{
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x22)); little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x22));
hci_cmd_buffer[2] = 0x08; hci_cmd_buffer[2] = 0x08;
hci_cmd_buffer[3] = 254; hci_cmd_buffer[3] = 254;
@ -113,6 +116,7 @@ static const btstack_chipset_t btstack_chipset_stlc2500d = {
}; };
// MARK: public API // MARK: public API
const btstack_chipset_t * btstack_chipset_stlc2500d_instance(void){ const btstack_chipset_t *btstack_chipset_stlc2500d_instance(void)
{
return &btstack_chipset_stlc2500d; return &btstack_chipset_stlc2500d;
} }

View file

@ -50,40 +50,42 @@
#include "btstack_config.h" #include "btstack_config.h"
#include "btstack_chipset_tc3566x.h" #include "btstack_chipset_tc3566x.h"
#include <stddef.h> /* NULL */ #include <stddef.h> /* NULL */
#include <stdio.h> #include <stdio.h>
#include <string.h> /* memcpy */ #include <string.h> /* memcpy */
#include "hci.h" #include "hci.h"
#include "btstack_debug.h" #include "btstack_debug.h"
// should go to some common place // should go to some common place
#define OPCODE(ogf, ocf) (ocf | ogf << 10) #define OPCODE(ogf, ocf) (ocf | ogf << 10)
static const uint8_t baudrate_command[] = { 0x08, 0xfc, 0x11, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x14, 0x42, 0xff, 0x10, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const uint8_t baudrate_command[] = {0x08, 0xfc, 0x11, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x14, 0x42, 0xff, 0x10, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer){ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buffer)
{
uint16_t div1 = 0; uint16_t div1 = 0;
uint8_t div2 = 0; uint8_t div2 = 0;
switch (baudrate) { switch (baudrate)
case 115200: {
div1 = 0x001A; case 115200:
div2 = 0x60; div1 = 0x001A;
break; div2 = 0x60;
case 230400: break;
div1 = 0x000D; case 230400:
div2 = 0x60; div1 = 0x000D;
break; div2 = 0x60;
case 460800: break;
div1 = 0x0005; case 460800:
div2 = 0xA0; div1 = 0x0005;
break; div2 = 0xA0;
case 921600: break;
div1 = 0x0003; case 460800:
div2 = 0x70; div1 = 0x0003;
break; div2 = 0x70;
default: break;
log_error("tc3566x_baudrate_cmd baudrate %u not supported", baudrate); default:
return; log_error("tc3566x_baudrate_cmd baudrate %u not supported", baudrate);
return;
} }
memcpy(hci_cmd_buffer, baudrate_command, sizeof(baudrate_command)); memcpy(hci_cmd_buffer, baudrate_command, sizeof(baudrate_command));
@ -91,7 +93,8 @@ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buf
hci_cmd_buffer[15] = div2; hci_cmd_buffer[15] = div2;
} }
static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){ static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer)
{
// OGF 0x04 - Informational Parameters, OCF 0x10 // OGF 0x04 - Informational Parameters, OCF 0x10
hci_cmd_buffer[0] = 0x13; hci_cmd_buffer[0] = 0x13;
hci_cmd_buffer[1] = 0x10; hci_cmd_buffer[1] = 0x10;
@ -108,6 +111,7 @@ static const btstack_chipset_t btstack_chipset_tc3566x = {
}; };
// MARK: public API // MARK: public API
const btstack_chipset_t * btstack_chipset_tc3566x_instance(void){ const btstack_chipset_t *btstack_chipset_tc3566x_instance(void)
{
return &btstack_chipset_tc3566x; return &btstack_chipset_tc3566x;
} }

View file

@ -51,8 +51,6 @@
*/ */
// ***************************************************************************** // *****************************************************************************
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -64,15 +62,15 @@
#include "btstack_stdin.h" #include "btstack_stdin.h"
#endif #endif
static uint8_t hsp_service_buffer[150]; static uint8_t hsp_service_buffer[150];
static const uint8_t rfcomm_channel_nr = 1; static const uint8_t rfcomm_channel_nr = 1;
static const char hsp_ag_service_name[] = "Audio Gateway Test"; static const char hsp_ag_service_name[] = "Audio Gateway Test";
static uint16_t sco_handle = HCI_CON_HANDLE_INVALID; static uint16_t sco_handle = HCI_CON_HANDLE_INVALID;
static char hs_cmd_buffer[100]; static char hs_cmd_buffer[100];
static const char * device_name = "HSP AG Demo 00:00:00:00:00:00"; static const char *device_name = "HSP AG Demo 00:00:00:00:00:00";
static const char * device_addr_string = "00:1b:dc:07:32:ef"; static const char *device_addr_string = "00:1b:dc:07:32:ef";
static bd_addr_t device_addr; static bd_addr_t device_addr;
/* @section Audio Transfer Setup /* @section Audio Transfer Setup
@ -81,12 +79,12 @@ static bd_addr_t device_addr;
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined. * To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
* *
* Tested working setups: * Tested working setups:
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud * - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 460800 baud
* - Ubuntu 14 64-bit, CSR USB dongle * - Ubuntu 14 64-bit, CSR USB dongle
* - OS X 10.11, CSR USB dongle * - OS X 10.11, CSR USB dongle
* *
* Broken setups: * Broken setups:
* - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 921600 baud * - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 460800 baud
* - select(..) blocks > 400 ms -> num completed is received to late -> gaps between audio * - select(..) blocks > 400 ms -> num completed is received to late -> gaps between audio
* - looks like bug in select->FTDI driver as it works correct on Linux * - looks like bug in select->FTDI driver as it works correct on Linux
* *
@ -98,10 +96,9 @@ static bd_addr_t device_addr;
* *
*/ */
#ifdef HAVE_BTSTACK_STDIN #ifdef HAVE_BTSTACK_STDIN
static void show_usage(void){ static void show_usage(void)
{
bd_addr_t iut_address; bd_addr_t iut_address;
gap_local_bd_addr(iut_address); gap_local_bd_addr(iut_address);
@ -123,155 +120,174 @@ static void show_usage(void){
printf("\n"); printf("\n");
} }
static void stdin_process(char c){ static void stdin_process(char c)
switch (c){ {
case 'a': switch (c)
printf("Establish audio connection\n"); {
hsp_ag_establish_audio_connection(); case 'a':
break; printf("Establish audio connection\n");
case 'A': hsp_ag_establish_audio_connection();
printf("Release audio connection\n"); break;
hsp_ag_release_audio_connection(); case 'A':
break; printf("Release audio connection\n");
case 'c': hsp_ag_release_audio_connection();
printf("Connect to %s\n", device_addr_string); break;
hsp_ag_connect(device_addr); case 'c':
break; printf("Connect to %s\n", device_addr_string);
case 'C': hsp_ag_connect(device_addr);
printf("Disconnect.\n"); break;
hsp_ag_disconnect(); case 'C':
break; printf("Disconnect.\n");
case 'D': hsp_ag_disconnect();
printf("Deleting all link keys\n"); break;
gap_delete_all_link_keys(); case 'D':
break; printf("Deleting all link keys\n");
case 'm': gap_delete_all_link_keys();
printf("Setting microphone gain 8\n"); break;
hsp_ag_set_microphone_gain(8); case 'm':
break; printf("Setting microphone gain 8\n");
case 'M': hsp_ag_set_microphone_gain(8);
printf("Setting microphone gain 15\n"); break;
hsp_ag_set_microphone_gain(15); case 'M':
break; printf("Setting microphone gain 15\n");
case 'o': hsp_ag_set_microphone_gain(15);
printf("Setting speaker gain 0\n"); break;
hsp_ag_set_speaker_gain(0); case 'o':
break; printf("Setting speaker gain 0\n");
case 's': hsp_ag_set_speaker_gain(0);
printf("Setting speaker gain 8\n"); break;
hsp_ag_set_speaker_gain(8); case 's':
break; printf("Setting speaker gain 8\n");
case 'S': hsp_ag_set_speaker_gain(8);
printf("Setting speaker gain 15\n"); break;
hsp_ag_set_speaker_gain(15); case 'S':
break; printf("Setting speaker gain 15\n");
case 'r': hsp_ag_set_speaker_gain(15);
printf("Start ringing\n"); break;
hsp_ag_start_ringing(); case 'r':
break; printf("Start ringing\n");
case 't': hsp_ag_start_ringing();
printf("Stop ringing\n"); break;
hsp_ag_stop_ringing(); case 't':
break; printf("Stop ringing\n");
default: hsp_ag_stop_ringing();
show_usage(); break;
break; default:
show_usage();
break;
} }
} }
#endif #endif
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *event, uint16_t event_size)
{
UNUSED(channel); UNUSED(channel);
uint8_t status; uint8_t status;
switch (packet_type){ switch (packet_type)
case HCI_SCO_DATA_PACKET: {
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle) break; case HCI_SCO_DATA_PACKET:
sco_demo_receive(event, event_size); if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle)
break; break;
sco_demo_receive(event, event_size);
break;
case HCI_EVENT_PACKET: case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(event)) { switch (hci_event_packet_get_type(event))
{
#ifndef HAVE_BTSTACK_STDIN #ifndef HAVE_BTSTACK_STDIN
case BTSTACK_EVENT_STATE: case BTSTACK_EVENT_STATE:
if (btstack_event_state_get_state(event) != HCI_STATE_WORKING) break; if (btstack_event_state_get_state(event) != HCI_STATE_WORKING)
printf("Establish HSP AG service to %s...\n", device_addr_string); break;
hsp_ag_connect(device_addr); printf("Establish HSP AG service to %s...\n", device_addr_string);
break; hsp_ag_connect(device_addr);
break;
#endif #endif
case HCI_EVENT_SCO_CAN_SEND_NOW: case HCI_EVENT_SCO_CAN_SEND_NOW:
sco_demo_send(sco_handle); sco_demo_send(sco_handle);
break;
case HCI_EVENT_HSP_META:
switch (hci_event_hsp_meta_get_subevent_code(event))
{
case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE:
status = hsp_subevent_rfcomm_connection_complete_get_status(event);
if (status != ERROR_CODE_SUCCESS)
{
printf("RFCOMM connection establishement failed with status %u\n", status);
break; break;
case HCI_EVENT_HSP_META: }
switch (hci_event_hsp_meta_get_subevent_code(event)) { printf("RFCOMM connection established.\n");
case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE:
status = hsp_subevent_rfcomm_connection_complete_get_status(event);
if (status != ERROR_CODE_SUCCESS){
printf("RFCOMM connection establishement failed with status %u\n", status);
break;
}
printf("RFCOMM connection established.\n");
#ifndef HAVE_BTSTACK_STDIN #ifndef HAVE_BTSTACK_STDIN
printf("Establish Audio connection to %s...\n", device_addr_string); printf("Establish Audio connection to %s...\n", device_addr_string);
hsp_ag_establish_audio_connection(); hsp_ag_establish_audio_connection();
#endif #endif
break; break;
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event); status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
if (status != ERROR_CODE_SUCCESS){ if (status != ERROR_CODE_SUCCESS)
printf("RFCOMM disconnection failed with status %u.\n", status); {
} else { printf("RFCOMM disconnection failed with status %u.\n", status);
printf("RFCOMM disconnected.\n"); }
} else
break; {
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: printf("RFCOMM disconnected.\n");
status = hsp_subevent_audio_connection_complete_get_status(event); }
if (status != ERROR_CODE_SUCCESS){ break;
printf("Audio connection establishment failed with status %u\n", status); case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
} else { status = hsp_subevent_audio_connection_complete_get_status(event);
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); if (status != ERROR_CODE_SUCCESS)
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); {
hci_request_sco_can_send_now_event(); printf("Audio connection establishment failed with status %u\n", status);
} }
break; else
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: {
printf("Audio connection released.\n\n"); sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
sco_handle = HCI_CON_HANDLE_INVALID; printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
break; hci_request_sco_can_send_now_event();
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: }
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); break;
break; case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: printf("Audio connection released.\n\n");
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); sco_handle = HCI_CON_HANDLE_INVALID;
break; break;
case HSP_SUBEVENT_HS_COMMAND:{ case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
unsigned int cmd_length = hsp_subevent_hs_command_get_value_length(event); break;
unsigned int size = cmd_length <= sizeof(hs_cmd_buffer)? cmd_length : sizeof(hs_cmd_buffer); case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1); printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer); break;
break; case HSP_SUBEVENT_HS_COMMAND:
} {
case HSP_SUBEVENT_BUTTON_PRESSED: memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
if (sco_handle == HCI_CON_HANDLE_INVALID){ unsigned int cmd_length = hsp_subevent_hs_command_get_value_length(event);
printf("Button event -> establish audio\n"); unsigned int size = cmd_length <= sizeof(hs_cmd_buffer) ? cmd_length : sizeof(hs_cmd_buffer);
hsp_ag_establish_audio_connection(); memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1);
} else { printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer);
printf("Button event -> release audio\n"); break;
hsp_ag_release_audio_connection(); }
} case HSP_SUBEVENT_BUTTON_PRESSED:
break; if (sco_handle == HCI_CON_HANDLE_INVALID)
default: {
printf("event not handled %u\n", event[2]); printf("Button event -> establish audio\n");
break; hsp_ag_establish_audio_connection();
} }
break; else
default: {
break; printf("Button event -> release audio\n");
hsp_ag_release_audio_connection();
}
break;
default:
printf("event not handled %u\n", event[2]);
break;
} }
break; break;
default: default:
break; break;
}
break;
default:
break;
} }
} }
@ -290,8 +306,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
*/ */
/* LISTING_START(MainConfiguration): Setup HSP Audio Gateway */ /* LISTING_START(MainConfiguration): Setup HSP Audio Gateway */
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
int btstack_main(int argc, const char * argv[]){ int btstack_main(int argc, const char *argv[])
{
(void)argc; (void)argc;
(void)argv; (void)argv;

View file

@ -68,12 +68,12 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
static uint8_t hsp_service_buffer[150]; static uint8_t hsp_service_buffer[150];
static const uint8_t rfcomm_channel_nr = 1; static const uint8_t rfcomm_channel_nr = 1;
static const char hsp_hs_service_name[] = "Headset Test"; static const char hsp_hs_service_name[] = "Headset Test";
static hci_con_handle_t sco_handle = HCI_CON_HANDLE_INVALID; static hci_con_handle_t sco_handle = HCI_CON_HANDLE_INVALID;
static char hs_cmd_buffer[100]; static char hs_cmd_buffer[100];
// mac 2013: // mac 2013:
static const char * device_addr_string = "84:38:35:65:d1:15"; static const char *device_addr_string = "84:38:35:65:d1:15";
static bd_addr_t device_addr; static bd_addr_t device_addr;
/* @section Audio Transfer Setup /* @section Audio Transfer Setup
@ -82,12 +82,12 @@ static bd_addr_t device_addr;
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined. * To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
* *
* Tested working setups: * Tested working setups:
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud * - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 460800 baud
* - Ubuntu 14 64-bit, CSR USB dongle * - Ubuntu 14 64-bit, CSR USB dongle
* - OS X 10.11, CSR USB dongle * - OS X 10.11, CSR USB dongle
* *
* Broken setups: * Broken setups:
* - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 921600 baud * - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 460800 baud
* - select(..) blocks > 400 ms -> num completed is received to late -> gaps between audio * - select(..) blocks > 400 ms -> num completed is received to late -> gaps between audio
* - looks like bug in select->FTDI driver as it works correct on Linux * - looks like bug in select->FTDI driver as it works correct on Linux
* *
@ -99,8 +99,8 @@ static bd_addr_t device_addr;
* *
*/ */
static void show_usage(void)
static void show_usage(void){ {
bd_addr_t iut_address; bd_addr_t iut_address;
gap_local_bd_addr(iut_address); gap_local_bd_addr(iut_address);
@ -121,139 +121,158 @@ static void show_usage(void){
} }
#ifdef HAVE_BTSTACK_STDIN #ifdef HAVE_BTSTACK_STDIN
static void stdin_process(char c){ static void stdin_process(char c)
switch (c){ {
case 'c': switch (c)
printf("Connect to %s\n", bd_addr_to_str(device_addr)); {
hsp_hs_connect(device_addr); case 'c':
break; printf("Connect to %s\n", bd_addr_to_str(device_addr));
case 'C': hsp_hs_connect(device_addr);
printf("Disconnect.\n"); break;
hsp_hs_disconnect(); case 'C':
break; printf("Disconnect.\n");
case 'a': hsp_hs_disconnect();
printf("Establish audio connection\n"); break;
hsp_hs_establish_audio_connection(); case 'a':
break; printf("Establish audio connection\n");
case 'A': hsp_hs_establish_audio_connection();
printf("Release audio connection\n"); break;
hsp_hs_release_audio_connection(); case 'A':
break; printf("Release audio connection\n");
hsp_hs_release_audio_connection();
break;
case 'z': case 'z':
printf("Setting microphone gain 0\n"); printf("Setting microphone gain 0\n");
hsp_hs_set_microphone_gain(0); hsp_hs_set_microphone_gain(0);
break; break;
case 'm': case 'm':
printf("Setting microphone gain 8\n"); printf("Setting microphone gain 8\n");
hsp_hs_set_microphone_gain(8); hsp_hs_set_microphone_gain(8);
break; break;
case 'M': case 'M':
printf("Setting microphone gain 15\n"); printf("Setting microphone gain 15\n");
hsp_hs_set_microphone_gain(15); hsp_hs_set_microphone_gain(15);
break; break;
case 'o': case 'o':
printf("Setting speaker gain 0\n"); printf("Setting speaker gain 0\n");
hsp_hs_set_speaker_gain(0); hsp_hs_set_speaker_gain(0);
break; break;
case 's': case 's':
printf("Setting speaker gain 8\n"); printf("Setting speaker gain 8\n");
hsp_hs_set_speaker_gain(8); hsp_hs_set_speaker_gain(8);
break; break;
case 'S': case 'S':
printf("Setting speaker gain 15\n"); printf("Setting speaker gain 15\n");
hsp_hs_set_speaker_gain(15); hsp_hs_set_speaker_gain(15);
break; break;
case 'b': case 'b':
printf("Press user button\n"); printf("Press user button\n");
hsp_hs_send_button_press(); hsp_hs_send_button_press();
break; break;
default: default:
show_usage(); show_usage();
break; break;
} }
} }
#endif #endif
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *event, uint16_t event_size)
{
UNUSED(channel); UNUSED(channel);
uint8_t status; uint8_t status;
switch (packet_type){ switch (packet_type)
case HCI_SCO_DATA_PACKET: {
sco_demo_receive(event, event_size); case HCI_SCO_DATA_PACKET:
sco_demo_receive(event, event_size);
break;
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(event))
{
case BTSTACK_EVENT_STATE:
if (btstack_event_state_get_state(event) != HCI_STATE_WORKING)
break;
show_usage();
break; break;
case HCI_EVENT_PACKET: case HCI_EVENT_SCO_CAN_SEND_NOW:
switch (hci_event_packet_get_type(event)) { if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle)
case BTSTACK_EVENT_STATE: break;
if (btstack_event_state_get_state(event) != HCI_STATE_WORKING) break; sco_demo_send(sco_handle);
show_usage(); break;
break; case HCI_EVENT_HSP_META:
case HCI_EVENT_SCO_CAN_SEND_NOW: switch (hci_event_hsp_meta_get_subevent_code(event))
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle) break; {
sco_demo_send(sco_handle); case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE:
break; status = hsp_subevent_rfcomm_connection_complete_get_status(event);
case HCI_EVENT_HSP_META: if (status != ERROR_CODE_SUCCESS)
switch (hci_event_hsp_meta_get_subevent_code(event)) { {
case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: printf("RFCOMM connection establishement failed with status %u\n", status);
status = hsp_subevent_rfcomm_connection_complete_get_status(event); }
if (status != ERROR_CODE_SUCCESS){ else
printf("RFCOMM connection establishement failed with status %u\n", status); {
} else { printf("RFCOMM connection established.\n");
printf("RFCOMM connection established.\n"); }
} break;
break; case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event); if (status != ERROR_CODE_SUCCESS)
if (status != ERROR_CODE_SUCCESS){ {
printf("RFCOMM disconnection failed with status %u.\n", status); printf("RFCOMM disconnection failed with status %u.\n", status);
} else { }
printf("RFCOMM disconnected.\n"); else
} {
break; printf("RFCOMM disconnected.\n");
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: }
status = hsp_subevent_audio_connection_complete_get_status(event); break;
if (status != ERROR_CODE_SUCCESS){ case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
printf("Audio connection establishment failed with status %u\n", status); status = hsp_subevent_audio_connection_complete_get_status(event);
} else { if (status != ERROR_CODE_SUCCESS)
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); {
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); printf("Audio connection establishment failed with status %u\n", status);
hci_request_sco_can_send_now_event(); }
} else
break; {
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
printf("Audio connection released.\n\n"); printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
sco_handle = HCI_CON_HANDLE_INVALID; hci_request_sco_can_send_now_event();
break; }
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: break;
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
break; printf("Audio connection released.\n\n");
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: sco_handle = HCI_CON_HANDLE_INVALID;
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); break;
break; case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
case HSP_SUBEVENT_RING: printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
printf("HS: RING RING!\n"); break;
break; case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
case HSP_SUBEVENT_AG_INDICATION: { printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); break;
unsigned int size = hsp_subevent_ag_indication_get_value_length(event); case HSP_SUBEVENT_RING:
if (size >= sizeof(hs_cmd_buffer)-1){ printf("HS: RING RING!\n");
size = sizeof(hs_cmd_buffer)-1; break;
} case HSP_SUBEVENT_AG_INDICATION:
memcpy(hs_cmd_buffer, hsp_subevent_ag_indication_get_value(event), size); {
printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer); memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
break; unsigned int size = hsp_subevent_ag_indication_get_value_length(event);
} if (size >= sizeof(hs_cmd_buffer) - 1)
default: {
printf("event not handled %u\n", hci_event_hsp_meta_get_subevent_code(event)); size = sizeof(hs_cmd_buffer) - 1;
break; }
} memcpy(hs_cmd_buffer, hsp_subevent_ag_indication_get_value(event), size);
break; printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer);
default: break;
break;
} }
default:
printf("event not handled %u\n", hci_event_hsp_meta_get_subevent_code(event));
break;
}
break;
default: default:
break; break;
}
default:
break;
} }
} }
@ -272,8 +291,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
*/ */
/* LISTING_START(MainConfiguration): Setup HSP Headset */ /* LISTING_START(MainConfiguration): Setup HSP Headset */
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
int btstack_main(int argc, const char * argv[]){ int btstack_main(int argc, const char *argv[])
{
(void)argc; (void)argc;
(void)argv; (void)argv;

View file

@ -56,9 +56,9 @@
#include "btstack_debug.h" #include "btstack_debug.h"
#include "btstack_util.h" #include "btstack_util.h"
#include <stdint.h> #include <stdint.h>
#include <termios.h> /* POSIX terminal control definitions */ #include <termios.h> /* POSIX terminal control definitions */
#include <fcntl.h> /* File control definitions */ #include <fcntl.h> /* File control definitions */
#include <unistd.h> /* UNIX standard function definitions */ #include <unistd.h> /* UNIX standard function definitions */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -70,32 +70,35 @@
#define BRIDGE_RX_BLOCKS_DROP 10 #define BRIDGE_RX_BLOCKS_DROP 10
// data source for integration with BTstack Runloop // data source for integration with BTstack Runloop
static btstack_data_source_t sco_data_source; static btstack_data_source_t sco_data_source;
static sco_format_t sco_format; static sco_format_t sco_format;
static hci_con_handle_t sco_handle; static hci_con_handle_t sco_handle;
// RX // RX
static uint8_t sco_rx_buffer[BRIDGE_BLOCK_SIZE_BYTES]; static uint8_t sco_rx_buffer[BRIDGE_BLOCK_SIZE_BYTES];
static uint16_t sco_rx_bytes_read; static uint16_t sco_rx_bytes_read;
static uint16_t sco_rx_counter; static uint16_t sco_rx_counter;
// TX // TX
static uint8_t sco_tx_packet[BRIDGE_BLOCK_SIZE_BYTES]; static uint8_t sco_tx_packet[BRIDGE_BLOCK_SIZE_BYTES];
static uint16_t sco_tx_packet_pos; static uint16_t sco_tx_packet_pos;
static uint16_t sco_tx_counter; static uint16_t sco_tx_counter;
static void (*posix_i2s_test_bridge_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); static void (*posix_i2s_test_bridge_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
static void posix_i2s_test_bridge_process_write(btstack_data_source_t *ds) { static void posix_i2s_test_bridge_process_write(btstack_data_source_t *ds)
{
ssize_t bytes_to_write = BRIDGE_BLOCK_SIZE_BYTES - sco_tx_packet_pos; ssize_t bytes_to_write = BRIDGE_BLOCK_SIZE_BYTES - sco_tx_packet_pos;
ssize_t bytes_written = write(ds->source.fd, &sco_tx_packet[sco_tx_packet_pos], bytes_to_write); ssize_t bytes_written = write(ds->source.fd, &sco_tx_packet[sco_tx_packet_pos], bytes_to_write);
if (bytes_written < 0) { if (bytes_written < 0)
{
log_error("write returned error"); log_error("write returned error");
return; return;
} }
sco_tx_packet_pos += bytes_written; sco_tx_packet_pos += bytes_written;
if (sco_tx_packet_pos < BRIDGE_BLOCK_SIZE_BYTES) { if (sco_tx_packet_pos < BRIDGE_BLOCK_SIZE_BYTES)
{
return; return;
} }
@ -103,27 +106,31 @@ static void posix_i2s_test_bridge_process_write(btstack_data_source_t *ds) {
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
} }
static void posix_i2s_test_bride_send_packet(const uint8_t *packet, uint16_t length){ static void posix_i2s_test_bride_send_packet(const uint8_t *packet, uint16_t length)
{
// ignore con handle // ignore con handle
btstack_assert( (packet[2]+3) == length); btstack_assert((packet[2] + 3) == length);
uint16_t i; uint16_t i;
switch (sco_format){ switch (sco_format)
case SCO_FORMAT_8_BIT: {
btstack_assert(length == 63); case SCO_FORMAT_8_BIT:
for (i=0;i<60;i++){ btstack_assert(length == 63);
big_endian_store_16(sco_tx_packet, i * 2, packet[ 3 + i ]); for (i = 0; i < 60; i++)
} {
break; big_endian_store_16(sco_tx_packet, i * 2, packet[3 + i]);
case SCO_FORMAT_16_BIT: }
btstack_assert(length == 123); break;
for (i=0;i<60;i++){ case SCO_FORMAT_16_BIT:
sco_tx_packet[ i * 2 ] = packet[4 + i * 2]; btstack_assert(length == 123);
sco_tx_packet[ i * 2 + 1] = packet[3 + i * 2]; for (i = 0; i < 60; i++)
} {
break; sco_tx_packet[i * 2] = packet[4 + i * 2];
default: sco_tx_packet[i * 2 + 1] = packet[3 + i * 2];
btstack_assert(false); }
break; break;
default:
btstack_assert(false);
break;
} }
// start sending // start sending
@ -131,21 +138,25 @@ static void posix_i2s_test_bride_send_packet(const uint8_t *packet, uint16_t len
btstack_run_loop_enable_data_source_callbacks(&sco_data_source, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(&sco_data_source, DATA_SOURCE_CALLBACK_WRITE);
} }
static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds) { static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds)
{
// read up to bytes_to_read data in // read up to bytes_to_read data in
ssize_t bytes_to_read = BRIDGE_BLOCK_SIZE_BYTES - sco_rx_bytes_read; ssize_t bytes_to_read = BRIDGE_BLOCK_SIZE_BYTES - sco_rx_bytes_read;
ssize_t bytes_read = read(ds->source.fd, &sco_rx_buffer[sco_rx_bytes_read], bytes_to_read); ssize_t bytes_read = read(ds->source.fd, &sco_rx_buffer[sco_rx_bytes_read], bytes_to_read);
if (bytes_read == 0){ if (bytes_read == 0)
log_error("read zero bytes of %d bytes", (int) bytes_to_read); {
log_error("read zero bytes of %d bytes", (int)bytes_to_read);
return; return;
} }
if (bytes_read < 0) { if (bytes_read < 0)
{
log_error("read returned error"); log_error("read returned error");
return; return;
} }
sco_rx_bytes_read += bytes_read; sco_rx_bytes_read += bytes_read;
if (sco_rx_bytes_read < BRIDGE_BLOCK_SIZE_BYTES) { if (sco_rx_bytes_read < BRIDGE_BLOCK_SIZE_BYTES)
{
return; return;
} }
@ -153,13 +164,15 @@ static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds) {
sco_rx_bytes_read = 0; sco_rx_bytes_read = 0;
// already active // already active
if (sco_handle == HCI_CON_HANDLE_INVALID) { if (sco_handle == HCI_CON_HANDLE_INVALID)
{
log_info("drop SCO packet, no con Handle yet"); log_info("drop SCO packet, no con Handle yet");
return; return;
} }
// drop first packets // drop first packets
if (sco_rx_counter < BRIDGE_RX_BLOCKS_DROP) { if (sco_rx_counter < BRIDGE_RX_BLOCKS_DROP)
{
sco_rx_counter++; sco_rx_counter++;
log_info("drop packet %u/%u\n", sco_rx_counter, BRIDGE_RX_BLOCKS_DROP); log_info("drop packet %u/%u\n", sco_rx_counter, BRIDGE_RX_BLOCKS_DROP);
return; return;
@ -167,46 +180,53 @@ static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds) {
// setup SCO header // setup SCO header
uint8_t packet[BRIDGE_BLOCK_SIZE_BYTES + 3]; uint8_t packet[BRIDGE_BLOCK_SIZE_BYTES + 3];
little_endian_store_16(packet,0, sco_handle); little_endian_store_16(packet, 0, sco_handle);
uint16_t index; uint16_t index;
switch (sco_format) { switch (sco_format)
case SCO_FORMAT_8_BIT: {
// data is received big endian and transparent data is in lower byte case SCO_FORMAT_8_BIT:
packet[2] = BRIDGE_BLOCK_SIZE_BYTES / 2; // data is received big endian and transparent data is in lower byte
for (index= 0 ; index < (BRIDGE_BLOCK_SIZE_BYTES / 2) ; index++) { packet[2] = BRIDGE_BLOCK_SIZE_BYTES / 2;
packet[3+index] = sco_rx_buffer[2 * index + 1]; for (index = 0; index < (BRIDGE_BLOCK_SIZE_BYTES / 2); index++)
} {
break; packet[3 + index] = sco_rx_buffer[2 * index + 1];
case SCO_FORMAT_16_BIT: }
// data is received big endian but sco packet contains little endian data -> swap bytes break;
packet[2] = BRIDGE_BLOCK_SIZE_BYTES; case SCO_FORMAT_16_BIT:
for (index = 0 ; index < (BRIDGE_BLOCK_SIZE_BYTES / 2) ; index++) { // data is received big endian but sco packet contains little endian data -> swap bytes
packet[3 + 2 * index] = sco_rx_buffer[2 * index + 1]; packet[2] = BRIDGE_BLOCK_SIZE_BYTES;
packet[4 + 2 * index] = sco_rx_buffer[2 * index]; for (index = 0; index < (BRIDGE_BLOCK_SIZE_BYTES / 2); index++)
} {
break; packet[3 + 2 * index] = sco_rx_buffer[2 * index + 1];
default: packet[4 + 2 * index] = sco_rx_buffer[2 * index];
btstack_assert(false); }
break; break;
default:
btstack_assert(false);
break;
} }
(*posix_i2s_test_bridge_packet_handler)(HCI_SCO_DATA_PACKET, packet, 3 + packet[2]); (*posix_i2s_test_bridge_packet_handler)(HCI_SCO_DATA_PACKET, packet, 3 + packet[2]);
} }
static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type)
if (ds->source.fd < 0) return; {
switch (callback_type){ if (ds->source.fd < 0)
case DATA_SOURCE_CALLBACK_READ: return;
posix_i2s_test_bridge_process_read(ds); switch (callback_type)
break; {
case DATA_SOURCE_CALLBACK_WRITE: case DATA_SOURCE_CALLBACK_READ:
posix_i2s_test_bridge_process_write(ds); posix_i2s_test_bridge_process_read(ds);
break; break;
default: case DATA_SOURCE_CALLBACK_WRITE:
break; posix_i2s_test_bridge_process_write(ds);
break;
default:
break;
} }
} }
static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate)
{
#ifdef __APPLE__ #ifdef __APPLE__
@ -218,7 +238,8 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
// and output speed. // and output speed.
speed_t speed = baudrate; speed_t speed = baudrate;
if (ioctl(fd, IOSSIOSPEED, &speed) == -1) { if (ioctl(fd, IOSSIOSPEED, &speed) == -1)
{
log_error("set baud: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno); log_error("set baud: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
return -1; return -1;
} }
@ -226,65 +247,104 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
#else #else
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("set baud: Couldn't get term attributes"); log_error("set baud: Couldn't get term attributes");
return -1; return -1;
} }
speed_t brate = baudrate; // let you override switch below if needed speed_t brate = baudrate; // let you override switch below if needed
switch(baudrate) { switch (baudrate)
case 9600: brate=B9600; break; {
case 19200: brate=B19200; break; case 9600:
case 38400: brate=B38400; break; brate = B9600;
case 57600: brate=B57600; break; break;
case 115200: brate=B115200; break; case 19200:
brate = B19200;
break;
case 38400:
brate = B38400;
break;
case 57600:
brate = B57600;
break;
case 115200:
brate = B115200;
break;
#ifdef B230400 #ifdef B230400
case 230400: brate=B230400; break; case 230400:
brate = B230400;
break;
#endif #endif
#ifdef B460800 #ifdef B460800
case 460800: brate=B460800; break; case 460800:
brate = B460800;
break;
#endif #endif
#ifdef B500000 #ifdef B500000
case 500000: brate=B500000; break; case 500000:
brate = B500000;
break;
#endif #endif
#ifdef B576000 #ifdef B576000
case 576000: brate=B576000; break; case 576000:
brate = B576000;
break;
#endif #endif
#ifdef B921600 #ifdef B460800
case 921600: brate=B921600; break; case 460800:
brate = B460800;
break;
#endif #endif
#ifdef B1000000 #ifdef B1000000
case 1000000: brate=B1000000; break; case 1000000:
brate = B1000000;
break;
#endif #endif
#ifdef B1152000 #ifdef B1152000
case 1152000: brate=B1152000; break; case 1152000:
brate = B1152000;
break;
#endif #endif
#ifdef B1500000 #ifdef B1500000
case 1500000: brate=B1500000; break; case 1500000:
brate = B1500000;
break;
#endif #endif
#ifdef B2000000 #ifdef B2000000
case 2000000: brate=B2000000; break; case 2000000:
brate = B2000000;
break;
#endif #endif
#ifdef B2500000 #ifdef B2500000
case 2500000: brate=B2500000; break; case 2500000:
brate = B2500000;
break;
#endif #endif
#ifdef B3000000 #ifdef B3000000
case 3000000: brate=B3000000; break; case 3000000:
brate = B3000000;
break;
#endif #endif
#ifdef B3500000 #ifdef B3500000
case 3500000: brate=B3500000; break; case 3500000:
brate = B3500000;
break;
#endif #endif
#ifdef B400000 #ifdef B400000
case 4000000: brate=B4000000; break; case 4000000:
brate = B4000000;
break;
#endif #endif
default: default:
log_error("can't set baudrate %dn", baudrate ); log_error("can't set baudrate %dn", baudrate);
return -1; return -1;
} }
cfsetospeed(&toptions, brate); cfsetospeed(&toptions, brate);
cfsetispeed(&toptions, brate); cfsetispeed(&toptions, brate);
if( tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
@ -293,43 +353,48 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
return 0; return 0;
} }
static int posix_i2s_test_bridge_init(const char * device_path){ static int posix_i2s_test_bridge_init(const char *device_path)
{
const uint32_t baudrate = 230400; const uint32_t baudrate = 230400;
struct termios toptions; struct termios toptions;
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK; int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
int fd = open(device_path, flags); int fd = open(device_path, flags);
if (fd == -1) { if (fd == -1)
{
log_error("Unable to open port %s", device_path); log_error("Unable to open port %s", device_path);
return -1; return -1;
} }
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("Couldn't get term attributes"); log_error("Couldn't get term attributes");
return -1; return -1;
} }
cfmakeraw(&toptions); // make raw cfmakeraw(&toptions); // make raw
// 8N1 // 8N1
toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag |= CS8; toptions.c_cflag |= CS8;
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 1; toptions.c_cc[VMIN] = 1;
toptions.c_cc[VTIME] = 0; toptions.c_cc[VTIME] = 0;
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
// also set baudrate // also set baudrate
if (posix_i2s_test_bridge_set_baudrate(fd, baudrate) < 0){ if (posix_i2s_test_bridge_set_baudrate(fd, baudrate) < 0)
{
return -1; return -1;
} }
@ -350,7 +415,8 @@ static int posix_i2s_test_bridge_init(const char * device_path){
return 0; return 0;
} }
static void posix_i2s_test_bridge_open(hci_con_handle_t con_handle, sco_format_t format){ static void posix_i2s_test_bridge_open(hci_con_handle_t con_handle, sco_format_t format)
{
log_info("open: handle 0x%04x, format %s", con_handle, (format == SCO_FORMAT_16_BIT) ? "16 bit" : "8 bit"); log_info("open: handle 0x%04x, format %s", con_handle, (format == SCO_FORMAT_16_BIT) ? "16 bit" : "8 bit");
// store config // store config
sco_format = format; sco_format = format;
@ -361,24 +427,28 @@ static void posix_i2s_test_bridge_open(hci_con_handle_t con_handle, sco_format_t
sco_tx_counter = 0; sco_tx_counter = 0;
} }
static void posix_i2s_test_bridge_close(hci_con_handle_t con_handle){ static void posix_i2s_test_bridge_close(hci_con_handle_t con_handle)
{
log_info("close: handle 0x%04x", con_handle); log_info("close: handle 0x%04x", con_handle);
sco_handle = HCI_CON_HANDLE_INVALID; sco_handle = HCI_CON_HANDLE_INVALID;
} }
static void posix_i2s_test_bridge_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ static void posix_i2s_test_bridge_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size))
{
posix_i2s_test_bridge_packet_handler = handler; posix_i2s_test_bridge_packet_handler = handler;
} }
const btstack_sco_transport_t * btstack_sco_transport_posix_i2s_test_bridge_init_instance(const char * device_path){ const btstack_sco_transport_t *btstack_sco_transport_posix_i2s_test_bridge_init_instance(const char *device_path)
{
static const btstack_sco_transport_t transport = { static const btstack_sco_transport_t transport = {
.open = posix_i2s_test_bridge_open, .open = posix_i2s_test_bridge_open,
.close = posix_i2s_test_bridge_close, .close = posix_i2s_test_bridge_close,
.register_packet_handler = posix_i2s_test_bridge_register_packet_handler, .register_packet_handler = posix_i2s_test_bridge_register_packet_handler,
.send_packet = posix_i2s_test_bride_send_packet, .send_packet = posix_i2s_test_bride_send_packet,
}; };
int err = posix_i2s_test_bridge_init(device_path); int err = posix_i2s_test_bridge_init(device_path);
if (err > 0) { if (err > 0)
{
return NULL; return NULL;
} }
sco_format = SCO_FORMAT_8_BIT; sco_format = SCO_FORMAT_8_BIT;

View file

@ -48,9 +48,9 @@
#include "btstack_run_loop.h" #include "btstack_run_loop.h"
#include "btstack_debug.h" #include "btstack_debug.h"
#include <termios.h> /* POSIX terminal control definitions */ #include <termios.h> /* POSIX terminal control definitions */
#include <fcntl.h> /* File control definitions */ #include <fcntl.h> /* File control definitions */
#include <unistd.h> /* UNIX standard function definitions */ #include <unistd.h> /* UNIX standard function definitions */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -59,57 +59,63 @@
#endif #endif
// uart config // uart config
static const btstack_uart_config_t * uart_config; static const btstack_uart_config_t *uart_config;
// data source for integration with BTstack Runloop // data source for integration with BTstack Runloop
static btstack_data_source_t transport_data_source; static btstack_data_source_t transport_data_source;
// block write // block write
static int btstack_uart_block_write_bytes_len; static int btstack_uart_block_write_bytes_len;
static const uint8_t * btstack_uart_block_write_bytes_data; static const uint8_t *btstack_uart_block_write_bytes_data;
// block read // block read
static uint16_t btstack_uart_block_read_bytes_len; static uint16_t btstack_uart_block_read_bytes_len;
static uint8_t * btstack_uart_block_read_bytes_data; static uint8_t *btstack_uart_block_read_bytes_data;
// callbacks // callbacks
static void (*block_sent)(void); static void (*block_sent)(void);
static void (*block_received)(void); static void (*block_received)(void);
static int btstack_uart_posix_init(const btstack_uart_config_t *config)
static int btstack_uart_posix_init(const btstack_uart_config_t * config){ {
uart_config = config; uart_config = config;
return 0; return 0;
} }
static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type); static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds) { static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds)
{
if (btstack_uart_block_write_bytes_len == 0) return; if (btstack_uart_block_write_bytes_len == 0)
return;
uint32_t start = btstack_run_loop_get_time_ms(); uint32_t start = btstack_run_loop_get_time_ms();
// write up to write_bytes_len to fd // write up to write_bytes_len to fd
int bytes_written = (int) write(ds->source.fd, btstack_uart_block_write_bytes_data, btstack_uart_block_write_bytes_len); int bytes_written = (int)write(ds->source.fd, btstack_uart_block_write_bytes_data, btstack_uart_block_write_bytes_len);
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
// log_info("write took %u ms", end - start); // log_info("write took %u ms", end - start);
} }
if (bytes_written == 0){ if (bytes_written == 0)
{
// log_error("wrote zero bytes\n"); // log_error("wrote zero bytes\n");
return; return;
} }
if (bytes_written < 0) { if (bytes_written < 0)
{
// log_error("write returned error\n"); // log_error("write returned error\n");
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
btstack_uart_block_write_bytes_data += bytes_written; btstack_uart_block_write_bytes_data += bytes_written;
btstack_uart_block_write_bytes_len -= bytes_written; btstack_uart_block_write_bytes_len -= bytes_written;
if (btstack_uart_block_write_bytes_len){ if (btstack_uart_block_write_bytes_len)
{
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
@ -117,14 +123,17 @@ static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds) {
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
// notify done // notify done
if (block_sent){ if (block_sent)
{
block_sent(); block_sent();
} }
} }
static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds) { static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds)
{
if (btstack_uart_block_read_bytes_len == 0) { if (btstack_uart_block_read_bytes_len == 0)
{
log_info("called but no read pending"); log_info("called but no read pending");
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
} }
@ -135,30 +144,36 @@ static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds) {
ssize_t bytes_read = read(ds->source.fd, btstack_uart_block_read_bytes_data, btstack_uart_block_read_bytes_len); ssize_t bytes_read = read(ds->source.fd, btstack_uart_block_read_bytes_data, btstack_uart_block_read_bytes_len);
// log_info("read need %u bytes, got %d", btstack_uart_block_read_bytes_len, (int) bytes_read); // log_info("read need %u bytes, got %d", btstack_uart_block_read_bytes_len, (int) bytes_read);
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
// log_info("read took %u ms", end - start); // log_info("read took %u ms", end - start);
} }
if (bytes_read == 0){ if (bytes_read == 0)
{
// log_error("read zero bytes\n"); // log_error("read zero bytes\n");
return; return;
} }
if (bytes_read < 0) { if (bytes_read < 0)
{
// log_error("read returned error\n"); // log_error("read returned error\n");
return; return;
} }
btstack_uart_block_read_bytes_len -= bytes_read; btstack_uart_block_read_bytes_len -= bytes_read;
btstack_uart_block_read_bytes_data += bytes_read; btstack_uart_block_read_bytes_data += bytes_read;
if (btstack_uart_block_read_bytes_len > 0) return; if (btstack_uart_block_read_bytes_len > 0)
return;
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
if (block_received){ if (block_received)
{
block_received(); block_received();
} }
} }
static int btstack_uart_posix_set_baudrate(uint32_t baudrate){ static int btstack_uart_posix_set_baudrate(uint32_t baudrate)
{
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
@ -166,7 +181,8 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
// log_error("btstack_uart_posix_set_baudrate: Couldn't get term attributes"); // log_error("btstack_uart_posix_set_baudrate: Couldn't get term attributes");
return -1; return -1;
} }
@ -174,54 +190,91 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
#ifndef __APPLE__ #ifndef __APPLE__
speed_t brate = baudrate; // let you override switch below if needed speed_t brate = baudrate; // let you override switch below if needed
switch(baudrate) { switch (baudrate)
case 9600: brate=B9600; break; {
case 19200: brate=B19200; break; case 9600:
case 38400: brate=B38400; break; brate = B9600;
case 57600: brate=B57600; break; break;
case 115200: brate=B115200; break; case 19200:
brate = B19200;
break;
case 38400:
brate = B38400;
break;
case 57600:
brate = B57600;
break;
case 115200:
brate = B115200;
break;
#ifdef B230400 #ifdef B230400
case 230400: brate=B230400; break; case 230400:
brate = B230400;
break;
#endif #endif
#ifdef B460800 #ifdef B460800
case 460800: brate=B460800; break; case 460800:
brate = B460800;
break;
#endif #endif
#ifdef B500000 #ifdef B500000
case 500000: brate=B500000; break; case 500000:
brate = B500000;
break;
#endif #endif
#ifdef B576000 #ifdef B576000
case 576000: brate=B576000; break; case 576000:
brate = B576000;
break;
#endif #endif
#ifdef B921600 #ifdef B460800
case 921600: brate=B921600; break; case 460800:
brate = B460800;
break;
#endif #endif
#ifdef B1000000 #ifdef B1000000
case 1000000: brate=B1000000; break; case 1000000:
brate = B1000000;
break;
#endif #endif
#ifdef B1152000 #ifdef B1152000
case 1152000: brate=B1152000; break; case 1152000:
brate = B1152000;
break;
#endif #endif
#ifdef B1500000 #ifdef B1500000
case 1500000: brate=B1500000; break; case 1500000:
brate = B1500000;
break;
#endif #endif
#ifdef B2000000 #ifdef B2000000
case 2000000: brate=B2000000; break; case 2000000:
brate = B2000000;
break;
#endif #endif
#ifdef B2500000 #ifdef B2500000
case 2500000: brate=B2500000; break; case 2500000:
brate = B2500000;
break;
#endif #endif
#ifdef B3000000 #ifdef B3000000
case 3000000: brate=B3000000; break; case 3000000:
brate = B3000000;
break;
#endif #endif
#ifdef B3500000 #ifdef B3500000
case 3500000: brate=B3500000; break; case 3500000:
brate = B3500000;
break;
#endif #endif
#ifdef B400000 #ifdef B400000
case 4000000: brate=B4000000; break; case 4000000:
brate = B4000000;
break;
#endif #endif
default: default:
log_error("can't set baudrate %dn", baudrate ); log_error("can't set baudrate %dn", baudrate);
return -1; return -1;
} }
cfsetospeed(&toptions, brate); cfsetospeed(&toptions, brate);
cfsetispeed(&toptions, brate); cfsetispeed(&toptions, brate);
@ -230,7 +283,8 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
// also set options for __APPLE__ to enforce write drain // also set options for __APPLE__ to enforce write drain
// Mac OS Mojave: tcsdrain did not work as expected // Mac OS Mojave: tcsdrain did not work as expected
if( tcsetattr(fd, TCSADRAIN, &toptions) < 0) { if (tcsetattr(fd, TCSADRAIN, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
@ -244,7 +298,8 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
// and output speed. // and output speed.
speed_t speed = baudrate; speed_t speed = baudrate;
if (ioctl(fd, IOSSIOSPEED, &speed) == -1) { if (ioctl(fd, IOSSIOSPEED, &speed) == -1)
{
log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno); log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
return -1; return -1;
} }
@ -253,96 +308,110 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
return 0; return 0;
} }
static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){ static void btstack_uart_posix_set_parity_option(struct termios *toptions, int parity)
switch (parity){ {
case BTSTACK_UART_PARITY_OFF: switch (parity)
toptions->c_cflag &= ~PARENB; {
toptions->c_cflag &= ~PARODD; case BTSTACK_UART_PARITY_OFF:
break; toptions->c_cflag &= ~PARENB;
case BTSTACK_UART_PARITY_EVEN: toptions->c_cflag &= ~PARODD;
toptions->c_cflag |= PARENB; break;
toptions->c_cflag &= ~PARODD; case BTSTACK_UART_PARITY_EVEN:
break; toptions->c_cflag |= PARENB;
case BTSTACK_UART_PARITY_ODD: toptions->c_cflag &= ~PARODD;
toptions->c_cflag |= PARENB; break;
toptions->c_cflag |= PARODD; case BTSTACK_UART_PARITY_ODD:
default: toptions->c_cflag |= PARENB;
break; toptions->c_cflag |= PARODD;
default:
break;
} }
} }
static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){ static void btstack_uart_posix_set_flowcontrol_option(struct termios *toptions, int flowcontrol)
if (flowcontrol) { {
if (flowcontrol)
{
// with flow control // with flow control
toptions->c_cflag |= CRTSCTS; toptions->c_cflag |= CRTSCTS;
} else { }
else
{
// no flow control // no flow control
toptions->c_cflag &= ~CRTSCTS; toptions->c_cflag &= ~CRTSCTS;
} }
} }
static int btstack_uart_posix_set_parity(int parity){ static int btstack_uart_posix_set_parity(int parity)
{
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("Couldn't get term attributes"); log_error("Couldn't get term attributes");
return -1; return -1;
} }
btstack_uart_posix_set_parity_option(&toptions, parity); btstack_uart_posix_set_parity_option(&toptions, parity);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
return 0; return 0;
} }
static int btstack_uart_posix_set_flowcontrol(int flowcontrol)
static int btstack_uart_posix_set_flowcontrol(int flowcontrol){ {
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("Couldn't get term attributes"); log_error("Couldn't get term attributes");
return -1; return -1;
} }
btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol); btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
return 0; return 0;
} }
static int btstack_uart_posix_open(void){ static int btstack_uart_posix_open(void)
{
const char * device_name = uart_config->device_name; const char *device_name = uart_config->device_name;
const uint32_t baudrate = uart_config->baudrate; const uint32_t baudrate = uart_config->baudrate;
const int flowcontrol = uart_config->flowcontrol; const int flowcontrol = uart_config->flowcontrol;
const int parity = uart_config->parity; const int parity = uart_config->parity;
struct termios toptions; struct termios toptions;
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK; int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
int fd = open(device_name, flags); int fd = open(device_name, flags);
if (fd == -1) { if (fd == -1)
{
log_error("Unable to open port %s", device_name); log_error("Unable to open port %s", device_name);
return -1; return -1;
} }
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("Couldn't get term attributes"); log_error("Couldn't get term attributes");
return -1; return -1;
} }
cfmakeraw(&toptions); // make raw cfmakeraw(&toptions); // make raw
// 8N1 // 8N1
toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag |= CS8; toptions.c_cflag |= CS8;
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 1; toptions.c_cc[VMIN] = 1;
toptions.c_cc[VTIME] = 0; toptions.c_cc[VTIME] = 0;
// no parity // no parity
@ -351,7 +420,8 @@ static int btstack_uart_posix_open(void){
// flowcontrol // flowcontrol
btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol); btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("Couldn't set term attributes"); log_error("Couldn't set term attributes");
return -1; return -1;
} }
@ -360,7 +430,8 @@ static int btstack_uart_posix_open(void){
transport_data_source.source.fd = fd; transport_data_source.source.fd = fd;
// also set baudrate // also set baudrate
if (btstack_uart_posix_set_baudrate(baudrate) < 0){ if (btstack_uart_posix_set_baudrate(baudrate) < 0)
{
return -1; return -1;
} }
@ -375,7 +446,8 @@ static int btstack_uart_posix_open(void){
return 0; return 0;
} }
static int btstack_uart_posix_close_new(void){ static int btstack_uart_posix_close_new(void)
{
// first remove run loop handler // first remove run loop handler
btstack_run_loop_remove_data_source(&transport_data_source); btstack_run_loop_remove_data_source(&transport_data_source);
@ -386,22 +458,26 @@ static int btstack_uart_posix_close_new(void){
return 0; return 0;
} }
static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){ static void btstack_uart_posix_set_block_received(void (*block_handler)(void))
{
block_received = block_handler; block_received = block_handler;
} }
static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){ static void btstack_uart_posix_set_block_sent(void (*block_handler)(void))
{
block_sent = block_handler; block_sent = block_handler;
} }
static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){ static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size)
{
// setup async write // setup async write
btstack_uart_block_write_bytes_data = data; btstack_uart_block_write_bytes_data = data;
btstack_uart_block_write_bytes_len = size; btstack_uart_block_write_bytes_len = size;
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
} }
static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){ static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len)
{
btstack_uart_block_read_bytes_data = buffer; btstack_uart_block_read_bytes_data = buffer;
btstack_uart_block_read_bytes_len = len; btstack_uart_block_read_bytes_len = len;
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
@ -413,25 +489,25 @@ static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
#include "btstack_slip.h" #include "btstack_slip.h"
// max size of outgoing SLIP chunks // max size of outgoing SLIP chunks
#define SLIP_TX_CHUNK_LEN 128 #define SLIP_TX_CHUNK_LEN 128
#define SLIP_RECEIVE_BUFFER_SIZE 128 #define SLIP_RECEIVE_BUFFER_SIZE 128
// encoded SLIP chunk // encoded SLIP chunk
static uint8_t btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1]; static uint8_t btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN + 1];
// block write // block write
static int btstack_uart_slip_write_bytes_len; static int btstack_uart_slip_write_bytes_len;
static const uint8_t * btstack_uart_slip_write_bytes_data; static const uint8_t *btstack_uart_slip_write_bytes_data;
static int btstack_uart_slip_write_active; static int btstack_uart_slip_write_active;
// block read // block read
static uint8_t btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE]; static uint8_t btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE];
static uint16_t btstack_uart_slip_receive_pos; static uint16_t btstack_uart_slip_receive_pos;
static uint16_t btstack_uart_slip_receive_len; static uint16_t btstack_uart_slip_receive_len;
static uint8_t btstack_uart_slip_receive_track_start; static uint8_t btstack_uart_slip_receive_track_start;
static uint32_t btstack_uart_slip_receive_start_time; static uint32_t btstack_uart_slip_receive_start_time;
static int btstack_uart_slip_receive_active; static int btstack_uart_slip_receive_active;
// callbacks // callbacks
static void (*frame_sent)(void); static void (*frame_sent)(void);
@ -439,28 +515,33 @@ static void (*frame_received)(uint16_t frame_size);
static void btstack_uart_slip_posix_block_sent(void); static void btstack_uart_slip_posix_block_sent(void);
static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) { static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds)
{
if (btstack_uart_slip_write_bytes_len == 0) return; if (btstack_uart_slip_write_bytes_len == 0)
return;
uint32_t start = btstack_run_loop_get_time_ms(); uint32_t start = btstack_run_loop_get_time_ms();
// write up to btstack_uart_slip_write_bytes_len to fd // write up to btstack_uart_slip_write_bytes_len to fd
int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len); int bytes_written = (int)write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len);
if (bytes_written < 0) { if (bytes_written < 0)
{
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
log_info("write took %u ms", end - start); log_info("write took %u ms", end - start);
} }
btstack_uart_slip_write_bytes_data += bytes_written; btstack_uart_slip_write_bytes_data += bytes_written;
btstack_uart_slip_write_bytes_len -= bytes_written; btstack_uart_slip_write_bytes_len -= bytes_written;
if (btstack_uart_slip_write_bytes_len){ if (btstack_uart_slip_write_bytes_len)
{
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
@ -472,29 +553,34 @@ static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) {
} }
// @returns frame size if complete frame decoded and delivered // @returns frame size if complete frame decoded and delivered
static uint16_t btstack_uart_slip_posix_process_buffer(void){ static uint16_t btstack_uart_slip_posix_process_buffer(void)
{
log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len); log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len);
uint16_t frame_size = 0; uint16_t frame_size = 0;
while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){ while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0)
{
btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]); btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]);
frame_size = btstack_slip_decoder_frame_size(); frame_size = btstack_slip_decoder_frame_size();
} }
// reset buffer if fully processed // reset buffer if fully processed
if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){ if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len)
{
btstack_uart_slip_receive_len = 0; btstack_uart_slip_receive_len = 0;
btstack_uart_slip_receive_pos = 0; btstack_uart_slip_receive_pos = 0;
} }
// deliver frame if frame complete // deliver frame if frame complete
if (frame_size) { if (frame_size)
{
// receive done // receive done
btstack_uart_slip_receive_active = 0; btstack_uart_slip_receive_active = 0;
// only print if read was involved // only print if read was involved
if (btstack_uart_slip_receive_track_start == 0){ if (btstack_uart_slip_receive_track_start == 0)
{
log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time); log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time);
btstack_uart_slip_receive_start_time = 0; btstack_uart_slip_receive_start_time = 0;
} }
@ -505,11 +591,13 @@ static uint16_t btstack_uart_slip_posix_process_buffer(void){
return frame_size; return frame_size;
} }
static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) { static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds)
{
uint32_t start = btstack_run_loop_get_time_ms(); uint32_t start = btstack_run_loop_get_time_ms();
if (btstack_uart_slip_receive_track_start){ if (btstack_uart_slip_receive_track_start)
{
btstack_uart_slip_receive_track_start = 0; btstack_uart_slip_receive_track_start = 0;
btstack_uart_slip_receive_start_time = start; btstack_uart_slip_receive_start_time = start;
} }
@ -517,15 +605,17 @@ static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) {
// read up to bytes_to_read data in // read up to bytes_to_read data in
ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE); ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE);
log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read); log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int)bytes_read);
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
log_info("read took %u ms", end - start); log_info("read took %u ms", end - start);
} }
if (bytes_read < 0) return; if (bytes_read < 0)
return;
btstack_uart_slip_receive_pos = 0; btstack_uart_slip_receive_pos = 0;
btstack_uart_slip_receive_len = (uint16_t ) bytes_read; btstack_uart_slip_receive_len = (uint16_t)bytes_read;
btstack_uart_slip_posix_process_buffer(); btstack_uart_slip_posix_process_buffer();
} }
@ -533,22 +623,26 @@ static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) {
// ----------------------------- // -----------------------------
// SLIP ENCODING // SLIP ENCODING
static void btstack_uart_slip_posix_encode_chunk_and_send(void){ static void btstack_uart_slip_posix_encode_chunk_and_send(void)
{
uint16_t pos = 0; uint16_t pos = 0;
while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) { while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN))
{
btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte(); btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
} }
// setup async write and start sending // setup async write and start sending
log_debug("slip: send %d bytes", pos); log_debug("slip: send %d bytes", pos);
btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer; btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer;
btstack_uart_slip_write_bytes_len = pos; btstack_uart_slip_write_bytes_len = pos;
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
} }
static void btstack_uart_slip_posix_block_sent(void){ static void btstack_uart_slip_posix_block_sent(void)
{
// check if more data to send // check if more data to send
if (btstack_slip_encoder_has_data()){ if (btstack_slip_encoder_has_data())
{
btstack_uart_slip_posix_encode_chunk_and_send(); btstack_uart_slip_posix_encode_chunk_and_send();
return; return;
} }
@ -557,12 +651,14 @@ static void btstack_uart_slip_posix_block_sent(void){
btstack_uart_slip_write_active = 0; btstack_uart_slip_write_active = 0;
// notify done // notify done
if (frame_sent){ if (frame_sent)
{
frame_sent(); frame_sent();
} }
} }
static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){ static void btstack_uart_slip_posix_send_frame(const uint8_t *frame, uint16_t frame_size)
{
// write started // write started
btstack_uart_slip_write_active = 1; btstack_uart_slip_write_active = 1;
@ -577,7 +673,8 @@ static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t f
// SLIP ENCODING // SLIP ENCODING
// ----------------------------- // -----------------------------
static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){ static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len)
{
// receive started // receive started
btstack_uart_slip_receive_active = 1; btstack_uart_slip_receive_active = 1;
@ -590,22 +687,24 @@ static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len)
// process bytes received in earlier read. might deliver packet, which in turn will call us again. // process bytes received in earlier read. might deliver packet, which in turn will call us again.
// just make sure to exit right away // just make sure to exit right away
if (btstack_uart_slip_receive_len){ if (btstack_uart_slip_receive_len)
{
int frame_found = btstack_uart_slip_posix_process_buffer(); int frame_found = btstack_uart_slip_posix_process_buffer();
if (frame_found) return; if (frame_found)
return;
} }
// no frame delivered, enable posix read // no frame delivered, enable posix read
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
} }
static void btstack_uart_slip_posix_set_frame_received(void (*block_handler)(uint16_t frame_size))
{
static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){
frame_received = block_handler; frame_received = block_handler;
} }
static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){ static void btstack_uart_slip_posix_set_frame_sent(void (*block_handler)(void))
{
frame_sent = block_handler; frame_sent = block_handler;
} }
@ -613,59 +712,70 @@ static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void))
#endif #endif
// dispatch into block or SLIP code // dispatch into block or SLIP code
static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type)
if (ds->source.fd < 0) return; {
switch (callback_type){ if (ds->source.fd < 0)
case DATA_SOURCE_CALLBACK_READ: return;
switch (callback_type)
{
case DATA_SOURCE_CALLBACK_READ:
#ifdef ENABLE_H5 #ifdef ENABLE_H5
if (btstack_uart_slip_receive_active){ if (btstack_uart_slip_receive_active)
btstack_uart_slip_posix_process_read(ds); {
} else btstack_uart_slip_posix_process_read(ds);
}
else
#endif #endif
{ {
btstack_uart_block_posix_process_read(ds); btstack_uart_block_posix_process_read(ds);
} }
break; break;
case DATA_SOURCE_CALLBACK_WRITE: case DATA_SOURCE_CALLBACK_WRITE:
#ifdef ENABLE_H5 #ifdef ENABLE_H5
if (btstack_uart_slip_write_active){ if (btstack_uart_slip_write_active)
btstack_uart_slip_posix_process_write(ds); {
} else btstack_uart_slip_posix_process_write(ds);
}
else
#endif #endif
{ {
btstack_uart_block_posix_process_write(ds); btstack_uart_block_posix_process_write(ds);
} }
break; break;
default: default:
break; break;
} }
} }
static const btstack_uart_t btstack_uart_posix = { static const btstack_uart_t btstack_uart_posix = {
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init, /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
/* int (*open)(void); */ &btstack_uart_posix_open, /* int (*open)(void); */ &btstack_uart_posix_open,
/* int (*close)(void); */ &btstack_uart_posix_close_new, /* int (*close)(void); */ &btstack_uart_posix_close_new,
/* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received, /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received,
/* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent, /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent,
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate, /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity, /* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
/* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol, /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol,
/* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block, /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block,
/* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block, /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
/* int (*get_supported_sleep_modes); */ NULL, /* int (*get_supported_sleep_modes); */ NULL,
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
#ifdef ENABLE_H5 #ifdef ENABLE_H5
/* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received, /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received,
/* void (*set_fraae_sent)(void (*handler)(void)); */ &btstack_uart_slip_posix_set_frame_sent, /* void (*set_fraae_sent)(void (*handler)(void)); */ &btstack_uart_slip_posix_set_frame_sent,
/* void (*receive_frame)(uint8_t *buffer, uint16_t len); */ &btstack_uart_slip_posix_receive_frame, /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */ &btstack_uart_slip_posix_receive_frame,
/* void (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame, /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame,
#else #else
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL,
NULL,
#endif #endif
}; };
const btstack_uart_t * btstack_uart_posix_instance(void){ const btstack_uart_t *btstack_uart_posix_instance(void)
return &btstack_uart_posix; {
return &btstack_uart_posix;
} }

View file

@ -50,27 +50,27 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
// debugging only // debugging only
// #include <stdio.h> // #include <stdio.h>
#define BT_PORT_OUT P9OUT #define BT_PORT_OUT P9OUT
#define BT_PORT_SEL P9SEL #define BT_PORT_SEL P9SEL
#define BT_PORT_DIR P9DIR #define BT_PORT_DIR P9DIR
#define BT_PORT_REN P9REN #define BT_PORT_REN P9REN
#define BT_PIN_TXD BIT4 #define BT_PIN_TXD BIT4
#define BT_PIN_RXD BIT5 #define BT_PIN_RXD BIT5
// RXD P9.5 // RXD P9.5
// TXD P9.4 // TXD P9.4
// RTS P1.4 // RTS P1.4
// CTS P1.3 // CTS P1.3
void dummy_handler(void){}; void dummy_handler(void) {};
// rx state // rx state
static uint16_t bytes_to_read = 0; static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0; static uint8_t *rx_buffer_ptr = 0;
// tx state // tx state
static uint16_t bytes_to_write = 0; static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0; static uint8_t *tx_buffer_ptr = 0;
// handlers // handlers
static void (*rx_done_handler)(void) = dummy_handler; static void (*rx_done_handler)(void) = dummy_handler;
@ -92,18 +92,18 @@ void hal_uart_dma_init(void)
BT_PORT_DIR &= ~BT_PIN_RXD; BT_PORT_DIR &= ~BT_PIN_RXD;
// set BT RTS (P1.3) // set BT RTS (P1.3)
P1SEL &= ~BIT3; // = 0 - I/O P1SEL &= ~BIT3; // = 0 - I/O
P1DIR |= BIT3; // = 1 - Output P1DIR |= BIT3; // = 1 - Output
P1OUT |= BIT3; // = 1 - RTS high -> stop P1OUT |= BIT3; // = 1 - RTS high -> stop
// set BT CTS (P1.4) // set BT CTS (P1.4)
P1SEL &= ~BIT4; // = 0 - I/O P1SEL &= ~BIT4; // = 0 - I/O
P1DIR &= ~BIT4; // = 0 - Input P1DIR |= BIT4; // RTS P1DIR &= ~BIT4; // = 0 - Input P1DIR |= BIT4; // RTS
// set BT SHUTDOWN (P2.7) to 1 (active low) // set BT SHUTDOWN (P2.7) to 1 (active low)
P2SEL &= ~BIT7; // = 0 - I/O P2SEL &= ~BIT7; // = 0 - I/O
P2DIR |= BIT7; // = 1 - Output P2DIR |= BIT7; // = 1 - Output
P2OUT |= BIT7; // = 1 - Active low -> ok P2OUT |= BIT7; // = 1 - Active low -> ok
// Enable ACLK to provide 32 kHz clock to Bluetooth module // Enable ACLK to provide 32 kHz clock to Bluetooth module
P2SEL |= BIT6; P2SEL |= BIT6;
@ -112,13 +112,13 @@ void hal_uart_dma_init(void)
// wait for Bluetooth to power up properly after providing 32khz clock // wait for Bluetooth to power up properly after providing 32khz clock
waitAboutOneSecond(); waitAboutOneSecond();
UCA2CTL1 |= UCSWRST; //Reset State UCA2CTL1 |= UCSWRST; // Reset State
UCA2CTL0 = UCMODE_0; UCA2CTL0 = UCMODE_0;
UCA2CTL0 &= ~UC7BIT; // 8bit char UCA2CTL0 &= ~UC7BIT; // 8bit char
UCA2CTL1 |= UCSSEL_2; UCA2CTL1 |= UCSSEL_2;
UCA2CTL1 &= ~UCSWRST; // continue UCA2CTL1 &= ~UCSWRST; // continue
hal_uart_dma_set_baud(115200); hal_uart_dma_set_baud(115200);
} }
@ -130,7 +130,7 @@ void hal_uart_dma_init(void)
16000000 / 576000 = 277.77 16000000 / 576000 = 277.77
16000000 / 115200 = 138.88 16000000 / 115200 = 138.88
16000000 / 921600 = 17.36 16000000 / 460800 = 17.36
16000000 / 1000000 = 16.00 16000000 / 1000000 = 16.00
16000000 / 2000000 = 8.00 16000000 / 2000000 = 8.00
16000000 / 2400000 = 6.66 16000000 / 2400000 = 6.66
@ -138,91 +138,97 @@ void hal_uart_dma_init(void)
16000000 / 4000000 = 2.00 16000000 / 4000000 = 2.00
*/ */
int hal_uart_dma_set_baud(uint32_t baud){ int hal_uart_dma_set_baud(uint32_t baud)
{
int result = 0; int result = 0;
UCA2CTL1 |= UCSWRST; //Reset State UCA2CTL1 |= UCSWRST; // Reset State
switch (baud){ switch (baud)
{
case 4000000: case 4000000:
UCA2BR0 = 2; UCA2BR0 = 2;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 3000000: case 3000000:
UCA2BR0 = 3; UCA2BR0 = 3;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 3 << 1; // + 0.375 UCA2MCTL = 3 << 1; // + 0.375
break; break;
case 2400000: case 2400000:
UCA2BR0 = 6; UCA2BR0 = 6;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 5 << 1; // + 0.625 UCA2MCTL = 5 << 1; // + 0.625
break; break;
case 2000000: case 2000000:
UCA2BR0 = 8; UCA2BR0 = 8;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 1000000: case 1000000:
UCA2BR0 = 16; UCA2BR0 = 16;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 921600: case 460800:
UCA2BR0 = 17; UCA2BR0 = 17;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375 UCA2MCTL = 7 << 1; // 3 << 1; // + 0.375
break; break;
case 115200: case 115200:
UCA2BR0 = 138; // from family user guide UCA2BR0 = 138; // from family user guide
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // + 0.875 UCA2MCTL = 7 << 1; // + 0.875
break; break;
case 57600: case 57600:
UCA2BR0 = 21; UCA2BR0 = 21;
UCA2BR1 = 1; UCA2BR1 = 1;
UCA2MCTL= 7 << 1; // + 0.875 UCA2MCTL = 7 << 1; // + 0.875
break; break;
default: default:
result = -1; result = -1;
break; break;
} }
UCA2CTL1 &= ~UCSWRST; // continue UCA2CTL1 &= ~UCSWRST; // continue
return result; return result;
} }
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_received(void (*the_block_handler)(void))
{
rx_done_handler = the_block_handler; rx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_sent(void (*the_block_handler)(void))
{
tx_done_handler = the_block_handler; tx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ void hal_uart_dma_set_csr_irq_handler(void (*the_irq_handler)(void))
if (the_irq_handler){ {
P1IFG = 0; // no IRQ pending if (the_irq_handler)
P1IV = 0; // no IRQ pending {
P1IES &= ~BIT4; // IRQ on 0->1 transition P1IFG = 0; // no IRQ pending
P1IE |= BIT4; // enable IRQ for P1.3 P1IV = 0; // no IRQ pending
P1IES &= ~BIT4; // IRQ on 0->1 transition
P1IE |= BIT4; // enable IRQ for P1.3
cts_irq_handler = the_irq_handler; cts_irq_handler = the_irq_handler;
return; return;
} }
P1IE &= ~BIT4; P1IE &= ~BIT4;
cts_irq_handler = dummy_handler; cts_irq_handler = dummy_handler;
} }
@ -235,39 +241,44 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
* *
* @return none * @return none
**************************************************************************/ **************************************************************************/
void hal_uart_dma_shutdown(void) { void hal_uart_dma_shutdown(void)
{
UCA2IE &= ~(UCRXIE | UCTXIE); UCA2IE &= ~(UCRXIE | UCTXIE);
UCA2CTL1 = UCSWRST; //Reset State UCA2CTL1 = UCSWRST; // Reset State
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD ); BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
BT_PORT_DIR |= BT_PIN_TXD; BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_RXD; BT_PORT_DIR |= BT_PIN_RXD;
BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD); BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
} }
void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){ void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
{
// printf("hal_uart_dma_send_block, size %u\n\r", len); // printf("hal_uart_dma_send_block, size %u\n\r", len);
UCA2IE &= ~UCTXIE ; // disable TX interrupts UCA2IE &= ~UCTXIE; // disable TX interrupts
tx_buffer_ptr = (uint8_t *) data; tx_buffer_ptr = (uint8_t *)data;
bytes_to_write = len; bytes_to_write = len;
UCA2IE |= UCTXIE; // enable TX interrupts UCA2IE |= UCTXIE; // enable TX interrupts
} }
static inline void hal_uart_dma_enable_rx(void){ static inline void hal_uart_dma_enable_rx(void)
P1OUT &= ~BIT3; // = 0 - RTS low -> ok {
P1OUT &= ~BIT3; // = 0 - RTS low -> ok
} }
static inline void hal_uart_dma_disable_rx(void){ static inline void hal_uart_dma_disable_rx(void)
P1OUT |= BIT3; // = 1 - RTS high -> stop {
P1OUT |= BIT3; // = 1 - RTS high -> stop
} }
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len)
{
// disable RX interrupts // disable RX interrupts
UCA2IE &= ~UCRXIE ; UCA2IE &= ~UCRXIE;
rx_buffer_ptr = buffer; rx_buffer_ptr = buffer;
bytes_to_read = len; bytes_to_read = len;
@ -279,12 +290,14 @@ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
UCA2IE |= UCRXIE; UCA2IE |= UCRXIE;
// if byte was pending, ISR controls RTS // if byte was pending, ISR controls RTS
if (!pending) { if (!pending)
{
hal_uart_dma_enable_rx(); hal_uart_dma_enable_rx();
} }
} }
void hal_uart_dma_set_sleep(uint8_t sleep){ void hal_uart_dma_set_sleep(uint8_t sleep)
{
hal_cpu_set_uart_needed_during_sleep(!sleep); hal_cpu_set_uart_needed_during_sleep(!sleep);
} }
@ -293,78 +306,86 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
__attribute__((interrupt(USCI_A2_VECTOR))) __attribute__((interrupt(USCI_A2_VECTOR)))
#endif #endif
#ifdef __IAR_SYSTEMS_ICC__ #ifdef __IAR_SYSTEMS_ICC__
#pragma vector=USCI_A2_VECTOR #pragma vector = USCI_A2_VECTOR
__interrupt __interrupt
#endif #endif
void usbRxTxISR(void){ void
usbRxTxISR(void)
{
// find reason // find reason
switch (UCA2IV){ switch (UCA2IV)
{
case 2: // RXIFG case 2: // RXIFG
if (bytes_to_read == 0) { if (bytes_to_read == 0)
hal_uart_dma_disable_rx(); {
UCA2IE &= ~UCRXIE ; // disable RX interrupts hal_uart_dma_disable_rx();
return; UCA2IE &= ~UCRXIE; // disable RX interrupts
} return;
*rx_buffer_ptr = UCA2RXBUF; }
++rx_buffer_ptr; *rx_buffer_ptr = UCA2RXBUF;
--bytes_to_read; ++rx_buffer_ptr;
if (bytes_to_read > 0) { --bytes_to_read;
hal_uart_dma_enable_rx(); if (bytes_to_read > 0)
return; {
} hal_uart_dma_enable_rx();
P1OUT |= BIT3; // = 1 - RTS high -> stop return;
UCA2IE &= ~UCRXIE ; // disable RX interrupts }
P1OUT |= BIT3; // = 1 - RTS high -> stop
UCA2IE &= ~UCRXIE; // disable RX interrupts
(*rx_done_handler)(); (*rx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
case 4: // TXIFG case 4: // TXIFG
if (bytes_to_write == 0){ if (bytes_to_write == 0)
UCA2IE &= ~UCTXIE ; // disable TX interrupts {
return; UCA2IE &= ~UCTXIE; // disable TX interrupts
} return;
UCA2TXBUF = *tx_buffer_ptr; }
++tx_buffer_ptr; UCA2TXBUF = *tx_buffer_ptr;
--bytes_to_write; ++tx_buffer_ptr;
--bytes_to_write;
if (bytes_to_write > 0) { if (bytes_to_write > 0)
return; {
} return;
}
UCA2IE &= ~UCTXIE ; // disable TX interrupts UCA2IE &= ~UCTXIE; // disable TX interrupts
(*tx_done_handler)(); (*tx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
default: default:
break; break;
} }
} }
// CTS ISR // CTS ISR
extern void ehcill_handle(uint8_t action); extern void ehcill_handle(uint8_t action);
#define EHCILL_CTS_SIGNAL 0x034 #define EHCILL_CTS_SIGNAL 0x034
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((interrupt(PORT1_VECTOR))) __attribute__((interrupt(PORT1_VECTOR)))
#endif #endif
#ifdef __IAR_SYSTEMS_ICC__ #ifdef __IAR_SYSTEMS_ICC__
#pragma vector=PORT1_VECTOR #pragma vector = PORT1_VECTOR
__interrupt __interrupt
#endif #endif
void ctsISR(void){ void
ctsISR(void)
{
P1IV = 0; P1IV = 0;
(*cts_irq_handler)(); (*cts_irq_handler)();
} }

View file

@ -50,27 +50,27 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
// debugging only // debugging only
// #include <stdio.h> // #include <stdio.h>
#define BT_PORT_OUT P9OUT #define BT_PORT_OUT P9OUT
#define BT_PORT_SEL P9SEL #define BT_PORT_SEL P9SEL
#define BT_PORT_DIR P9DIR #define BT_PORT_DIR P9DIR
#define BT_PORT_REN P9REN #define BT_PORT_REN P9REN
#define BT_PIN_TXD BIT4 #define BT_PIN_TXD BIT4
#define BT_PIN_RXD BIT5 #define BT_PIN_RXD BIT5
// RXD P9.5 // RXD P9.5
// TXD P9.4 // TXD P9.4
// RTS P1.4 // RTS P1.4
// CTS P1.3 // CTS P1.3
void dummy_handler(void){}; void dummy_handler(void) {};
// rx state // rx state
static uint16_t bytes_to_read = 0; static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0; static uint8_t *rx_buffer_ptr = 0;
// tx state // tx state
static uint16_t bytes_to_write = 0; static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0; static uint8_t *tx_buffer_ptr = 0;
// handlers // handlers
static void (*rx_done_handler)(void) = dummy_handler; static void (*rx_done_handler)(void) = dummy_handler;
@ -92,18 +92,18 @@ void hal_uart_dma_init(void)
BT_PORT_DIR &= ~BT_PIN_RXD; BT_PORT_DIR &= ~BT_PIN_RXD;
// set BT RTS (P1.4) // set BT RTS (P1.4)
P1SEL &= ~BIT4; // = 0 - I/O P1SEL &= ~BIT4; // = 0 - I/O
P1DIR |= BIT4; // = 1 - Output P1DIR |= BIT4; // = 1 - Output
P1OUT |= BIT4; // = 1 - RTS high -> stop P1OUT |= BIT4; // = 1 - RTS high -> stop
// set BT CTS // set BT CTS
P1SEL &= ~BIT3; // = 0 - I/O P1SEL &= ~BIT3; // = 0 - I/O
P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS
// set BT SHUTDOWN (P8.2) to 1 (active low) // set BT SHUTDOWN (P8.2) to 1 (active low)
P8SEL &= ~BIT2; // = 0 - I/O P8SEL &= ~BIT2; // = 0 - I/O
P8DIR |= BIT2; // = 1 - Output P8DIR |= BIT2; // = 1 - Output
P8OUT |= BIT2; // = 1 - Active low -> ok P8OUT |= BIT2; // = 1 - Active low -> ok
// Enable ACLK to provide 32 kHz clock to Bluetooth module // Enable ACLK to provide 32 kHz clock to Bluetooth module
P11SEL |= BIT0; P11SEL |= BIT0;
@ -112,13 +112,13 @@ void hal_uart_dma_init(void)
// wait for Bluetooth to power up properly after providing 32khz clock // wait for Bluetooth to power up properly after providing 32khz clock
waitAboutOneSecond(); waitAboutOneSecond();
UCA2CTL1 |= UCSWRST; //Reset State UCA2CTL1 |= UCSWRST; // Reset State
UCA2CTL0 = UCMODE_0; UCA2CTL0 = UCMODE_0;
UCA2CTL0 &= ~UC7BIT; // 8bit char UCA2CTL0 &= ~UC7BIT; // 8bit char
UCA2CTL1 |= UCSSEL_2; UCA2CTL1 |= UCSSEL_2;
UCA2CTL1 &= ~UCSWRST; // continue UCA2CTL1 &= ~UCSWRST; // continue
hal_uart_dma_set_baud(115200); hal_uart_dma_set_baud(115200);
} }
@ -130,7 +130,7 @@ void hal_uart_dma_init(void)
16000000 / 576000 = 277.77 16000000 / 576000 = 277.77
16000000 / 115200 = 138.88 16000000 / 115200 = 138.88
16000000 / 921600 = 17.36 16000000 / 460800 = 17.36
16000000 / 1000000 = 16.00 16000000 / 1000000 = 16.00
16000000 / 2000000 = 8.00 16000000 / 2000000 = 8.00
16000000 / 2400000 = 6.66 16000000 / 2400000 = 6.66
@ -138,91 +138,97 @@ void hal_uart_dma_init(void)
16000000 / 4000000 = 2.00 16000000 / 4000000 = 2.00
*/ */
int hal_uart_dma_set_baud(uint32_t baud){ int hal_uart_dma_set_baud(uint32_t baud)
{
int result = 0; int result = 0;
UCA2CTL1 |= UCSWRST; //Reset State UCA2CTL1 |= UCSWRST; // Reset State
switch (baud){ switch (baud)
{
case 4000000: case 4000000:
UCA2BR0 = 2; UCA2BR0 = 2;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 3000000: case 3000000:
UCA2BR0 = 3; UCA2BR0 = 3;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 3 << 1; // + 0.375 UCA2MCTL = 3 << 1; // + 0.375
break; break;
case 2400000: case 2400000:
UCA2BR0 = 6; UCA2BR0 = 6;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 5 << 1; // + 0.625 UCA2MCTL = 5 << 1; // + 0.625
break; break;
case 2000000: case 2000000:
UCA2BR0 = 8; UCA2BR0 = 8;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 1000000: case 1000000:
UCA2BR0 = 16; UCA2BR0 = 16;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000 UCA2MCTL = 0 << 1; // + 0.000
break; break;
case 921600: case 460800:
UCA2BR0 = 17; UCA2BR0 = 17;
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375 UCA2MCTL = 7 << 1; // 3 << 1; // + 0.375
break; break;
case 115200: case 115200:
UCA2BR0 = 138; // from family user guide UCA2BR0 = 138; // from family user guide
UCA2BR1 = 0; UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // + 0.875 UCA2MCTL = 7 << 1; // + 0.875
break; break;
case 57600: case 57600:
UCA2BR0 = 21; UCA2BR0 = 21;
UCA2BR1 = 1; UCA2BR1 = 1;
UCA2MCTL= 7 << 1; // + 0.875 UCA2MCTL = 7 << 1; // + 0.875
break; break;
default: default:
result = -1; result = -1;
break; break;
} }
UCA2CTL1 &= ~UCSWRST; // continue UCA2CTL1 &= ~UCSWRST; // continue
return result; return result;
} }
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_received(void (*the_block_handler)(void))
{
rx_done_handler = the_block_handler; rx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_sent(void (*the_block_handler)(void))
{
tx_done_handler = the_block_handler; tx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ void hal_uart_dma_set_csr_irq_handler(void (*the_irq_handler)(void))
if (the_irq_handler){ {
P1IFG = 0; // no IRQ pending if (the_irq_handler)
P1IV = 0; // no IRQ pending {
P1IES &= ~BIT3; // IRQ on 0->1 transition P1IFG = 0; // no IRQ pending
P1IE |= BIT3; // enable IRQ for P1.3 P1IV = 0; // no IRQ pending
P1IES &= ~BIT3; // IRQ on 0->1 transition
P1IE |= BIT3; // enable IRQ for P1.3
cts_irq_handler = the_irq_handler; cts_irq_handler = the_irq_handler;
return; return;
} }
P1IE &= ~BIT3; P1IE &= ~BIT3;
cts_irq_handler = dummy_handler; cts_irq_handler = dummy_handler;
} }
@ -235,39 +241,44 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
* *
* @return none * @return none
**************************************************************************/ **************************************************************************/
void hal_uart_dma_shutdown(void) { void hal_uart_dma_shutdown(void)
{
UCA2IE &= ~(UCRXIE | UCTXIE); UCA2IE &= ~(UCRXIE | UCTXIE);
UCA2CTL1 = UCSWRST; //Reset State UCA2CTL1 = UCSWRST; // Reset State
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD ); BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
BT_PORT_DIR |= BT_PIN_TXD; BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_RXD; BT_PORT_DIR |= BT_PIN_RXD;
BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD); BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
} }
void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){ void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
{
// printf("hal_uart_dma_send_block, size %u\n\r", len); // printf("hal_uart_dma_send_block, size %u\n\r", len);
UCA2IE &= ~UCTXIE ; // disable TX interrupts UCA2IE &= ~UCTXIE; // disable TX interrupts
tx_buffer_ptr = (uint8_t *) data; tx_buffer_ptr = (uint8_t *)data;
bytes_to_write = len; bytes_to_write = len;
UCA2IE |= UCTXIE; // enable TX interrupts UCA2IE |= UCTXIE; // enable TX interrupts
} }
static inline void hal_uart_dma_enable_rx(void){ static inline void hal_uart_dma_enable_rx(void)
P1OUT &= ~BIT4; // = 0 - RTS low -> ok {
P1OUT &= ~BIT4; // = 0 - RTS low -> ok
} }
static inline void hal_uart_dma_disable_rx(void){ static inline void hal_uart_dma_disable_rx(void)
P1OUT |= BIT4; // = 1 - RTS high -> stop {
P1OUT |= BIT4; // = 1 - RTS high -> stop
} }
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len)
{
// disable RX interrupts // disable RX interrupts
UCA2IE &= ~UCRXIE ; UCA2IE &= ~UCRXIE;
rx_buffer_ptr = buffer; rx_buffer_ptr = buffer;
bytes_to_read = len; bytes_to_read = len;
@ -279,12 +290,14 @@ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
UCA2IE |= UCRXIE; UCA2IE |= UCRXIE;
// if byte was pending, ISR controls RTS // if byte was pending, ISR controls RTS
if (!pending) { if (!pending)
{
hal_uart_dma_enable_rx(); hal_uart_dma_enable_rx();
} }
} }
void hal_uart_dma_set_sleep(uint8_t sleep){ void hal_uart_dma_set_sleep(uint8_t sleep)
{
hal_cpu_set_uart_needed_during_sleep(!sleep); hal_cpu_set_uart_needed_during_sleep(!sleep);
} }
@ -293,78 +306,86 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
__attribute__((interrupt(USCI_A2_VECTOR))) __attribute__((interrupt(USCI_A2_VECTOR)))
#endif #endif
#ifdef __IAR_SYSTEMS_ICC__ #ifdef __IAR_SYSTEMS_ICC__
#pragma vector=USCI_A2_VECTOR #pragma vector = USCI_A2_VECTOR
__interrupt __interrupt
#endif #endif
void usbRxTxISR(void){ void
usbRxTxISR(void)
{
// find reason // find reason
switch (UCA2IV){ switch (UCA2IV)
{
case 2: // RXIFG case 2: // RXIFG
if (bytes_to_read == 0) { if (bytes_to_read == 0)
hal_uart_dma_disable_rx(); {
UCA2IE &= ~UCRXIE ; // disable RX interrupts hal_uart_dma_disable_rx();
return; UCA2IE &= ~UCRXIE; // disable RX interrupts
} return;
*rx_buffer_ptr = UCA2RXBUF; }
++rx_buffer_ptr; *rx_buffer_ptr = UCA2RXBUF;
--bytes_to_read; ++rx_buffer_ptr;
if (bytes_to_read > 0) { --bytes_to_read;
hal_uart_dma_enable_rx(); if (bytes_to_read > 0)
return; {
} hal_uart_dma_enable_rx();
P1OUT |= BIT4; // = 1 - RTS high -> stop return;
UCA2IE &= ~UCRXIE ; // disable RX interrupts }
P1OUT |= BIT4; // = 1 - RTS high -> stop
UCA2IE &= ~UCRXIE; // disable RX interrupts
(*rx_done_handler)(); (*rx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
case 4: // TXIFG case 4: // TXIFG
if (bytes_to_write == 0){ if (bytes_to_write == 0)
UCA2IE &= ~UCTXIE ; // disable TX interrupts {
return; UCA2IE &= ~UCTXIE; // disable TX interrupts
} return;
UCA2TXBUF = *tx_buffer_ptr; }
++tx_buffer_ptr; UCA2TXBUF = *tx_buffer_ptr;
--bytes_to_write; ++tx_buffer_ptr;
--bytes_to_write;
if (bytes_to_write > 0) { if (bytes_to_write > 0)
return; {
} return;
}
UCA2IE &= ~UCTXIE ; // disable TX interrupts UCA2IE &= ~UCTXIE; // disable TX interrupts
(*tx_done_handler)(); (*tx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
default: default:
break; break;
} }
} }
// CTS ISR // CTS ISR
extern void ehcill_handle(uint8_t action); extern void ehcill_handle(uint8_t action);
#define EHCILL_CTS_SIGNAL 0x034 #define EHCILL_CTS_SIGNAL 0x034
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((interrupt(PORT1_VECTOR))) __attribute__((interrupt(PORT1_VECTOR)))
#endif #endif
#ifdef __IAR_SYSTEMS_ICC__ #ifdef __IAR_SYSTEMS_ICC__
#pragma vector=PORT1_VECTOR #pragma vector = PORT1_VECTOR
__interrupt __interrupt
#endif #endif
void ctsISR(void){ void
ctsISR(void)
{
P1IV = 0; P1IV = 0;
(*cts_irq_handler)(); (*cts_irq_handler)();
} }

View file

@ -50,15 +50,14 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
// debugging only // debugging only
// #include <stdio.h> // #include <stdio.h>
// RXD 3.4 // RXD 3.4
// TXD 3.3 // TXD 3.3
#define BT_PORT_OUT P3OUT #define BT_PORT_OUT P3OUT
#define BT_PORT_SEL P3SEL #define BT_PORT_SEL P3SEL
#define BT_PORT_DIR P3DIR #define BT_PORT_DIR P3DIR
#define BT_PORT_REN P3REN #define BT_PORT_REN P3REN
#define BT_PIN_TXD BIT3 #define BT_PIN_TXD BIT3
#define BT_PIN_RXD BIT4 #define BT_PIN_RXD BIT4
// RTS P2.3 // RTS P2.3
#define RTS_SEL P2SEL #define RTS_SEL P2SEL
@ -78,15 +77,15 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
#define N_SHUTDOWN_DIR P4DIR #define N_SHUTDOWN_DIR P4DIR
#define N_SHUTDOWN_PIN BIT1 #define N_SHUTDOWN_PIN BIT1
void dummy_handler(void){}; void dummy_handler(void) {};
// rx state // rx state
static uint16_t bytes_to_read = 0; static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0; static uint8_t *rx_buffer_ptr = 0;
// tx state // tx state
static uint16_t bytes_to_write = 0; static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0; static uint8_t *tx_buffer_ptr = 0;
// handlers // handlers
static void (*rx_done_handler)(void) = dummy_handler; static void (*rx_done_handler)(void) = dummy_handler;
@ -108,29 +107,29 @@ void hal_uart_dma_init(void)
BT_PORT_DIR &= ~BT_PIN_RXD; BT_PORT_DIR &= ~BT_PIN_RXD;
// set BT RTS // set BT RTS
RTS_SEL &= ~RTS_PIN; // = 0 - I/O RTS_SEL &= ~RTS_PIN; // = 0 - I/O
RTS_DIR |= RTS_PIN; // = 1 - Output RTS_DIR |= RTS_PIN; // = 1 - Output
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
// set BT CTS // set BT CTS
CTS_SEL &= ~CTS_PIN; // = 0 - I/O CTS_SEL &= ~CTS_PIN; // = 0 - I/O
CTS_DIR &= ~CTS_PIN; // = 0 - Input CTS_DIR &= ~CTS_PIN; // = 0 - Input
// set BT SHUTDOWN to 1 (active low) // set BT SHUTDOWN to 1 (active low)
N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN; // = 0 - I/O N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN; // = 0 - I/O
N_SHUTDOWN_DIR |= N_SHUTDOWN_PIN; // = 1 - Output N_SHUTDOWN_DIR |= N_SHUTDOWN_PIN; // = 1 - Output
N_SHUTDOWN_OUT |= N_SHUTDOWN_PIN; // = 1 - Active low -> ok N_SHUTDOWN_OUT |= N_SHUTDOWN_PIN; // = 1 - Active low -> ok
// wait for Bluetooth to power up properly after providing 32khz clock // wait for Bluetooth to power up properly after providing 32khz clock
waitAboutOneSecond(); waitAboutOneSecond();
UCA0CTL1 |= UCSWRST; //Reset State UCA0CTL1 |= UCSWRST; // Reset State
UCA0CTL0 = UCMODE_0; UCA0CTL0 = UCMODE_0;
UCA0CTL0 &= ~UC7BIT; // 8bit char UCA0CTL0 &= ~UC7BIT; // 8bit char
UCA0CTL1 |= UCSSEL_2; UCA0CTL1 |= UCSSEL_2;
UCA0CTL1 &= ~UCSWRST; // continue UCA0CTL1 &= ~UCSWRST; // continue
hal_uart_dma_set_baud(115200); hal_uart_dma_set_baud(115200);
} }
@ -142,7 +141,7 @@ void hal_uart_dma_init(void)
16000000 / 576000 = 277.77 16000000 / 576000 = 277.77
16000000 / 115200 = 138.88 16000000 / 115200 = 138.88
16000000 / 921600 = 17.36 16000000 / 460800 = 17.36
16000000 / 1000000 = 16.00 16000000 / 1000000 = 16.00
16000000 / 2000000 = 8.00 16000000 / 2000000 = 8.00
16000000 / 2400000 = 6.66 16000000 / 2400000 = 6.66
@ -150,91 +149,97 @@ void hal_uart_dma_init(void)
16000000 / 4000000 = 2.00 16000000 / 4000000 = 2.00
*/ */
int hal_uart_dma_set_baud(uint32_t baud){ int hal_uart_dma_set_baud(uint32_t baud)
{
int result = 0; int result = 0;
UCA0CTL1 |= UCSWRST; //Reset State UCA0CTL1 |= UCSWRST; // Reset State
switch (baud){ switch (baud)
{
case 4000000: case 4000000:
UCA0BR0 = 2; UCA0BR0 = 2;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 0 << 1; // + 0.000 UCA0MCTL = 0 << 1; // + 0.000
break; break;
case 3000000: case 3000000:
UCA0BR0 = 3; UCA0BR0 = 3;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 3 << 1; // + 0.375 UCA0MCTL = 3 << 1; // + 0.375
break; break;
case 2400000: case 2400000:
UCA0BR0 = 6; UCA0BR0 = 6;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 5 << 1; // + 0.625 UCA0MCTL = 5 << 1; // + 0.625
break; break;
case 2000000: case 2000000:
UCA0BR0 = 8; UCA0BR0 = 8;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 0 << 1; // + 0.000 UCA0MCTL = 0 << 1; // + 0.000
break; break;
case 1000000: case 1000000:
UCA0BR0 = 16; UCA0BR0 = 16;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 0 << 1; // + 0.000 UCA0MCTL = 0 << 1; // + 0.000
break; break;
case 921600: case 460800:
UCA0BR0 = 17; UCA0BR0 = 17;
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 7 << 1; // 3 << 1; // + 0.375 UCA0MCTL = 7 << 1; // 3 << 1; // + 0.375
break; break;
case 115200: case 115200:
UCA0BR0 = 138; // from family user guide UCA0BR0 = 138; // from family user guide
UCA0BR1 = 0; UCA0BR1 = 0;
UCA0MCTL= 7 << 1; // + 0.875 UCA0MCTL = 7 << 1; // + 0.875
break; break;
case 57600: case 57600:
UCA0BR0 = 21; UCA0BR0 = 21;
UCA0BR1 = 1; UCA0BR1 = 1;
UCA0MCTL= 7 << 1; // + 0.875 UCA0MCTL = 7 << 1; // + 0.875
break; break;
default: default:
result = -1; result = -1;
break; break;
} }
UCA0CTL1 &= ~UCSWRST; // continue UCA0CTL1 &= ~UCSWRST; // continue
return result; return result;
} }
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_received(void (*the_block_handler)(void))
{
rx_done_handler = the_block_handler; rx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){ void hal_uart_dma_set_block_sent(void (*the_block_handler)(void))
{
tx_done_handler = the_block_handler; tx_done_handler = the_block_handler;
} }
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ void hal_uart_dma_set_csr_irq_handler(void (*the_irq_handler)(void))
{
#ifdef HAVE_CTS_IRQ #ifdef HAVE_CTS_IRQ
if (the_irq_handler){ if (the_irq_handler)
P2IFG = 0; // no IRQ pending {
P2IV = 0; // no IRQ pending P2IFG = 0; // no IRQ pending
P2IES &= ~ CTS_PIN; // IRQ on 0->1 transition P2IV = 0; // no IRQ pending
P2IE |= CTS_PIN; // enable IRQ for P8.1 P2IES &= ~CTS_PIN; // IRQ on 0->1 transition
P2IE |= CTS_PIN; // enable IRQ for P8.1
cts_irq_handler = the_irq_handler; cts_irq_handler = the_irq_handler;
return; return;
} }
P2IE &= ~CTS_PIN; P2IE &= ~CTS_PIN;
cts_irq_handler = dummy_handler; cts_irq_handler = dummy_handler;
#endif #endif
} }
@ -248,37 +253,42 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
* *
* @return none * @return none
**************************************************************************/ **************************************************************************/
void hal_uart_dma_shutdown(void) { void hal_uart_dma_shutdown(void)
{
UCA0IE &= ~(UCRXIE | UCTXIE); UCA0IE &= ~(UCRXIE | UCTXIE);
UCA0CTL1 = UCSWRST; //Reset State UCA0CTL1 = UCSWRST; // Reset State
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD ); BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
BT_PORT_DIR |= BT_PIN_TXD; BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_RXD; BT_PORT_DIR |= BT_PIN_RXD;
BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD); BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
} }
void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){ void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
{
// printf("hal_uart_dma_send_block, size %u\n\r", len); // printf("hal_uart_dma_send_block, size %u\n\r", len);
UCA0IE &= ~UCTXIE ; // disable TX interrupts UCA0IE &= ~UCTXIE; // disable TX interrupts
tx_buffer_ptr = (uint8_t *) data; tx_buffer_ptr = (uint8_t *)data;
bytes_to_write = len; bytes_to_write = len;
UCA0IE |= UCTXIE; // enable TX interrupts UCA0IE |= UCTXIE; // enable TX interrupts
} }
static inline void hal_uart_dma_enable_rx(void){ static inline void hal_uart_dma_enable_rx(void)
RTS_OUT &= ~ RTS_PIN; // = 0 - RTS low -> ok {
RTS_OUT &= ~RTS_PIN; // = 0 - RTS low -> ok
} }
static inline void hal_uart_dma_disable_rx(void){ static inline void hal_uart_dma_disable_rx(void)
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop {
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
} }
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len)
{
// disable RX interrupts // disable RX interrupts
UCA0IE &= ~UCRXIE; UCA0IE &= ~UCRXIE;
@ -289,15 +299,17 @@ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
int pending = UCA0IFG & UCRXIFG; int pending = UCA0IFG & UCRXIFG;
// enable RX interrupts - will trigger ISR below if byte pending // enable RX interrupts - will trigger ISR below if byte pending
UCA0IE |= UCRXIE; // enable RX interrupts UCA0IE |= UCRXIE; // enable RX interrupts
// if byte was pending, ISR controls RTS // if byte was pending, ISR controls RTS
if (!pending) { if (!pending)
{
hal_uart_dma_enable_rx(); hal_uart_dma_enable_rx();
} }
} }
void hal_uart_dma_set_sleep(uint8_t sleep){ void hal_uart_dma_set_sleep(uint8_t sleep)
{
hal_cpu_set_uart_needed_during_sleep(!sleep); hal_cpu_set_uart_needed_during_sleep(!sleep);
} }
@ -306,81 +318,88 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
__attribute__((interrupt(USCI_A0_VECTOR))) __attribute__((interrupt(USCI_A0_VECTOR)))
#endif #endif
#ifdef __IAR_SYSTEMS_ICC__ #ifdef __IAR_SYSTEMS_ICC__
#pragma vector=USCI_A0_VECTOR #pragma vector = USCI_A0_VECTOR
__interrupt __interrupt
#endif #endif
void usbRxTxISR(void){ void
usbRxTxISR(void)
{
// find reason // find reason
switch (UCA0IV){ switch (UCA0IV)
{
case 2: // RXIFG case 2: // RXIFG
if (bytes_to_read == 0) { if (bytes_to_read == 0)
hal_uart_dma_disable_rx(); {
UCA0IE &= ~UCRXIE ; // disable RX interrupts hal_uart_dma_disable_rx();
return; UCA0IE &= ~UCRXIE; // disable RX interrupts
} return;
*rx_buffer_ptr = UCA0RXBUF; }
++rx_buffer_ptr; *rx_buffer_ptr = UCA0RXBUF;
--bytes_to_read; ++rx_buffer_ptr;
if (bytes_to_read > 0) { --bytes_to_read;
hal_uart_dma_enable_rx(); if (bytes_to_read > 0)
return; {
} hal_uart_dma_enable_rx();
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop return;
UCA0IE &= ~UCRXIE ; // disable RX interrupts }
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
UCA0IE &= ~UCRXIE; // disable RX interrupts
(*rx_done_handler)(); (*rx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
case 4: // TXIFG case 4: // TXIFG
if (bytes_to_write == 0){ if (bytes_to_write == 0)
UCA0IE &= ~UCTXIE ; // disable TX interrupts {
return; UCA0IE &= ~UCTXIE; // disable TX interrupts
} return;
UCA0TXBUF = *tx_buffer_ptr; }
++tx_buffer_ptr; UCA0TXBUF = *tx_buffer_ptr;
--bytes_to_write; ++tx_buffer_ptr;
--bytes_to_write;
if (bytes_to_write > 0) { if (bytes_to_write > 0)
return; {
} return;
}
UCA0IE &= ~UCTXIE ; // disable TX interrupts UCA0IE &= ~UCTXIE; // disable TX interrupts
(*tx_done_handler)(); (*tx_done_handler)();
// force exit low power mode // force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; break;
default: default:
break; break;
} }
} }
// CTS ISR // CTS ISR
#ifdef HAVE_CTS_IRQ #ifdef HAVE_CTS_IRQ
// TODO: there's no PORT8_VECTOR, but configuration seems possible // TODO: there's no PORT8_VECTOR, but configuration seems possible
extern void ehcill_handle(uint8_t action); extern void ehcill_handle(uint8_t action);
#define EHCILL_CTS_SIGNAL 0x034 #define EHCILL_CTS_SIGNAL 0x034
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((interrupt(PORT2_VECTOR))) __attribute__((interrupt(PORT2_VECTOR)))
#elif defined( __IAR_SYSTEMS_ICC__) #elif defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT2_VECTOR #pragma vector = PORT2_VECTOR
__interrupt __interrupt
#endif #endif
void ctsISR(void){ void
ctsISR(void)
{
P2IV = 0; P2IV = 0;
(*cts_irq_handler)(); (*cts_irq_handler)();
} }
#endif #endif

View file

@ -67,31 +67,31 @@
#include "hci.h" #include "hci.h"
#include "hci_dump.h" #include "hci_dump.h"
int btstack_main(int argc, const char *argv[]);
int btstack_main(int argc, const char * argv[]);
#define TLV_DB_PATH_PREFIX "/tmp/btstack_" #define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static hci_transport_config_uart_t transport_config = { static hci_transport_config_uart_t transport_config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
921600, // main baudrate 460800, // main baudrate
0, // flow control 0, // flow control
NULL, NULL,
BTSTACK_UART_PARITY_EVEN, // parity BTSTACK_UART_PARITY_EVEN, // parity
}; };
static btstack_uart_config_t uart_config; static btstack_uart_config_t uart_config;
static int main_argc; static int main_argc;
static const char ** main_argv; static const char **main_argv;
static btstack_packet_callback_registration_t hci_event_callback_registration; static btstack_packet_callback_registration_t hci_event_callback_registration;
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -108,45 +108,51 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
// setup TLV break;
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); gap_local_bd_addr(addr);
strcat(tlv_db_path, bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); // setup TLV
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); strcat(tlv_db_path, bd_addr_to_str(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);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
default: default:
break; break;
} }
} }
static void phase2(int status); static void phase2(int status);
int main(int argc, const char * argv[]){ int main(int argc, const char *argv[])
{
/// GET STARTED with BTstack /// /// GET STARTED with BTstack ///
btstack_memory_init(); btstack_memory_init();
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
// hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER); // hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -157,26 +163,25 @@ int main(int argc, const char * argv[]){
transport_config.device_name = "/dev/tty.usbserial-A9OVNX5P"; // RedBear IoT pHAT breakout board transport_config.device_name = "/dev/tty.usbserial-A9OVNX5P"; // RedBear IoT pHAT breakout board
// get BCM chipset driver // get BCM chipset driver
const btstack_chipset_t * chipset = btstack_chipset_bcm_instance(); const btstack_chipset_t *chipset = btstack_chipset_bcm_instance();
chipset->init(&transport_config); chipset->init(&transport_config);
// set chipset name // set chipset name
btstack_chipset_bcm_set_device_name("BCM43430A1"); btstack_chipset_bcm_set_device_name("BCM43430A1");
// setup UART driver // setup UART driver
const btstack_uart_t * uart_driver = (const btstack_uart_t *) btstack_uart_posix_instance(); const btstack_uart_t *uart_driver = (const btstack_uart_t *)btstack_uart_posix_instance();
// extract UART config from transport config // extract UART config from transport config
uart_config.baudrate = transport_config.baudrate_init; uart_config.baudrate = transport_config.baudrate_init;
uart_config.flowcontrol = transport_config.flowcontrol; uart_config.flowcontrol = transport_config.flowcontrol;
uart_config.device_name = transport_config.device_name; uart_config.device_name = transport_config.device_name;
uart_driver->init(&uart_config); uart_driver->init(&uart_config);
// setup HCI (to be able to use bcm chipset driver) // setup HCI (to be able to use bcm chipset driver)
// init HCI // init HCI
const hci_transport_t * transport = hci_transport_h5_instance(uart_driver); const hci_transport_t *transport = hci_transport_h5_instance(uart_driver);
hci_init(transport, (void*) &transport_config); hci_init(transport, (void *)&transport_config);
hci_set_chipset(btstack_chipset_bcm_instance()); hci_set_chipset(btstack_chipset_bcm_instance());
// inform about BTstack state // inform about BTstack state
@ -200,9 +205,11 @@ int main(int argc, const char * argv[]){
return 0; return 0;
} }
static void phase2(int status){ static void phase2(int status)
{
if (status){ if (status)
{
printf("Download firmware failed\n"); printf("Download firmware failed\n");
return; return;
} }
@ -212,4 +219,3 @@ static void phase2(int status){
// setup app // setup app
btstack_main(main_argc, main_argv); btstack_main(main_argc, main_argv);
} }

View file

@ -29,7 +29,7 @@
#define ENABLE_SDP #define ENABLE_SDP
#define HAVE_TRANSPORT_H4 #define HAVE_TRANSPORT_H4
#define UART_DEVICE "/dev/tty.bluetooth" #define UART_DEVICE "/dev/tty.bluetooth"
#define UART_SPEED 921600 #define UART_SPEED 460800
#define USE_LAUNCHD #define USE_LAUNCHD
#define USE_SPRINGBOARD #define USE_SPRINGBOARD

View file

@ -72,52 +72,57 @@
#include "wilc3000_ble_firmware.h" #include "wilc3000_ble_firmware.h"
static int main_argc; static int main_argc;
static const char ** main_argv; static const char **main_argv;
static const btstack_uart_t * uart_driver; static const btstack_uart_t *uart_driver;
static btstack_uart_config_t uart_config; static btstack_uart_config_t uart_config;
#define TLV_DB_PATH_PREFIX "/tmp/btstack_" #define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
static hci_transport_config_uart_t transport_config = { static hci_transport_config_uart_t transport_config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
921600, 460800,
0, // main baudrate 0, // main baudrate
1, // flow control 1, // flow control
NULL, NULL,
}; };
static btstack_packet_callback_registration_t hci_event_callback_registration; 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){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
// setup TLV break;
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); gap_local_bd_addr(addr);
strcat(tlv_db_path, bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); // setup TLV
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); strcat(tlv_db_path, bd_addr_to_str(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);
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
default: default:
break; break;
} }
} }
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -134,14 +139,17 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void phase2(int status){ static void phase2(int status)
{
if (status){ if (status)
{
printf("Download firmware failed\n"); printf("Download firmware failed\n");
return; return;
} }
@ -149,8 +157,8 @@ static void phase2(int status){
printf("Phase 2: Main app\n"); printf("Phase 2: Main app\n");
// init HCI // init HCI
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
hci_init(transport, (void*) &transport_config); hci_init(transport, (void *)&transport_config);
hci_set_chipset(btstack_chipset_atwilc3000_instance()); hci_set_chipset(btstack_chipset_atwilc3000_instance());
// inform about BTstack state // inform about BTstack state
@ -164,17 +172,17 @@ static void phase2(int status){
btstack_main(main_argc, main_argv); btstack_main(main_argc, main_argv);
} }
int main(int argc, const char *argv[])
{
int main(int argc, const char * argv[]){ /// GET STARTED with BTstack ///
btstack_memory_init();
/// GET STARTED with BTstack ///
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance()); btstack_run_loop_init(btstack_run_loop_posix_get_instance());
// log into file using HCI_DUMP_PACKETLOGGER format // log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -183,7 +191,7 @@ int main(int argc, const char * argv[]){
uart_driver = btstack_uart_posix_instance(); uart_driver = btstack_uart_posix_instance();
// extract UART config from transport config, but disable flow control and use default baudrate // extract UART config from transport config, but disable flow control and use default baudrate
uart_config.baudrate = HCI_DEFAULT_BAUDRATE; uart_config.baudrate = HCI_DEFAULT_BAUDRATE;
uart_config.flowcontrol = 0; uart_config.flowcontrol = 0;
uart_config.device_name = transport_config.device_name; uart_config.device_name = transport_config.device_name;
uart_driver->init(&uart_config); uart_driver->init(&uart_config);
@ -195,7 +203,7 @@ int main(int argc, const char * argv[]){
printf("Phase 1: Download firmware\n"); printf("Phase 1: Download firmware\n");
// phase #2 start main app // phase #2 start main app
btstack_chipset_atwilc3000_download_firmware_with_uart(uart_driver, transport_config.baudrate_init, transport_config.flowcontrol, (const uint8_t *) firmware_ble, sizeof(firmware_ble), &phase2); btstack_chipset_atwilc3000_download_firmware_with_uart(uart_driver, transport_config.baudrate_init, transport_config.flowcontrol, (const uint8_t *)firmware_ble, sizeof(firmware_ble), &phase2);
// go // go
btstack_run_loop_execute(); btstack_run_loop_execute();

View file

@ -76,69 +76,77 @@
#include "btstack_chipset_stlc2500d.h" #include "btstack_chipset_stlc2500d.h"
#include "btstack_chipset_tc3566x.h" #include "btstack_chipset_tc3566x.h"
#define TLV_DB_PATH_PREFIX "/tmp/btstack_" #define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static int is_bcm; static int is_bcm;
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
static void local_version_information_handler(uint8_t * packet); static void local_version_information_handler(uint8_t *packet);
static hci_transport_config_uart_t config = { static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
0, // main baudrate 0, // main baudrate
1, // flow control 1, // flow control
NULL, NULL,
}; };
static btstack_packet_callback_registration_t hci_event_callback_registration; 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){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
// setup TLV break;
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); gap_local_bd_addr(addr);
strcat(tlv_db_path, bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); // setup TLV
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); strcat(tlv_db_path, bd_addr_to_str(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);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
case HCI_EVENT_COMMAND_COMPLETE: case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){ if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name))
if (hci_event_command_complete_get_return_parameters(packet)[0]) break; {
// terminate, name 248 chars if (hci_event_command_complete_get_return_parameters(packet)[0])
packet[6+248] = 0; break;
printf("Local name: %s\n", &packet[6]); // terminate, name 248 chars
if (is_bcm){ packet[6 + 248] = 0;
btstack_chipset_bcm_set_device_name((const char *)&packet[6]); printf("Local name: %s\n", &packet[6]);
} if (is_bcm)
{
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
} }
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ }
local_version_information_handler(packet); if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
} {
break; local_version_information_handler(packet);
default: }
break; break;
default:
break;
} }
} }
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -155,11 +163,13 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void use_fast_uart(void){ static void use_fast_uart(void)
{
#if defined(HAVE_POSIX_B240000_MAPPED_TO_3000000) || defined(HAVE_POSIX_B600_MAPPED_TO_3000000) #if defined(HAVE_POSIX_B240000_MAPPED_TO_3000000) || defined(HAVE_POSIX_B600_MAPPED_TO_3000000)
printf("Using 3000000 baud.\n"); printf("Using 3000000 baud.\n");
config.baudrate_main = 3000000; config.baudrate_main = 3000000;
@ -167,86 +177,90 @@ static void use_fast_uart(void){
printf("Using 2000000 baud.\n"); printf("Using 2000000 baud.\n");
config.baudrate_main = 2000000; config.baudrate_main = 2000000;
#else #else
printf("Using 921600 baud.\n"); printf("Using 460800 baud.\n");
config.baudrate_main = 921600; config.baudrate_main = 460800;
#endif #endif
} }
static void local_version_information_handler(uint8_t * packet){ static void local_version_information_handler(uint8_t *packet)
{
printf("Local version information:\n"); printf("Local version information:\n");
uint16_t hci_version = packet[6]; uint16_t hci_version = packet[6];
uint16_t hci_revision = little_endian_read_16(packet, 7); uint16_t hci_revision = little_endian_read_16(packet, 7);
uint16_t lmp_version = packet[9]; uint16_t lmp_version = packet[9];
uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t manufacturer = little_endian_read_16(packet, 10);
uint16_t lmp_subversion = little_endian_read_16(packet, 12); uint16_t lmp_subversion = little_endian_read_16(packet, 12);
printf("- HCI Version 0x%04x\n", hci_version); printf("- HCI Version 0x%04x\n", hci_version);
printf("- HCI Revision 0x%04x\n", hci_revision); printf("- HCI Revision 0x%04x\n", hci_revision);
printf("- LMP Version 0x%04x\n", lmp_version); printf("- LMP Version 0x%04x\n", lmp_version);
printf("- LMP Subversion 0x%04x\n", lmp_subversion); printf("- LMP Subversion 0x%04x\n", lmp_subversion);
printf("- Manufacturer 0x%04x\n", manufacturer); printf("- Manufacturer 0x%04x\n", manufacturer);
switch (manufacturer){ switch (manufacturer)
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: {
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
use_fast_uart(); printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
hci_set_chipset(btstack_chipset_csr_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_csr_instance());
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: break;
printf("Texas Instruments - CC256x compatible chipset.\n"); case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ printf("Texas Instruments - CC256x compatible chipset.\n");
printf("Error: LMP Subversion does not match initscript! "); if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); {
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n"); printf("Error: LMP Subversion does not match initscript! ");
exit(10); printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
} printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
use_fast_uart(); exit(10);
hci_set_chipset(btstack_chipset_cc256x_instance()); }
use_fast_uart();
hci_set_chipset(btstack_chipset_cc256x_instance());
#ifdef ENABLE_EHCILL #ifdef ENABLE_EHCILL
printf("eHCILL enabled.\n"); printf("eHCILL enabled.\n");
#else #else
printf("eHCILL disable.\n"); printf("eHCILL disable.\n");
#endif #endif
break; break;
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
printf("Broadcom/Cypress - using BCM driver.\n"); printf("Broadcom/Cypress - using BCM driver.\n");
hci_set_chipset(btstack_chipset_bcm_instance()); hci_set_chipset(btstack_chipset_bcm_instance());
use_fast_uart(); use_fast_uart();
is_bcm = 1; is_bcm = 1;
break; break;
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS: case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
printf("ST Microelectronics - using STLC2500d driver.\n"); printf("ST Microelectronics - using STLC2500d driver.\n");
use_fast_uart(); use_fast_uart();
hci_set_chipset(btstack_chipset_stlc2500d_instance()); hci_set_chipset(btstack_chipset_stlc2500d_instance());
break; break;
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA: case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
printf("EM Microelectronics - using EM9301 driver.\n"); printf("EM Microelectronics - using EM9301 driver.\n");
hci_set_chipset(btstack_chipset_em9301_instance()); hci_set_chipset(btstack_chipset_em9301_instance());
use_fast_uart(); use_fast_uart();
break; break;
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA: case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
printf("Nordic Semiconductor nRF5 chipset.\n"); printf("Nordic Semiconductor nRF5 chipset.\n");
break; break;
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP: case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
printf("Toshiba - using TC3566x driver.\n"); printf("Toshiba - using TC3566x driver.\n");
hci_set_chipset(btstack_chipset_tc3566x_instance()); hci_set_chipset(btstack_chipset_tc3566x_instance());
use_fast_uart(); use_fast_uart();
break; break;
default: default:
printf("Unknown manufacturer / manufacturer not supported yet.\n"); printf("Unknown manufacturer / manufacturer not supported yet.\n");
break; break;
} }
} }
int main(int argc, const char * argv[]){ int main(int argc, const char *argv[])
{
/// GET STARTED with BTstack /// /// GET STARTED with BTstack ///
btstack_memory_init(); btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance()); btstack_run_loop_init(btstack_run_loop_posix_get_instance());
// log into file using HCI_DUMP_PACKETLOGGER format // log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -257,17 +271,18 @@ int main(int argc, const char * argv[]){
config.device_name = "/dev/tty.usbserial-A900K0VK"; // CSR8811 breakout board config.device_name = "/dev/tty.usbserial-A900K0VK"; // CSR8811 breakout board
// accept path from command line // accept path from command line
if (argc >= 3 && strcmp(argv[1], "-u") == 0){ if (argc >= 3 && strcmp(argv[1], "-u") == 0)
{
config.device_name = argv[2]; config.device_name = argv[2];
argc -= 2; argc -= 2;
memmove(&argv[1], &argv[3], (argc-1) * sizeof(char *)); memmove(&argv[1], &argv[3], (argc - 1) * sizeof(char *));
} }
printf("H4 device: %s\n", config.device_name); printf("H4 device: %s\n", config.device_name);
// init HCI // init HCI
const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); const btstack_uart_t *uart_driver = btstack_uart_posix_instance();
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
hci_init(transport, (void*) &config); hci_init(transport, (void *)&config);
#ifdef HAVE_PORTAUDIO #ifdef HAVE_PORTAUDIO
btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance()); btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance());

View file

@ -74,27 +74,28 @@
#include "btstack_chipset_stlc2500d.h" #include "btstack_chipset_stlc2500d.h"
#include "btstack_chipset_tc3566x.h" #include "btstack_chipset_tc3566x.h"
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
#define TLV_DB_PATH_PREFIX "/tmp/btstack_" #define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static hci_transport_config_uart_t config = { static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
0, // main baudrate 0, // main baudrate
1, // flow control 1, // flow control
NULL, NULL,
BTSTACK_UART_PARITY_EVEN, // parity BTSTACK_UART_PARITY_EVEN, // parity
}; };
static btstack_packet_callback_registration_t hci_event_callback_registration; static btstack_packet_callback_registration_t hci_event_callback_registration;
static void local_version_information_handler(uint8_t * packet); static void local_version_information_handler(uint8_t *packet);
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -111,104 +112,116 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void use_fast_uart(void){ static void use_fast_uart(void)
printf("Using 921600 baud.\n"); {
config.baudrate_main = 921600; printf("Using 460800 baud.\n");
config.baudrate_main = 460800;
} }
static void local_version_information_handler(uint8_t * packet){ static void local_version_information_handler(uint8_t *packet)
{
printf("Local version information:\n"); printf("Local version information:\n");
uint16_t hci_version = packet[6]; uint16_t hci_version = packet[6];
uint16_t hci_revision = little_endian_read_16(packet, 7); uint16_t hci_revision = little_endian_read_16(packet, 7);
uint16_t lmp_version = packet[9]; uint16_t lmp_version = packet[9];
uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t manufacturer = little_endian_read_16(packet, 10);
uint16_t lmp_subversion = little_endian_read_16(packet, 12); uint16_t lmp_subversion = little_endian_read_16(packet, 12);
printf("- HCI Version 0x%04x\n", hci_version); printf("- HCI Version 0x%04x\n", hci_version);
printf("- HCI Revision 0x%04x\n", hci_revision); printf("- HCI Revision 0x%04x\n", hci_revision);
printf("- LMP Version 0x%04x\n", lmp_version); printf("- LMP Version 0x%04x\n", lmp_version);
printf("- LMP Revision 0x%04x\n", lmp_subversion); printf("- LMP Revision 0x%04x\n", lmp_subversion);
printf("- Manufacturer 0x%04x\n", manufacturer); printf("- Manufacturer 0x%04x\n", manufacturer);
switch (manufacturer){ switch (manufacturer)
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: {
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
use_fast_uart(); printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
hci_set_chipset(btstack_chipset_csr_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_csr_instance());
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: break;
printf("Texas Instruments - CC256x compatible chipset.\n"); case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
use_fast_uart(); printf("Texas Instruments - CC256x compatible chipset.\n");
hci_set_chipset(btstack_chipset_cc256x_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_cc256x_instance());
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: break;
printf("Broadcom chipset. Not supported by posix-h5 port, please use port/posix-h5-bcm\n"); case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
exit(10); printf("Broadcom chipset. Not supported by posix-h5 port, please use port/posix-h5-bcm\n");
break; exit(10);
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS: break;
printf("ST Microelectronics - using STLC2500d driver.\n"); case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
use_fast_uart(); printf("ST Microelectronics - using STLC2500d driver.\n");
hci_set_chipset(btstack_chipset_stlc2500d_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_stlc2500d_instance());
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA: break;
printf("EM Microelectronics - using EM9301 driver.\n"); case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
hci_set_chipset(btstack_chipset_em9301_instance()); printf("EM Microelectronics - using EM9301 driver.\n");
break; hci_set_chipset(btstack_chipset_em9301_instance());
default: break;
printf("Unknown manufacturer / manufacturer not supported yet.\n"); default:
break; printf("Unknown manufacturer / manufacturer not supported yet.\n");
break;
} }
} }
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
// setup TLV break;
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); gap_local_bd_addr(addr);
strcat(tlv_db_path, bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); // setup TLV
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); strcat(tlv_db_path, bd_addr_to_str(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);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
case HCI_EVENT_COMMAND_COMPLETE: case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){ if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name))
if (hci_event_command_complete_get_return_parameters(packet)[0]) break; {
// terminate, name 248 chars if (hci_event_command_complete_get_return_parameters(packet)[0])
packet[6+248] = 0; break;
printf("Local name: %s\n", &packet[6]); // terminate, name 248 chars
} packet[6 + 248] = 0;
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ printf("Local name: %s\n", &packet[6]);
local_version_information_handler(packet); }
} if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
break; {
default: local_version_information_handler(packet);
break; }
break;
default:
break;
} }
} }
int main(int argc, const char * argv[]){ int main(int argc, const char *argv[])
{
/// GET STARTED with BTstack /// /// GET STARTED with BTstack ///
btstack_memory_init(); btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance()); btstack_run_loop_init(btstack_run_loop_posix_get_instance());
// log into file using HCI_DUMP_PACKETLOGGER format // log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -219,17 +232,18 @@ int main(int argc, const char * argv[]){
config.device_name = "/dev/tty.usbserial-A900K0VK"; // CSR8811 breakout board config.device_name = "/dev/tty.usbserial-A900K0VK"; // CSR8811 breakout board
// accept path from command line // accept path from command line
if (argc >= 3 && strcmp(argv[1], "-u") == 0){ if (argc >= 3 && strcmp(argv[1], "-u") == 0)
{
config.device_name = argv[2]; config.device_name = argv[2];
argc -= 2; argc -= 2;
memmove(&argv[1], &argv[3], (argc-1) * sizeof(char *)); memmove(&argv[1], &argv[3], (argc - 1) * sizeof(char *));
} }
printf("H5 device: %s\n", config.device_name); printf("H5 device: %s\n", config.device_name);
// init HCI // init HCI
const btstack_uart_t * uart_driver = (const btstack_uart_t *) btstack_uart_posix_instance(); const btstack_uart_t *uart_driver = (const btstack_uart_t *)btstack_uart_posix_instance();
const hci_transport_t * transport = hci_transport_h5_instance(uart_driver); const hci_transport_t *transport = hci_transport_h5_instance(uart_driver);
hci_init(transport, (void*) &config); hci_init(transport, (void *)&config);
// set BD_ADDR for CSR without Flash/unique address // set BD_ADDR for CSR without Flash/unique address
// bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; // bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};

View file

@ -86,14 +86,14 @@
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static bd_addr_t local_addr; static bd_addr_t local_addr;
static int is_bcm; static int is_bcm;
extern "C" int btstack_main(int argc, const char * argv[]); extern "C" int btstack_main(int argc, const char *argv[]);
static const uint8_t read_static_address_command_complete_prefix[] = { 0x0e, 0x1b, 0x01, 0x09, 0xfc }; static const uint8_t read_static_address_command_complete_prefix[] = {0x0e, 0x1b, 0x01, 0x09, 0xfc};
static bd_addr_t static_address; static bd_addr_t static_address;
static int using_static_address; static int using_static_address;
@ -104,111 +104,124 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
static hci_transport_config_uart_t config = { static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
0, // main baudrate 0, // main baudrate
1, // flow control 1, // flow control
NULL, NULL,
}; };
static void use_fast_uart(void){ static void use_fast_uart(void)
printf("Using 921600 baud.\n"); {
config.baudrate_main = 921600; printf("Using 460800 baud.\n");
config.baudrate_main = 460800;
} }
static void local_version_information_handler(uint8_t * packet){ static void local_version_information_handler(uint8_t *packet)
{
printf("Local version information:\n"); printf("Local version information:\n");
uint16_t hci_version = packet[6]; uint16_t hci_version = packet[6];
uint16_t hci_revision = little_endian_read_16(packet, 7); uint16_t hci_revision = little_endian_read_16(packet, 7);
uint16_t lmp_version = packet[9]; uint16_t lmp_version = packet[9];
uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t manufacturer = little_endian_read_16(packet, 10);
uint16_t lmp_subversion = little_endian_read_16(packet, 12); uint16_t lmp_subversion = little_endian_read_16(packet, 12);
printf("- HCI Version 0x%04x\n", hci_version); printf("- HCI Version 0x%04x\n", hci_version);
printf("- HCI Revision 0x%04x\n", hci_revision); printf("- HCI Revision 0x%04x\n", hci_revision);
printf("- LMP Version 0x%04x\n", lmp_version); printf("- LMP Version 0x%04x\n", lmp_version);
printf("- LMP Subversion 0x%04x\n", lmp_subversion); printf("- LMP Subversion 0x%04x\n", lmp_subversion);
printf("- Manufacturer 0x%04x\n", manufacturer); printf("- Manufacturer 0x%04x\n", manufacturer);
switch (manufacturer){ switch (manufacturer)
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: {
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
use_fast_uart(); printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
hci_set_chipset(btstack_chipset_csr_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_csr_instance());
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: break;
printf("Texas Instruments - CC256x compatible chipset.\n"); case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ printf("Texas Instruments - CC256x compatible chipset.\n");
printf("Error: LMP Subversion does not match initscript! "); if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); {
printf("Please update CMakeLists.txt to include the appropriate bluetooth_init_cc256???.c file\n"); printf("Error: LMP Subversion does not match initscript! ");
exit(10); printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
} printf("Please update CMakeLists.txt to include the appropriate bluetooth_init_cc256???.c file\n");
use_fast_uart(); exit(10);
hci_set_chipset(btstack_chipset_cc256x_instance()); }
use_fast_uart();
hci_set_chipset(btstack_chipset_cc256x_instance());
#ifdef ENABLE_EHCILL #ifdef ENABLE_EHCILL
printf("eHCILL enabled.\n"); printf("eHCILL enabled.\n");
#else #else
printf("eHCILL disable.\n"); printf("eHCILL disable.\n");
#endif #endif
break; break;
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
printf("Broadcom/Cypress - using BCM driver.\n"); printf("Broadcom/Cypress - using BCM driver.\n");
hci_set_chipset(btstack_chipset_bcm_instance()); hci_set_chipset(btstack_chipset_bcm_instance());
use_fast_uart(); use_fast_uart();
is_bcm = 1; is_bcm = 1;
break; break;
default: default:
printf("Unknown manufacturer / manufacturer not supported yet.\n"); printf("Unknown manufacturer / manufacturer not supported yet.\n");
break; break;
} }
} }
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ {
UNUSED(channel); UNUSED(channel);
UNUSED(size); UNUSED(size);
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; {
gap_local_bd_addr(local_addr); case BTSTACK_EVENT_STATE:
if (using_static_address){ if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
memcpy(local_addr, static_address, 6); return;
} gap_local_bd_addr(local_addr);
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); if (using_static_address)
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); {
memcpy(local_addr, static_address, 6);
}
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
// bd_addr_to_str use ":" which is not allowed in windows file names // bd_addr_to_str use ":" which is not allowed in windows file names
strcat(tlv_db_path, bd_addr_to_str(local_addr)); strcat(tlv_db_path, bd_addr_to_str(local_addr));
#endif #endif
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); strcat(tlv_db_path, TLV_DB_PATH_POSTFIX);
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path);
btstack_tlv_set_instance(tlv_impl, &tlv_context); btstack_tlv_set_instance(tlv_impl, &tlv_context);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
case HCI_EVENT_COMMAND_COMPLETE: case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){ if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name))
if (hci_event_command_complete_get_return_parameters(packet)[0]) break; {
// terminate, name 248 chars if (hci_event_command_complete_get_return_parameters(packet)[0])
packet[6+248] = 0; break;
printf("Local name: %s\n", &packet[6]); // terminate, name 248 chars
if (is_bcm){ packet[6 + 248] = 0;
btstack_chipset_bcm_set_device_name((const char *)&packet[6]); printf("Local name: %s\n", &packet[6]);
} if (is_bcm)
{
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
} }
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ }
local_version_information_handler(packet); if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
} {
break; local_version_information_handler(packet);
default: }
break; break;
default:
break;
} }
} }
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -225,15 +238,17 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
#define USB_MAX_PATH_LEN 7 #define USB_MAX_PATH_LEN 7
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
int main(int argc, char * argv[]){ int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
@ -249,20 +264,20 @@ int main(int argc, char * argv[]){
strcpy(pklg_path, "/tmp/hci_dump.pklg"); strcpy(pklg_path, "/tmp/hci_dump.pklg");
#endif #endif
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
// init HCI // init HCI
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
const btstack_uart_block_t * uart_driver = btstack_uart_block_windows_instance(); const btstack_uart_block_t *uart_driver = btstack_uart_block_windows_instance();
config.device_name = "\\\\.\\COM7"; config.device_name = "\\\\.\\COM7";
#else #else
const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); const btstack_uart_t *uart_driver = btstack_uart_posix_instance();
config.device_name = "/dev/tty.usbserial-A900K2WS"; // DFROBOT config.device_name = "/dev/tty.usbserial-A900K2WS"; // DFROBOT
#endif #endif
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver); const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
hci_init(transport, (void*) &config); hci_init(transport, (void *)&config);
#ifdef HAVE_PORTAUDIO #ifdef HAVE_PORTAUDIO
btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance()); btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance());
@ -277,7 +292,7 @@ int main(int argc, char * argv[]){
signal(SIGINT, sigint_handler); signal(SIGINT, sigint_handler);
// setup app // setup app
btstack_main(argc, (const char **) argv); btstack_main(argc, (const char **)argv);
// enter Qt run loop // enter Qt run loop
return a.exec(); return a.exec();

View file

@ -81,12 +81,12 @@
#include "btstack_chipset_bcm_download_firmware.h" #include "btstack_chipset_bcm_download_firmware.h"
#include "btstack_control_raspi.h" #include "btstack_control_raspi.h"
#include "raspi_get_model.h" #include "raspi_get_model.h"
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
typedef enum { typedef enum
{
UART_INVALID, UART_INVALID,
UART_SOFTWARE_NO_FLOW, UART_SOFTWARE_NO_FLOW,
UART_HARDWARE_NO_FLOW, UART_HARDWARE_NO_FLOW,
@ -97,95 +97,96 @@ typedef enum {
static hci_transport_config_uart_t transport_config = { static hci_transport_config_uart_t transport_config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
0, // main baudrate 0, // main baudrate
0, // flow control 0, // flow control
NULL, NULL,
}; };
static btstack_uart_config_t uart_config; static btstack_uart_config_t uart_config;
static int main_argc; static int main_argc;
static const char ** main_argv; static const char **main_argv;
static btstack_packet_callback_registration_t hci_event_callback_registration; static btstack_packet_callback_registration_t hci_event_callback_registration;
#define TLV_DB_PATH_PREFIX "/tmp/btstack_" #define TLV_DB_PATH_PREFIX "/tmp/btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static int raspi_speed_to_baud(speed_t baud) static int raspi_speed_to_baud(speed_t baud)
{ {
switch (baud) { switch (baud)
case B9600: {
return 9600; case B9600:
case B19200: return 9600;
return 19200; case B19200:
case B38400: return 19200;
return 38400; case B38400:
case B57600: return 38400;
return 57600; case B57600:
case B115200: return 57600;
return 115200; case B115200:
case B230400: return 115200;
return 230400; case B230400:
case B460800: return 230400;
return 460800; case B460800:
case B500000: return 460800;
return 500000; case B500000:
case B576000: return 500000;
return 576000; case B576000:
case B921600: return 576000;
return 921600; case B460800:
case B1000000: return 460800;
return 1000000; case B1000000:
case B1152000: return 1000000;
return 1152000; case B1152000:
case B1500000: return 1152000;
return 1500000; case B1500000:
case B2000000: return 1500000;
return 2000000; case B2000000:
case B2500000: return 2000000;
return 2500000; case B2500000:
case B3000000: return 2500000;
return 3000000; case B3000000:
case B3500000: return 3000000;
return 3500000; case B3500000:
case B4000000: return 3500000;
return 4000000; case B4000000:
default: return 4000000;
return -1; default:
return -1;
} }
} }
static void raspi_get_terminal_params( hci_transport_config_uart_t *tc ) static void raspi_get_terminal_params(hci_transport_config_uart_t *tc)
{ {
// open serial terminal and get parameters // open serial terminal and get parameters
int fd = open( tc->device_name, O_RDONLY ); int fd = open(tc->device_name, O_RDONLY);
if( fd < 0 ) if (fd < 0)
{ {
perror( "can't open serial port" ); perror("can't open serial port");
return; return;
} }
struct termios tios; struct termios tios;
tcgetattr( fd, &tios ); tcgetattr(fd, &tios);
close( fd ); close(fd);
speed_t ospeed = cfgetospeed( &tios ); speed_t ospeed = cfgetospeed(&tios);
int baud = raspi_speed_to_baud( ospeed ); int baud = raspi_speed_to_baud(ospeed);
printf( "current serial terminal parameter baudrate: %d, flow control: %s\n", baud, (tios.c_cflag&CRTSCTS)?"Hardware":"None" ); printf("current serial terminal parameter baudrate: %d, flow control: %s\n", baud, (tios.c_cflag & CRTSCTS) ? "Hardware" : "None");
// overwrites the initial baudrate only in case it was likely to be altered before // overwrites the initial baudrate only in case it was likely to be altered before
if( baud > 9600 ) if (baud > 9600)
{ {
tc->baudrate_init = baud; tc->baudrate_init = baud;
tc->flowcontrol = (tios.c_cflag & CRTSCTS)?1:0; tc->flowcontrol = (tios.c_cflag & CRTSCTS) ? 1 : 0;
} }
} }
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n"); printf("CTRL-C - SIGINT received, shutting down..\n");
@ -202,112 +203,139 @@ static void sigint_handler(int param){
} }
static int led_state = 0; static int led_state = 0;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
// setup TLV break;
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); gap_local_bd_addr(addr);
strcat(tlv_db_path, bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); // setup TLV
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); strcat(tlv_db_path, bd_addr_to_str(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);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
break; break;
case HCI_EVENT_COMMAND_COMPLETE: case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){ if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name))
if (hci_event_command_complete_get_return_parameters(packet)[0]) break; {
// terminate, name 248 chars if (hci_event_command_complete_get_return_parameters(packet)[0])
packet[6+248] = 0; break;
printf("Local name: %s\n", &packet[6]); // terminate, name 248 chars
packet[6 + 248] = 0;
printf("Local name: %s\n", &packet[6]);
btstack_chipset_bcm_set_device_name((const char *)&packet[6]); btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
} }
break; break;
default: default:
break; break;
} }
} }
// see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart // see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart
static int raspi_get_bd_addr(bd_addr_t addr){ static int raspi_get_bd_addr(bd_addr_t addr)
{
FILE *fd = fopen( "/proc/device-tree/serial-number", "r" ); FILE *fd = fopen("/proc/device-tree/serial-number", "r");
if( fd == NULL ){ if (fd == NULL)
fprintf(stderr, "can't read serial number, %s\n", strerror( errno ) ); {
fprintf(stderr, "can't read serial number, %s\n", strerror(errno));
return -1; return -1;
} }
fscanf( fd, "%*08x" "%*02x" "%02" SCNx8 "%02" SCNx8 "%02" SCNx8, &addr[3], &addr[4], &addr[5] ); fscanf(fd, "%*08x"
fclose( fd ); "%*02x"
"%02" SCNx8 "%02" SCNx8 "%02" SCNx8,
&addr[3], &addr[4], &addr[5]);
fclose(fd);
addr[0] = 0xb8; addr[1] = 0x27; addr[2] = 0xeb; addr[0] = 0xb8;
addr[3] ^= 0xaa; addr[4] ^= 0xaa; addr[5] ^= 0xaa; addr[1] = 0x27;
addr[2] = 0xeb;
addr[3] ^= 0xaa;
addr[4] ^= 0xaa;
addr[5] ^= 0xaa;
return 0; return 0;
} }
// see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart // see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart
// on UART_INVALID errno is set // on UART_INVALID errno is set
static uart_type_t raspi_get_bluetooth_uart_type(void){ static uart_type_t raspi_get_bluetooth_uart_type(void)
{
uint8_t deviceUart0[21] = { 0 }; uint8_t deviceUart0[21] = {0};
FILE *fd = fopen( "/proc/device-tree/aliases/uart0", "r" ); FILE *fd = fopen("/proc/device-tree/aliases/uart0", "r");
if( fd == NULL ) return UART_INVALID; if (fd == NULL)
fscanf( fd, "%20s", deviceUart0 ); return UART_INVALID;
fclose( fd ); fscanf(fd, "%20s", deviceUart0);
fclose(fd);
uint8_t deviceSerial1[21] = { 0 }; uint8_t deviceSerial1[21] = {0};
fd = fopen( "/proc/device-tree/aliases/serial1", "r" ); fd = fopen("/proc/device-tree/aliases/serial1", "r");
if( fd == NULL ) return UART_INVALID; if (fd == NULL)
fscanf( fd, "%20s", deviceSerial1 ); return UART_INVALID;
fclose( fd ); fscanf(fd, "%20s", deviceSerial1);
fclose(fd);
// test if uart0 is an alias for serial1 // test if uart0 is an alias for serial1
if( strncmp( (const char *) deviceUart0, (const char *) deviceSerial1, 21 ) == 0 ){ if (strncmp((const char *)deviceUart0, (const char *)deviceSerial1, 21) == 0)
{
// HW uart // HW uart
size_t count = 0; size_t count = 0;
uint8_t buf[16]; uint8_t buf[16];
fd = fopen( "/proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm,pins", "r" ); fd = fopen("/proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm,pins", "r");
if( fd == NULL ) return UART_INVALID; if (fd == NULL)
count = fread( buf, 1, 16, fd ); return UART_INVALID;
fclose( fd ); count = fread(buf, 1, 16, fd);
fclose(fd);
// contains assigned pins // contains assigned pins
int pins = count / 4; int pins = count / 4;
if( pins == 4 ){ if (pins == 4)
{
return UART_HARDWARE_FLOW; return UART_HARDWARE_FLOW;
} else { }
else
{
return UART_HARDWARE_NO_FLOW; return UART_HARDWARE_NO_FLOW;
} }
} else { }
else
{
return UART_SOFTWARE_NO_FLOW; return UART_SOFTWARE_NO_FLOW;
} }
} }
static void phase2(int status); static void phase2(int status);
int main(int argc, const char * argv[]){ int main(int argc, const char *argv[])
{
/// GET STARTED with BTstack /// /// GET STARTED with BTstack ///
btstack_memory_init(); btstack_memory_init();
// log into file using HCI_DUMP_PACKETLOGGER format // log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -318,84 +346,92 @@ int main(int argc, const char * argv[]){
transport_config.device_name = "/dev/serial1"; transport_config.device_name = "/dev/serial1";
// derive bd_addr from serial number // derive bd_addr from serial number
bd_addr_t addr = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; bd_addr_t addr = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
raspi_get_bd_addr(addr); raspi_get_bd_addr(addr);
// set UART config based on raspi Bluetooth UART type // set UART config based on raspi Bluetooth UART type
int bt_reg_en_pin = -1; int bt_reg_en_pin = -1;
bool power_cycle = true; bool power_cycle = true;
switch (raspi_get_bluetooth_uart_type()){ switch (raspi_get_bluetooth_uart_type())
case UART_INVALID: {
fprintf(stderr, "can't verify HW uart, %s\n", strerror( errno ) ); case UART_INVALID:
return -1; fprintf(stderr, "can't verify HW uart, %s\n", strerror(errno));
case UART_SOFTWARE_NO_FLOW: return -1;
// ?? case UART_SOFTWARE_NO_FLOW:
bt_reg_en_pin = 128; // ??
bt_reg_en_pin = 128;
transport_config.baudrate_main = 460800;
transport_config.flowcontrol = 0;
break;
case UART_HARDWARE_NO_FLOW:
// Raspberry Pi 3 A
// Raspberry Pi 3 B
// power up with H5 and without power cycle untested/unsupported
bt_reg_en_pin = 128;
transport_config.baudrate_main = 460800;
transport_config.flowcontrol = 0;
break;
case UART_HARDWARE_FLOW:
// Raspberry Pi Zero W gpio 45, 3 mbps does not work (investigation pending)
// Raspberry Pi 3A+ vgpio 129 but WLAN + BL
// Raspberry Pi 3B+ vgpio 129 but WLAN + BL
transport_config.flowcontrol = 1;
int model = raspi_get_model();
if (model == MODEL_ZERO_W)
{
bt_reg_en_pin = 45;
transport_config.baudrate_main = 460800; transport_config.baudrate_main = 460800;
transport_config.flowcontrol = 0; }
break; else
case UART_HARDWARE_NO_FLOW: {
// Raspberry Pi 3 A bt_reg_en_pin = 129;
// Raspberry Pi 3 B transport_config.baudrate_main = 3000000;
// power up with H5 and without power cycle untested/unsupported }
bt_reg_en_pin = 128;
transport_config.baudrate_main = 921600;
transport_config.flowcontrol = 0;
break;
case UART_HARDWARE_FLOW:
// Raspberry Pi Zero W gpio 45, 3 mbps does not work (investigation pending)
// Raspberry Pi 3A+ vgpio 129 but WLAN + BL
// Raspberry Pi 3B+ vgpio 129 but WLAN + BL
transport_config.flowcontrol = 1;
int model = raspi_get_model();
if (model == MODEL_ZERO_W){
bt_reg_en_pin = 45;
transport_config.baudrate_main = 921600;
} else {
bt_reg_en_pin = 129;
transport_config.baudrate_main = 3000000;
}
#ifdef ENABLE_CONTROLLER_WARM_BOOT #ifdef ENABLE_CONTROLLER_WARM_BOOT
power_cycle = false; power_cycle = false;
#else #else
// warn about power cycle on devices with shared reg_en pins // warn about power cycle on devices with shared reg_en pins
if (model == MODEL_3APLUS || model == MODEL_3BPLUS){ if (model == MODEL_3APLUS || model == MODEL_3BPLUS)
printf("Wifi and Bluetooth share a single RESET line and BTstack needs to reset Bluetooth -> SSH over Wifi will fail\n"); {
printf("Please add ENABLE_CONTROLLER_WARM_BOOT to btstack_config.h to enable startup without RESET\n"); printf("Wifi and Bluetooth share a single RESET line and BTstack needs to reset Bluetooth -> SSH over Wifi will fail\n");
} printf("Please add ENABLE_CONTROLLER_WARM_BOOT to btstack_config.h to enable startup without RESET\n");
}
#endif #endif
break; break;
} }
printf("%s, %u, BT_REG_EN at GPIO %u, %s\n", transport_config.flowcontrol ? "H4":"H5", transport_config.baudrate_main, bt_reg_en_pin, power_cycle ? "Reset Controller" : "Warm Boot"); printf("%s, %u, BT_REG_EN at GPIO %u, %s\n", transport_config.flowcontrol ? "H4" : "H5", transport_config.baudrate_main, bt_reg_en_pin, power_cycle ? "Reset Controller" : "Warm Boot");
// get BCM chipset driver // get BCM chipset driver
const btstack_chipset_t * chipset = btstack_chipset_bcm_instance(); const btstack_chipset_t *chipset = btstack_chipset_bcm_instance();
chipset->init(&transport_config); chipset->init(&transport_config);
// set path to firmware files // set path to firmware files
btstack_chipset_bcm_set_hcd_folder_path("/lib/firmware/brcm"); btstack_chipset_bcm_set_hcd_folder_path("/lib/firmware/brcm");
// setup UART driver // setup UART driver
const btstack_uart_t * uart_driver = btstack_uart_posix_instance(); const btstack_uart_t *uart_driver = btstack_uart_posix_instance();
// extract UART config from transport config // extract UART config from transport config
uart_config.baudrate = transport_config.baudrate_init; uart_config.baudrate = transport_config.baudrate_init;
uart_config.flowcontrol = transport_config.flowcontrol; uart_config.flowcontrol = transport_config.flowcontrol;
uart_config.device_name = transport_config.device_name; uart_config.device_name = transport_config.device_name;
uart_driver->init(&uart_config); uart_driver->init(&uart_config);
// HW with FlowControl -> we can use regular h4 mode // HW with FlowControl -> we can use regular h4 mode
const hci_transport_t * transport; const hci_transport_t *transport;
if (transport_config.flowcontrol){ if (transport_config.flowcontrol)
{
transport = hci_transport_h4_instance(uart_driver); transport = hci_transport_h4_instance(uart_driver);
} else { }
else
{
transport = hci_transport_h5_instance(uart_driver); transport = hci_transport_h5_instance(uart_driver);
} }
// setup HCI (to be able to use bcm chipset driver) // setup HCI (to be able to use bcm chipset driver)
hci_init(transport, (void*) &transport_config); hci_init(transport, (void *)&transport_config);
hci_set_bd_addr( addr ); hci_set_bd_addr(addr);
hci_set_chipset(btstack_chipset_bcm_instance()); hci_set_chipset(btstack_chipset_bcm_instance());
// inform about BTstack state // inform about BTstack state
@ -409,26 +445,30 @@ int main(int argc, const char * argv[]){
main_argv = argv; main_argv = argv;
// power cycle Bluetooth controller on older models without flowcontrol // power cycle Bluetooth controller on older models without flowcontrol
if (power_cycle){ if (power_cycle)
{
btstack_control_raspi_set_bt_reg_en_pin(bt_reg_en_pin); btstack_control_raspi_set_bt_reg_en_pin(bt_reg_en_pin);
btstack_control_t *control = btstack_control_raspi_get_instance(); btstack_control_t *control = btstack_control_raspi_get_instance();
control->init(NULL); control->init(NULL);
control->off(); control->off();
usleep( 100000 ); usleep(100000);
control->on(); control->on();
} }
if (transport_config.flowcontrol){ if (transport_config.flowcontrol)
{
// re-use current terminal speed (if there was no power cycle) // re-use current terminal speed (if there was no power cycle)
if (!power_cycle){ if (!power_cycle)
raspi_get_terminal_params( &transport_config ); {
raspi_get_terminal_params(&transport_config);
} }
// with flowcontrol, we use h4 and are done // with flowcontrol, we use h4 and are done
btstack_main(main_argc, main_argv); btstack_main(main_argc, main_argv);
}
} else { else
{
// assume BCM4343W used in Pi 3 A/B. Pi 3 A/B+ have a newer controller but support H4 with Flowcontrol // assume BCM4343W used in Pi 3 A/B. Pi 3 A/B+ have a newer controller but support H4 with Flowcontrol
btstack_chipset_bcm_set_device_name("BCM43430A1"); btstack_chipset_bcm_set_device_name("BCM43430A1");
@ -445,9 +485,11 @@ int main(int argc, const char * argv[]){
return 0; return 0;
} }
static void phase2(int status){ static void phase2(int status)
{
if (status){ if (status)
{
printf("Download firmware failed\n"); printf("Download firmware failed\n");
return; return;
} }
@ -457,4 +499,3 @@ static void phase2(int status){
// setup app // setup app
btstack_main(main_argc, main_argv); btstack_main(main_argc, main_argv);
} }

View file

@ -70,14 +70,14 @@
#include "btstack_chipset_stlc2500d.h" #include "btstack_chipset_stlc2500d.h"
#include "btstack_chipset_tc3566x.h" #include "btstack_chipset_tc3566x.h"
int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char *argv[]);
static void local_version_information_handler(uint8_t * packet); static void local_version_information_handler(uint8_t *packet);
static hci_transport_config_uart_t config = { static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
115200, 115200,
0, // main baudrate 0, // main baudrate
1, // flow control 1, // flow control
NULL, NULL,
}; };
@ -88,16 +88,18 @@ static int led_state = 0;
#define TLV_DB_PATH_PREFIX "btstack_" #define TLV_DB_PATH_PREFIX "btstack_"
#define TLV_DB_PATH_POSTFIX ".tlv" #define TLV_DB_PATH_POSTFIX ".tlv"
static char tlv_db_path[100]; static char tlv_db_path[100];
static const btstack_tlv_t * tlv_impl; static const btstack_tlv_t *tlv_impl;
static btstack_tlv_posix_t tlv_context; static btstack_tlv_posix_t tlv_context;
static bd_addr_t local_addr; static bd_addr_t local_addr;
void hal_led_toggle(void){ void hal_led_toggle(void)
{
led_state = 1 - led_state; led_state = 1 - led_state;
printf("LED State %u\n", led_state); printf("LED State %u\n", led_state);
} }
static void sigint_handler(int param){ static void sigint_handler(int param)
{
UNUSED(param); UNUSED(param);
printf("CTRL-C = SIGINT received, shutting down..\n"); printf("CTRL-C = SIGINT received, shutting down..\n");
@ -115,114 +117,127 @@ static void sigint_handler(int param){
static btstack_packet_callback_registration_t hci_event_callback_registration; 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){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
bd_addr_t addr; bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET)
switch (hci_event_packet_get_type(packet)){ return;
case BTSTACK_EVENT_STATE: switch (hci_event_packet_get_type(packet))
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; {
gap_local_bd_addr(addr); case BTSTACK_EVENT_STATE:
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX); break;
strcat(tlv_db_path, bd_addr_to_str(local_addr)); gap_local_bd_addr(addr);
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX); printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path); strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
btstack_tlv_set_instance(tlv_impl, &tlv_context); 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);
#ifdef ENABLE_CLASSIC #ifdef ENABLE_CLASSIC
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context)); hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
#endif #endif
#ifdef ENABLE_BLE #ifdef ENABLE_BLE
le_device_db_tlv_configure(tlv_impl, &tlv_context); le_device_db_tlv_configure(tlv_impl, &tlv_context);
#endif #endif
printf("BTstack up and running at %s\n", bd_addr_to_str(addr)); printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
break; break;
case HCI_EVENT_COMMAND_COMPLETE: case HCI_EVENT_COMMAND_COMPLETE:
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){ if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name))
if (hci_event_command_complete_get_return_parameters(packet)[0]) break; {
// terminate, name 248 chars if (hci_event_command_complete_get_return_parameters(packet)[0])
packet[6+248] = 0; break;
printf("Local name: %s\n", &packet[6]); // terminate, name 248 chars
if (is_bcm){ packet[6 + 248] = 0;
btstack_chipset_bcm_set_device_name((const char *)&packet[6]); printf("Local name: %s\n", &packet[6]);
} if (is_bcm)
{
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
} }
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ }
local_version_information_handler(packet); if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
} {
break; local_version_information_handler(packet);
default: }
break; break;
default:
break;
} }
} }
static void use_fast_uart(void){ static void use_fast_uart(void)
printf("Using 921600 baud.\n"); {
config.baudrate_main = 921600; printf("Using 460800 baud.\n");
config.baudrate_main = 460800;
} }
static void local_version_information_handler(uint8_t * packet){ static void local_version_information_handler(uint8_t *packet)
{
printf("Local version information:\n"); printf("Local version information:\n");
uint16_t hci_version = packet[6]; uint16_t hci_version = packet[6];
uint16_t hci_revision = little_endian_read_16(packet, 7); uint16_t hci_revision = little_endian_read_16(packet, 7);
uint16_t lmp_version = packet[9]; uint16_t lmp_version = packet[9];
uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t manufacturer = little_endian_read_16(packet, 10);
uint16_t lmp_subversion = little_endian_read_16(packet, 12); uint16_t lmp_subversion = little_endian_read_16(packet, 12);
printf("- HCI Version 0x%04x\n", hci_version); printf("- HCI Version 0x%04x\n", hci_version);
printf("- HCI Revision 0x%04x\n", hci_revision); printf("- HCI Revision 0x%04x\n", hci_revision);
printf("- LMP Version 0x%04x\n", lmp_version); printf("- LMP Version 0x%04x\n", lmp_version);
printf("- LMP Revision 0x%04x\n", lmp_subversion); printf("- LMP Revision 0x%04x\n", lmp_subversion);
printf("- Manufacturer 0x%04x\n", manufacturer); printf("- Manufacturer 0x%04x\n", manufacturer);
switch (manufacturer){ switch (manufacturer)
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO: {
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision); case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
use_fast_uart(); printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
hci_set_chipset(btstack_chipset_csr_instance()); use_fast_uart();
break; hci_set_chipset(btstack_chipset_csr_instance());
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: break;
printf("Texas Instruments - CC256x compatible chipset.\n"); case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ printf("Texas Instruments - CC256x compatible chipset.\n");
printf("Error: LMP Subversion does not match initscript!"); if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); {
printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n"); printf("Error: LMP Subversion does not match initscript!");
exit(10); printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
} printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
use_fast_uart(); exit(10);
hci_set_chipset(btstack_chipset_cc256x_instance()); }
use_fast_uart();
hci_set_chipset(btstack_chipset_cc256x_instance());
#ifdef ENABLE_EHCILL #ifdef ENABLE_EHCILL
printf("eHCILL enabled.\n"); printf("eHCILL enabled.\n");
#else #else
printf("eHCILL disable.\n"); printf("eHCILL disable.\n");
#endif #endif
break; break;
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION: case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
printf("Broadcom - using BCM driver.\n"); printf("Broadcom - using BCM driver.\n");
hci_set_chipset(btstack_chipset_bcm_instance()); hci_set_chipset(btstack_chipset_bcm_instance());
use_fast_uart(); use_fast_uart();
is_bcm = 1; is_bcm = 1;
break; break;
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS: case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
printf("ST Microelectronics - using STLC2500d driver.\n"); printf("ST Microelectronics - using STLC2500d driver.\n");
use_fast_uart(); use_fast_uart();
hci_set_chipset(btstack_chipset_stlc2500d_instance()); hci_set_chipset(btstack_chipset_stlc2500d_instance());
break; break;
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA: case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
printf("EM Microelectronics - using EM9301 driver.\n"); printf("EM Microelectronics - using EM9301 driver.\n");
hci_set_chipset(btstack_chipset_em9301_instance()); hci_set_chipset(btstack_chipset_em9301_instance());
break; break;
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA: case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
printf("Nordic Semiconductor nRF5 chipset.\n"); printf("Nordic Semiconductor nRF5 chipset.\n");
break; break;
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP: case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
printf("Toshiba - using TC3566x driver.\n"); printf("Toshiba - using TC3566x driver.\n");
hci_set_chipset(btstack_chipset_tc3566x_instance()); hci_set_chipset(btstack_chipset_tc3566x_instance());
use_fast_uart(); use_fast_uart();
break; break;
default: default:
printf("Unknown manufacturer / manufacturer not supported yet.\n"); printf("Unknown manufacturer / manufacturer not supported yet.\n");
break; break;
} }
} }
int main(int argc, const char * argv[]){ int main(int argc, const char *argv[])
{
printf("BTstack on windows booting up\n"); printf("BTstack on windows booting up\n");
/// GET STARTED with BTstack /// /// GET STARTED with BTstack ///
@ -230,9 +245,9 @@ int main(int argc, const char * argv[]){
btstack_run_loop_init(btstack_run_loop_windows_get_instance()); btstack_run_loop_init(btstack_run_loop_windows_get_instance());
// log into file using HCI_DUMP_PACKETLOGGER format // log into file using HCI_DUMP_PACKETLOGGER format
const char * pklg_path = "/tmp/hci_dump.pklg"; const char *pklg_path = "/tmp/hci_dump.pklg";
hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
const hci_dump_t * hci_dump_impl = hci_dump_posix_fs_get_instance(); const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance();
hci_dump_init(hci_dump_impl); hci_dump_init(hci_dump_impl);
printf("Packet Log: %s\n", pklg_path); printf("Packet Log: %s\n", pklg_path);
@ -240,17 +255,18 @@ int main(int argc, const char * argv[]){
config.device_name = "\\\\.\\COM7"; config.device_name = "\\\\.\\COM7";
// accept path from command line // accept path from command line
if (argc >= 3 && strcmp(argv[1], "-u") == 0){ if (argc >= 3 && strcmp(argv[1], "-u") == 0)
{
config.device_name = argv[2]; config.device_name = argv[2];
argc -= 2; argc -= 2;
memmove(&argv[1], &argv[3], (argc-1) * sizeof(char *)); memmove(&argv[1], &argv[3], (argc - 1) * sizeof(char *));
} }
printf("H4 device: %s\n", config.device_name); printf("H4 device: %s\n", config.device_name);
// init HCI // init HCI
const btstack_uart_block_t * uart_driver = btstack_uart_block_windows_instance(); const btstack_uart_block_t *uart_driver = btstack_uart_block_windows_instance();
const hci_transport_t * transport = hci_transport_h4_instance(uart_driver); const hci_transport_t *transport = hci_transport_h4_instance(uart_driver);
hci_init(transport, (void*) &config); hci_init(transport, (void *)&config);
// inform about BTstack state // inform about BTstack state
hci_event_callback_registration.callback = &packet_handler; hci_event_callback_registration.callback = &packet_handler;

View file

@ -48,9 +48,9 @@
#include "btstack_run_loop.h" #include "btstack_run_loop.h"
#include "btstack_debug.h" #include "btstack_debug.h"
#include <termios.h> /* POSIX terminal control definitions */ #include <termios.h> /* POSIX terminal control definitions */
#include <fcntl.h> /* File control definitions */ #include <fcntl.h> /* File control definitions */
#include <unistd.h> /* UNIX standard function definitions */ #include <unistd.h> /* UNIX standard function definitions */
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#ifdef __APPLE__ #ifdef __APPLE__
@ -59,51 +59,56 @@
#endif #endif
// uart config // uart config
static const btstack_uart_config_t * uart_config; static const btstack_uart_config_t *uart_config;
// data source for integration with BTstack Runloop // data source for integration with BTstack Runloop
static btstack_data_source_t transport_data_source; static btstack_data_source_t transport_data_source;
// block write // block write
static int write_bytes_len; static int write_bytes_len;
static const uint8_t * write_bytes_data; static const uint8_t *write_bytes_data;
// block read // block read
static uint16_t read_bytes_len; static uint16_t read_bytes_len;
static uint8_t * read_bytes_data; static uint8_t *read_bytes_data;
// callbacks // callbacks
static void (*block_sent)(void); static void (*block_sent)(void);
static void (*block_received)(void); static void (*block_received)(void);
static int btstack_uart_posix_init(const btstack_uart_config_t *config)
static int btstack_uart_posix_init(const btstack_uart_config_t * config){ {
uart_config = config; uart_config = config;
return 0; return 0;
} }
static void btstack_uart_posix_process_write(btstack_data_source_t *ds) { static void btstack_uart_posix_process_write(btstack_data_source_t *ds)
{
if (write_bytes_len == 0) return; if (write_bytes_len == 0)
return;
uint32_t start = btstack_run_loop_get_time_ms(); uint32_t start = btstack_run_loop_get_time_ms();
// write up to write_bytes_len to fd // write up to write_bytes_len to fd
int bytes_written = (int) write(ds->source.fd, write_bytes_data, write_bytes_len); int bytes_written = (int)write(ds->source.fd, write_bytes_data, write_bytes_len);
if (bytes_written < 0) { if (bytes_written < 0)
{
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
log_info("h4_process: write took %u ms", end - start); log_info("h4_process: write took %u ms", end - start);
} }
write_bytes_data += bytes_written; write_bytes_data += bytes_written;
write_bytes_len -= bytes_written; write_bytes_len -= bytes_written;
if (write_bytes_len){ if (write_bytes_len)
{
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
return; return;
} }
@ -111,14 +116,17 @@ static void btstack_uart_posix_process_write(btstack_data_source_t *ds) {
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
// notify done // notify done
if (block_sent){ if (block_sent)
{
block_sent(); block_sent();
} }
} }
static void btstack_uart_posix_process_read(btstack_data_source_t *ds) { static void btstack_uart_posix_process_read(btstack_data_source_t *ds)
{
if (read_bytes_len == 0) { if (read_bytes_len == 0)
{
log_info("btstack_uart_posix_process_read but no read requested"); log_info("btstack_uart_posix_process_read but no read requested");
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
} }
@ -129,37 +137,45 @@ static void btstack_uart_posix_process_read(btstack_data_source_t *ds) {
ssize_t bytes_read = read(ds->source.fd, read_bytes_data, read_bytes_len); ssize_t bytes_read = read(ds->source.fd, read_bytes_data, read_bytes_len);
// log_info("btstack_uart_posix_process_read need %u bytes, got %d", read_bytes_len, (int) bytes_read); // log_info("btstack_uart_posix_process_read need %u bytes, got %d", read_bytes_len, (int) bytes_read);
uint32_t end = btstack_run_loop_get_time_ms(); uint32_t end = btstack_run_loop_get_time_ms();
if (end - start > 10){ if (end - start > 10)
{
log_info("h4_process: read took %u ms", end - start); log_info("h4_process: read took %u ms", end - start);
} }
if (bytes_read < 0) return; if (bytes_read < 0)
return;
read_bytes_len -= bytes_read; read_bytes_len -= bytes_read;
read_bytes_data += bytes_read; read_bytes_data += bytes_read;
if (read_bytes_len > 0) return; if (read_bytes_len > 0)
return;
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
if (block_received){ if (block_received)
{
block_received(); block_received();
} }
} }
static void hci_transport_h5_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { static void hci_transport_h5_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type)
if (ds->source.fd < 0) return; {
switch (callback_type){ if (ds->source.fd < 0)
case DATA_SOURCE_CALLBACK_READ: return;
btstack_uart_posix_process_read(ds); switch (callback_type)
break; {
case DATA_SOURCE_CALLBACK_WRITE: case DATA_SOURCE_CALLBACK_READ:
btstack_uart_posix_process_write(ds); btstack_uart_posix_process_read(ds);
break; break;
default: case DATA_SOURCE_CALLBACK_WRITE:
break; btstack_uart_posix_process_write(ds);
break;
default:
break;
} }
} }
static int btstack_uart_posix_set_baudrate(uint32_t baudrate){ static int btstack_uart_posix_set_baudrate(uint32_t baudrate)
{
UNUSED(baudrate); UNUSED(baudrate);
#if 0 #if 0
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
@ -199,8 +215,8 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
#ifdef B460800 #ifdef B460800
case 460800: brate=B460800; break; case 460800: brate=B460800; break;
#endif #endif
#ifdef B921600 #ifdef B460800
case 921600: brate=B921600; break; case 460800: brate=B460800; break;
#endif #endif
// Hacks to switch to 2/3 mbps on FTDI FT232 chipsets // Hacks to switch to 2/3 mbps on FTDI FT232 chipsets
@ -238,87 +254,103 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
return 0; return 0;
} }
static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){ static void btstack_uart_posix_set_parity_option(struct termios *toptions, int parity)
if (parity){ {
if (parity)
{
// enable even parity // enable even parity
toptions->c_cflag |= PARENB; toptions->c_cflag |= PARENB;
} else { }
else
{
// disable even parity // disable even parity
toptions->c_cflag &= ~PARENB; toptions->c_cflag &= ~PARENB;
} }
} }
static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){ static void btstack_uart_posix_set_flowcontrol_option(struct termios *toptions, int flowcontrol)
if (flowcontrol) { {
if (flowcontrol)
{
// with flow control // with flow control
toptions->c_cflag |= CRTSCTS; toptions->c_cflag |= CRTSCTS;
} else { }
else
{
// no flow control // no flow control
toptions->c_cflag &= ~CRTSCTS; toptions->c_cflag &= ~CRTSCTS;
} }
} }
static int btstack_uart_posix_set_parity(int parity){ static int btstack_uart_posix_set_parity(int parity)
{
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("btstack_uart_posix_set_parity: Couldn't get term attributes"); log_error("btstack_uart_posix_set_parity: Couldn't get term attributes");
return -1; return -1;
} }
btstack_uart_posix_set_parity_option(&toptions, parity); btstack_uart_posix_set_parity_option(&toptions, parity);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("posix_set_parity: Couldn't set term attributes"); log_error("posix_set_parity: Couldn't set term attributes");
return -1; return -1;
} }
return 0; return 0;
} }
static int btstack_uart_posix_set_flowcontrol(int flowcontrol)
static int btstack_uart_posix_set_flowcontrol(int flowcontrol){ {
int fd = transport_data_source.source.fd; int fd = transport_data_source.source.fd;
struct termios toptions; struct termios toptions;
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("btstack_uart_posix_set_parity: Couldn't get term attributes"); log_error("btstack_uart_posix_set_parity: Couldn't get term attributes");
return -1; return -1;
} }
btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol); btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("posix_set_flowcontrol: Couldn't set term attributes"); log_error("posix_set_flowcontrol: Couldn't set term attributes");
return -1; return -1;
} }
return 0; return 0;
} }
static int btstack_uart_posix_open(void){ static int btstack_uart_posix_open(void)
{
const char * device_name = uart_config->device_name; const char *device_name = uart_config->device_name;
const int flowcontrol = uart_config->flowcontrol; const int flowcontrol = uart_config->flowcontrol;
const uint32_t baudrate = uart_config->baudrate; const uint32_t baudrate = uart_config->baudrate;
struct termios toptions; struct termios toptions;
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK; int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
int fd = open(device_name, flags); int fd = open(device_name, flags);
if (fd == -1) { if (fd == -1)
{
log_error("posix_open: Unable to open port %s", device_name); log_error("posix_open: Unable to open port %s", device_name);
return -1; return -1;
} }
if (tcgetattr(fd, &toptions) < 0) { if (tcgetattr(fd, &toptions) < 0)
{
log_error("posix_open: Couldn't get term attributes"); log_error("posix_open: Couldn't get term attributes");
return -1; return -1;
} }
cfmakeraw(&toptions); // make raw cfmakeraw(&toptions); // make raw
// 8N1 // 8N1
toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag |= CS8; toptions.c_cflag |= CS8;
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 1; toptions.c_cc[VMIN] = 1;
toptions.c_cc[VTIME] = 0; toptions.c_cc[VTIME] = 0;
// no parity // no parity
@ -327,7 +359,8 @@ static int btstack_uart_posix_open(void){
// flowcontrol // flowcontrol
btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol); btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
if(tcsetattr(fd, TCSANOW, &toptions) < 0) { if (tcsetattr(fd, TCSANOW, &toptions) < 0)
{
log_error("posix_open: Couldn't set term attributes"); log_error("posix_open: Couldn't set term attributes");
return -1; return -1;
} }
@ -336,7 +369,8 @@ static int btstack_uart_posix_open(void){
transport_data_source.source.fd = fd; transport_data_source.source.fd = fd;
// also set baudrate // also set baudrate
if (btstack_uart_posix_set_baudrate(baudrate) < 0){ if (btstack_uart_posix_set_baudrate(baudrate) < 0)
{
return -1; return -1;
} }
@ -351,7 +385,8 @@ static int btstack_uart_posix_open(void){
return 0; return 0;
} }
static int btstack_uart_posix_close_new(void){ static int btstack_uart_posix_close_new(void)
{
// first remove run loop handler // first remove run loop handler
btstack_run_loop_remove_data_source(&transport_data_source); btstack_run_loop_remove_data_source(&transport_data_source);
@ -362,25 +397,29 @@ static int btstack_uart_posix_close_new(void){
return 0; return 0;
} }
static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){ static void btstack_uart_posix_set_block_received(void (*block_handler)(void))
{
block_received = block_handler; block_received = block_handler;
} }
static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){ static void btstack_uart_posix_set_block_sent(void (*block_handler)(void))
{
block_sent = block_handler; block_sent = block_handler;
} }
static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){ static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size)
{
// setup async write // setup async write
write_bytes_data = data; write_bytes_data = data;
write_bytes_len = size; write_bytes_len = size;
// go // go
// btstack_uart_posix_process_write(&transport_data_source); // btstack_uart_posix_process_write(&transport_data_source);
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
} }
static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){ static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len)
{
read_bytes_data = buffer; read_bytes_data = buffer;
read_bytes_len = len; read_bytes_len = len;
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
@ -395,22 +434,26 @@ static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
// } // }
static const btstack_uart_block_t btstack_uart_posix = { static const btstack_uart_block_t btstack_uart_posix = {
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init, /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
/* int (*open)(void); */ &btstack_uart_posix_open, /* int (*open)(void); */ &btstack_uart_posix_open,
/* int (*close)(void); */ &btstack_uart_posix_close_new, /* int (*close)(void); */ &btstack_uart_posix_close_new,
/* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received, /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received,
/* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent, /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent,
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate, /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity, /* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
/* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol, /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol,
/* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block, /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block,
/* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block, /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
/* int (*get_supported_sleep_modes); */ NULL, /* int (*get_supported_sleep_modes); */ NULL,
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL,
NULL,
}; };
const btstack_uart_block_t * btstack_uart_posix_instance(void){ const btstack_uart_block_t *btstack_uart_posix_instance(void)
return &btstack_uart_posix; {
return &btstack_uart_posix;
} }

View file

@ -86,7 +86,7 @@ static void local_version_information_handler(uint8_t *packet);
static hci_transport_config_uart_t config = { static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART, HCI_TRANSPORT_CONFIG_UART,
921600, 460800,
0, // main baudrate 0, // main baudrate
0, // flow control 0, // flow control
NULL, NULL,

View file

@ -67,11 +67,11 @@ class ESP32BTDriver:
serial_bridge = None serial_bridge = None
serial_bridge_name = None serial_bridge_name = None
serial_hci_thread = None serial_hci_thread = None
serial_baudrate = 921600 serial_baudrate = 460800
serial_portname = None serial_portname = None
# Constructor ------------------------------------ # Constructor ------------------------------------
def __init__(self, port_name=None, baudrate=921600, reset_board=True, def __init__(self, port_name=None, baudrate=460800, reset_board=True,
debug=False): debug=False):
self.serial_portname = port_name self.serial_portname = port_name