Lower baudrate
This commit is contained in:
parent
0e174ca570
commit
74ced478e0
23 changed files with 2576 additions and 2118 deletions
|
@ -55,7 +55,7 @@ class SnifferBREDR:
|
|||
# Constructor
|
||||
def __init__(self,
|
||||
serial_port=None,
|
||||
serial_baud=921600,
|
||||
serial_baud=460800,
|
||||
show_summary=True,
|
||||
start_wireshark=False,
|
||||
save_pcap=True,
|
||||
|
@ -187,7 +187,7 @@ class SnifferBREDR:
|
|||
|
||||
# Defaults
|
||||
serial_port = '/dev/ttyUSB0'
|
||||
serial_baud = 921600
|
||||
serial_baud = 460800
|
||||
|
||||
|
||||
@click.command()
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -41,7 +41,7 @@
|
|||
* btstack_chipset_em9301.c
|
||||
*
|
||||
* Adapter to use em9301-based chipsets with BTstack
|
||||
*
|
||||
*
|
||||
* Allows to set public BD ADDR
|
||||
*/
|
||||
|
||||
|
@ -49,31 +49,29 @@
|
|||
#include "btstack_chipset_em9301.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <string.h> /* memcpy */
|
||||
#include "hci.h"
|
||||
|
||||
// should go to some common place
|
||||
#define OPCODE(ogf, ocf) (ocf | ogf << 10)
|
||||
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27)
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28)
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29)
|
||||
#define HCI_OPCODE_EM_CPU_RESET (0xFC32)
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27)
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28)
|
||||
#define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29)
|
||||
#define HCI_OPCODE_EM_CPU_RESET (0xFC32)
|
||||
|
||||
/**
|
||||
* @param bd_addr
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_set_public_address = {
|
||||
0xFC02, "B"
|
||||
};
|
||||
0xFC02, "B"};
|
||||
|
||||
/**
|
||||
* @param baud_rate_index
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_set_uart_baudrate = {
|
||||
0xFC07, "1"
|
||||
};
|
||||
0xFC07, "1"};
|
||||
|
||||
/**
|
||||
* @param transmitter_test_mode
|
||||
|
@ -82,216 +80,227 @@ const hci_cmd_t hci_vendor_em_set_uart_baudrate = {
|
|||
* @param packet_payload_type
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_transmitter_test = {
|
||||
0xFC11, "1111"
|
||||
};
|
||||
0xFC11, "1111"};
|
||||
|
||||
/**
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_transmitter_test_end = {
|
||||
0xFC12, ""
|
||||
};
|
||||
0xFC12, ""};
|
||||
|
||||
/**
|
||||
* @param patch_index
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_patch_query = {
|
||||
0xFC34, "2"
|
||||
};
|
||||
0xFC34, "2"};
|
||||
|
||||
/**
|
||||
* Change the state of the selected memory.
|
||||
* @param memory_attribute
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_set_memory_mode = {
|
||||
0xFC2B, "1"
|
||||
};
|
||||
0xFC2B, "1"};
|
||||
|
||||
/**
|
||||
* @param sleep_option_settings
|
||||
*/
|
||||
const hci_cmd_t hci_vendor_em_set_sleep_options = {
|
||||
0xFC2D, "1"
|
||||
};
|
||||
0xFC2D, "1"};
|
||||
|
||||
// baudrate to index for hci_vendor_em_set_uart_baudrate
|
||||
static const uint32_t baudrates[] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
9600,
|
||||
14400,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
76800,
|
||||
115200,
|
||||
230400,
|
||||
460800,
|
||||
921600,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
9600,
|
||||
14400,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
76800,
|
||||
115200,
|
||||
230400,
|
||||
460800,
|
||||
460800,
|
||||
1843200,
|
||||
};
|
||||
|
||||
#ifdef HAVE_EM9304_PATCH_CONTAINER
|
||||
|
||||
extern const uint8_t container_blob_data[];
|
||||
extern const uint32_t container_blob_size;
|
||||
extern const uint8_t container_blob_data[];
|
||||
extern const uint32_t container_blob_size;
|
||||
|
||||
static uint32_t container_blob_offset = 0;
|
||||
static uint32_t container_end; // current container
|
||||
static uint32_t container_blob_offset = 0;
|
||||
static uint32_t container_end; // current container
|
||||
static uint16_t patch_sequence_number;
|
||||
static int em_cpu_reset_sent;
|
||||
static int em_cpu_reset_sent;
|
||||
|
||||
static enum {
|
||||
UPLOAD_IDLE,
|
||||
UPLOAD_ACTIVE,
|
||||
} upload_state;
|
||||
|
||||
|
||||
// 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
|
||||
static const uint32_t crc32_table[16] = {
|
||||
static const uint32_t crc32_table[16] = {
|
||||
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;
|
||||
uint32_t crc = 0xffffffff;
|
||||
for (pos=0 ; pos<size ; pos++){
|
||||
int tbl_idx = crc ^ buf[pos];
|
||||
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
|
||||
tbl_idx = crc ^ (buf[pos] >> 4);
|
||||
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
|
||||
}
|
||||
for (pos = 0; pos < size; pos++)
|
||||
{
|
||||
int tbl_idx = crc ^ buf[pos];
|
||||
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
|
||||
tbl_idx = crc ^ (buf[pos] >> 4);
|
||||
crc = crc32_table[tbl_idx & 0x0f] ^ (crc >> 4);
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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;
|
||||
reverse_bd_addr(addr, &hci_cmd_buffer[3]);
|
||||
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;
|
||||
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
|
||||
int i;
|
||||
int found = 0;
|
||||
for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){
|
||||
if (baudrates[i] == baudrate){
|
||||
for (i = 0; i < sizeof(baudrates) / sizeof(uint32_t); i++)
|
||||
{
|
||||
if (baudrates[i] == baudrate)
|
||||
{
|
||||
found = i;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found){
|
||||
if (!found)
|
||||
{
|
||||
log_error("Baudrate %u not found in table", baudrate);
|
||||
return;
|
||||
}
|
||||
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07));
|
||||
hci_cmd_buffer[2] = 0x01;
|
||||
hci_cmd_buffer[3] = i;
|
||||
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x07));
|
||||
hci_cmd_buffer[2] = 0x01;
|
||||
hci_cmd_buffer[3] = i;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EM9304_PATCH_CONTAINER
|
||||
static void chipset_init(const void * config){
|
||||
static void chipset_init(const void *config)
|
||||
{
|
||||
UNUSED(config);
|
||||
container_blob_offset = 0;
|
||||
em_cpu_reset_sent = 0;
|
||||
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);
|
||||
|
||||
if (container_blob_offset >= container_blob_size) {
|
||||
if (0 == em_cpu_reset_sent){
|
||||
// send EM CPU Reset
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET);
|
||||
hci_cmd_buffer[2] = 0;
|
||||
em_cpu_reset_sent = 1;
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
} else {
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
}
|
||||
if (container_blob_offset >= container_blob_size)
|
||||
{
|
||||
if (0 == em_cpu_reset_sent)
|
||||
{
|
||||
// send EM CPU Reset
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET);
|
||||
hci_cmd_buffer[2] = 0;
|
||||
em_cpu_reset_sent = 1;
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tag;
|
||||
uint16_t bytes_to_upload;
|
||||
uint32_t crc;
|
||||
uint32_t container_size;
|
||||
uint32_t tag;
|
||||
uint16_t bytes_to_upload;
|
||||
uint32_t crc;
|
||||
uint32_t container_size;
|
||||
|
||||
switch (upload_state){
|
||||
case UPLOAD_IDLE:
|
||||
// check for 'em93' tag
|
||||
tag = little_endian_read_32(container_blob_data, container_blob_offset);
|
||||
if (0x656d3933 != tag) {
|
||||
log_error("Expected 0x656d3933 ('em934') but got %08x", (int) tag);
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
// fetch info for current container
|
||||
container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4);
|
||||
container_end = container_blob_offset + container_size;
|
||||
// start uploading (<= 59 bytes)
|
||||
patch_sequence_number = 1;
|
||||
bytes_to_upload = btstack_min(59, container_end - container_blob_offset);
|
||||
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u",
|
||||
(int) container_blob_data[container_blob_offset+9],
|
||||
(int) container_blob_data[container_blob_offset+10],
|
||||
(int) little_endian_read_16(container_blob_data, container_blob_offset+12),
|
||||
(int) little_endian_read_16(container_blob_data, container_blob_offset+14),
|
||||
(int) container_size);
|
||||
// build command
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START);
|
||||
hci_cmd_buffer[2] = 5 + bytes_to_upload;
|
||||
hci_cmd_buffer[3] = 0; // upload to iRAM1
|
||||
little_endian_store_32(hci_cmd_buffer, 4, crc);
|
||||
memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
container_blob_offset += bytes_to_upload;
|
||||
if (container_blob_offset < container_end){
|
||||
upload_state = UPLOAD_ACTIVE;
|
||||
}
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
case UPLOAD_ACTIVE:
|
||||
// Upload next segement
|
||||
bytes_to_upload = btstack_min(58, container_end - container_blob_offset);
|
||||
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
// build command
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE);
|
||||
hci_cmd_buffer[2] = 6 + bytes_to_upload;
|
||||
little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++);
|
||||
little_endian_store_32(hci_cmd_buffer, 5, crc);
|
||||
memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
container_blob_offset += bytes_to_upload;
|
||||
if (container_blob_offset >= container_end){
|
||||
log_info("container done maybe another one");
|
||||
upload_state = UPLOAD_IDLE;
|
||||
}
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
switch (upload_state)
|
||||
{
|
||||
case UPLOAD_IDLE:
|
||||
// check for 'em93' tag
|
||||
tag = little_endian_read_32(container_blob_data, container_blob_offset);
|
||||
if (0x656d3933 != tag)
|
||||
{
|
||||
log_error("Expected 0x656d3933 ('em934') but got %08x", (int)tag);
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
// fetch info for current container
|
||||
container_size = little_endian_read_32(container_blob_data, container_blob_offset + 4);
|
||||
container_end = container_blob_offset + container_size;
|
||||
// start uploading (<= 59 bytes)
|
||||
patch_sequence_number = 1;
|
||||
bytes_to_upload = btstack_min(59, container_end - container_blob_offset);
|
||||
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
log_info("Container type 0x%02x, id %u, build nr %u, user build nr %u, size %u",
|
||||
(int)container_blob_data[container_blob_offset + 9],
|
||||
(int)container_blob_data[container_blob_offset + 10],
|
||||
(int)little_endian_read_16(container_blob_data, container_blob_offset + 12),
|
||||
(int)little_endian_read_16(container_blob_data, container_blob_offset + 14),
|
||||
(int)container_size);
|
||||
// build command
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START);
|
||||
hci_cmd_buffer[2] = 5 + bytes_to_upload;
|
||||
hci_cmd_buffer[3] = 0; // upload to iRAM1
|
||||
little_endian_store_32(hci_cmd_buffer, 4, crc);
|
||||
memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
container_blob_offset += bytes_to_upload;
|
||||
if (container_blob_offset < container_end)
|
||||
{
|
||||
upload_state = UPLOAD_ACTIVE;
|
||||
}
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
case UPLOAD_ACTIVE:
|
||||
// Upload next segement
|
||||
bytes_to_upload = btstack_min(58, container_end - container_blob_offset);
|
||||
crc = btstack_crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
// build command
|
||||
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE);
|
||||
hci_cmd_buffer[2] = 6 + bytes_to_upload;
|
||||
little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++);
|
||||
little_endian_store_32(hci_cmd_buffer, 5, crc);
|
||||
memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload);
|
||||
container_blob_offset += bytes_to_upload;
|
||||
if (container_blob_offset >= container_end)
|
||||
{
|
||||
log_info("container done maybe another one");
|
||||
upload_state = UPLOAD_IDLE;
|
||||
}
|
||||
return BTSTACK_CHIPSET_VALID_COMMAND;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
}
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const btstack_chipset_t btstack_chipset_em9301 = {
|
||||
"EM9301",
|
||||
"EM9301",
|
||||
#ifdef HAVE_EM9304_PATCH_CONTAINER
|
||||
chipset_init,
|
||||
chipset_next_command,
|
||||
chipset_init,
|
||||
chipset_next_command,
|
||||
#else
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
chipset_set_baudrate_command,
|
||||
chipset_set_bd_addr_command,
|
||||
chipset_set_baudrate_command,
|
||||
chipset_set_bd_addr_command,
|
||||
};
|
||||
|
||||
// MARK: public API
|
||||
const btstack_chipset_t * btstack_chipset_em9301_instance(void){
|
||||
return &btstack_chipset_em9301;
|
||||
const btstack_chipset_t *btstack_chipset_em9301_instance(void)
|
||||
{
|
||||
return &btstack_chipset_em9301;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -41,62 +41,65 @@
|
|||
* btstack_chipset_stlc2500d.c
|
||||
*
|
||||
* Adapter to use stlc2500d-based chipsets with BTstack
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "btstack_config.h"
|
||||
#include "btstack_chipset_stlc2500d.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include "hci.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
// should go to some common place
|
||||
#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
|
||||
int preset = 0;
|
||||
switch (baudrate){
|
||||
case 57600:
|
||||
preset = 0x0e;
|
||||
break;
|
||||
case 115200:
|
||||
preset = 0x10;
|
||||
break;
|
||||
case 230400:
|
||||
preset = 0x12;
|
||||
break;
|
||||
case 460800:
|
||||
preset = 0x13;
|
||||
break;
|
||||
case 921600:
|
||||
preset = 0x14;
|
||||
break;
|
||||
case 1843200:
|
||||
preset = 0x16;
|
||||
break;
|
||||
case 2000000:
|
||||
preset = 0x19;
|
||||
break;
|
||||
case 3000000:
|
||||
preset = 0x1b;
|
||||
break;
|
||||
case 4000000:
|
||||
preset = 0x1f;
|
||||
break;
|
||||
default:
|
||||
log_error("stlc2500d_baudrate_cmd baudrate %u not supported", baudrate);
|
||||
return;
|
||||
switch (baudrate)
|
||||
{
|
||||
case 57600:
|
||||
preset = 0x0e;
|
||||
break;
|
||||
case 115200:
|
||||
preset = 0x10;
|
||||
break;
|
||||
case 230400:
|
||||
preset = 0x12;
|
||||
break;
|
||||
case 460800:
|
||||
preset = 0x13;
|
||||
break;
|
||||
case 460800:
|
||||
preset = 0x14;
|
||||
break;
|
||||
case 1843200:
|
||||
preset = 0x16;
|
||||
break;
|
||||
case 2000000:
|
||||
preset = 0x19;
|
||||
break;
|
||||
case 3000000:
|
||||
preset = 0x1b;
|
||||
break;
|
||||
case 4000000:
|
||||
preset = 0x1f;
|
||||
break;
|
||||
default:
|
||||
log_error("stlc2500d_baudrate_cmd baudrate %u not supported", baudrate);
|
||||
return;
|
||||
}
|
||||
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0xfc));
|
||||
hci_cmd_buffer[2] = 0x01;
|
||||
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));
|
||||
hci_cmd_buffer[2] = 0x08;
|
||||
hci_cmd_buffer[3] = 254;
|
||||
|
@ -113,6 +116,7 @@ static const btstack_chipset_t btstack_chipset_stlc2500d = {
|
|||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -41,7 +41,7 @@
|
|||
* btstack_chipset_tc3566x.c
|
||||
*
|
||||
* Adapter to use Toshiba TC3566x-based chipsets with BTstack
|
||||
*
|
||||
*
|
||||
* Supports:
|
||||
* - Set BD ADDR
|
||||
* - Set baud rate
|
||||
|
@ -50,40 +50,42 @@
|
|||
#include "btstack_config.h"
|
||||
#include "btstack_chipset_tc3566x.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include "hci.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
// should go to some common place
|
||||
#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;
|
||||
uint8_t div2 = 0;
|
||||
switch (baudrate) {
|
||||
case 115200:
|
||||
div1 = 0x001A;
|
||||
div2 = 0x60;
|
||||
break;
|
||||
case 230400:
|
||||
div1 = 0x000D;
|
||||
div2 = 0x60;
|
||||
break;
|
||||
case 460800:
|
||||
div1 = 0x0005;
|
||||
div2 = 0xA0;
|
||||
break;
|
||||
case 921600:
|
||||
div1 = 0x0003;
|
||||
div2 = 0x70;
|
||||
break;
|
||||
default:
|
||||
log_error("tc3566x_baudrate_cmd baudrate %u not supported", baudrate);
|
||||
return;
|
||||
uint8_t div2 = 0;
|
||||
switch (baudrate)
|
||||
{
|
||||
case 115200:
|
||||
div1 = 0x001A;
|
||||
div2 = 0x60;
|
||||
break;
|
||||
case 230400:
|
||||
div1 = 0x000D;
|
||||
div2 = 0x60;
|
||||
break;
|
||||
case 460800:
|
||||
div1 = 0x0005;
|
||||
div2 = 0xA0;
|
||||
break;
|
||||
case 460800:
|
||||
div1 = 0x0003;
|
||||
div2 = 0x70;
|
||||
break;
|
||||
default:
|
||||
log_error("tc3566x_baudrate_cmd baudrate %u not supported", baudrate);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
hci_cmd_buffer[0] = 0x13;
|
||||
hci_cmd_buffer[1] = 0x10;
|
||||
|
@ -108,6 +111,7 @@ static const btstack_chipset_t btstack_chipset_tc3566x = {
|
|||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -44,15 +44,13 @@
|
|||
// *****************************************************************************
|
||||
/* EXAMPLE_START(hsp_ag_demo): HSP AG - Audio Gateway
|
||||
*
|
||||
* @text This example implements a HSP Audio Gateway device that sends and receives
|
||||
* audio signal over HCI SCO. It demonstrates how to receive
|
||||
* an output from a remote headset (HS), and,
|
||||
* if HAVE_BTSTACK_STDIN is defined, how to control the HS.
|
||||
* @text This example implements a HSP Audio Gateway device that sends and receives
|
||||
* audio signal over HCI SCO. It demonstrates how to receive
|
||||
* an output from a remote headset (HS), and,
|
||||
* if HAVE_BTSTACK_STDIN is defined, how to control the HS.
|
||||
*/
|
||||
// *****************************************************************************
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -64,49 +62,48 @@
|
|||
#include "btstack_stdin.h"
|
||||
#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 char hsp_ag_service_name[] = "Audio Gateway Test";
|
||||
static uint16_t sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
static const char hsp_ag_service_name[] = "Audio Gateway Test";
|
||||
static uint16_t sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
|
||||
static char hs_cmd_buffer[100];
|
||||
|
||||
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_name = "HSP AG Demo 00:00:00:00:00:00";
|
||||
static const char *device_addr_string = "00:1b:dc:07:32:ef";
|
||||
static bd_addr_t device_addr;
|
||||
|
||||
/* @section Audio Transfer Setup
|
||||
/* @section Audio Transfer Setup
|
||||
*
|
||||
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
|
||||
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
|
||||
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
|
||||
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
|
||||
*
|
||||
* Tested working setups:
|
||||
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud
|
||||
* Tested working setups:
|
||||
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 460800 baud
|
||||
* - Ubuntu 14 64-bit, CSR USB dongle
|
||||
* - OS X 10.11, CSR USB dongle
|
||||
*
|
||||
* 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
|
||||
* - looks like bug in select->FTDI driver as it works correct on Linux
|
||||
*
|
||||
* SCO not routed over HCI yet:
|
||||
* - CSR UART dongle
|
||||
* - CSR UART dongle
|
||||
* - Broadcom USB dongle
|
||||
* - Broadcom UART chipset
|
||||
* - ..
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_BTSTACK_STDIN
|
||||
static void show_usage(void){
|
||||
static void show_usage(void)
|
||||
{
|
||||
bd_addr_t iut_address;
|
||||
gap_local_bd_addr(iut_address);
|
||||
|
||||
printf("\n--- Bluetooth HSP Audio Gateway Test Console %s ---\n", bd_addr_to_str(iut_address));
|
||||
|
||||
|
||||
printf("---\n");
|
||||
printf("c - Connect to %s\n", device_addr_string);
|
||||
printf("C - Disconnect\n");
|
||||
|
@ -123,175 +120,195 @@ static void show_usage(void){
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void stdin_process(char c){
|
||||
switch (c){
|
||||
case 'a':
|
||||
printf("Establish audio connection\n");
|
||||
hsp_ag_establish_audio_connection();
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release audio connection\n");
|
||||
hsp_ag_release_audio_connection();
|
||||
break;
|
||||
case 'c':
|
||||
printf("Connect to %s\n", device_addr_string);
|
||||
hsp_ag_connect(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect.\n");
|
||||
hsp_ag_disconnect();
|
||||
break;
|
||||
case 'D':
|
||||
printf("Deleting all link keys\n");
|
||||
gap_delete_all_link_keys();
|
||||
break;
|
||||
case 'm':
|
||||
printf("Setting microphone gain 8\n");
|
||||
hsp_ag_set_microphone_gain(8);
|
||||
break;
|
||||
case 'M':
|
||||
printf("Setting microphone gain 15\n");
|
||||
hsp_ag_set_microphone_gain(15);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Setting speaker gain 0\n");
|
||||
hsp_ag_set_speaker_gain(0);
|
||||
break;
|
||||
case 's':
|
||||
printf("Setting speaker gain 8\n");
|
||||
hsp_ag_set_speaker_gain(8);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Setting speaker gain 15\n");
|
||||
hsp_ag_set_speaker_gain(15);
|
||||
break;
|
||||
case 'r':
|
||||
printf("Start ringing\n");
|
||||
hsp_ag_start_ringing();
|
||||
break;
|
||||
case 't':
|
||||
printf("Stop ringing\n");
|
||||
hsp_ag_stop_ringing();
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
static void stdin_process(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
printf("Establish audio connection\n");
|
||||
hsp_ag_establish_audio_connection();
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release audio connection\n");
|
||||
hsp_ag_release_audio_connection();
|
||||
break;
|
||||
case 'c':
|
||||
printf("Connect to %s\n", device_addr_string);
|
||||
hsp_ag_connect(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect.\n");
|
||||
hsp_ag_disconnect();
|
||||
break;
|
||||
case 'D':
|
||||
printf("Deleting all link keys\n");
|
||||
gap_delete_all_link_keys();
|
||||
break;
|
||||
case 'm':
|
||||
printf("Setting microphone gain 8\n");
|
||||
hsp_ag_set_microphone_gain(8);
|
||||
break;
|
||||
case 'M':
|
||||
printf("Setting microphone gain 15\n");
|
||||
hsp_ag_set_microphone_gain(15);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Setting speaker gain 0\n");
|
||||
hsp_ag_set_speaker_gain(0);
|
||||
break;
|
||||
case 's':
|
||||
printf("Setting speaker gain 8\n");
|
||||
hsp_ag_set_speaker_gain(8);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Setting speaker gain 15\n");
|
||||
hsp_ag_set_speaker_gain(15);
|
||||
break;
|
||||
case 'r':
|
||||
printf("Start ringing\n");
|
||||
hsp_ag_start_ringing();
|
||||
break;
|
||||
case 't':
|
||||
printf("Stop ringing\n");
|
||||
hsp_ag_stop_ringing();
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
uint8_t status;
|
||||
|
||||
switch (packet_type){
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle) break;
|
||||
sco_demo_receive(event, event_size);
|
||||
switch (packet_type)
|
||||
{
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle)
|
||||
break;
|
||||
sco_demo_receive(event, event_size);
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(event)) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(event))
|
||||
{
|
||||
#ifndef HAVE_BTSTACK_STDIN
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(event) != HCI_STATE_WORKING) break;
|
||||
printf("Establish HSP AG service to %s...\n", device_addr_string);
|
||||
hsp_ag_connect(device_addr);
|
||||
break;
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(event) != HCI_STATE_WORKING)
|
||||
break;
|
||||
printf("Establish HSP AG service to %s...\n", device_addr_string);
|
||||
hsp_ag_connect(device_addr);
|
||||
break;
|
||||
#endif
|
||||
case HCI_EVENT_SCO_CAN_SEND_NOW:
|
||||
sco_demo_send(sco_handle);
|
||||
case HCI_EVENT_SCO_CAN_SEND_NOW:
|
||||
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;
|
||||
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;
|
||||
}
|
||||
printf("RFCOMM connection established.\n");
|
||||
}
|
||||
printf("RFCOMM connection established.\n");
|
||||
#ifndef HAVE_BTSTACK_STDIN
|
||||
printf("Establish Audio connection to %s...\n", device_addr_string);
|
||||
hsp_ag_establish_audio_connection();
|
||||
printf("Establish Audio connection to %s...\n", device_addr_string);
|
||||
hsp_ag_establish_audio_connection();
|
||||
#endif
|
||||
break;
|
||||
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
|
||||
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
printf("RFCOMM disconnection failed with status %u.\n", status);
|
||||
} else {
|
||||
printf("RFCOMM disconnected.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
|
||||
status = hsp_subevent_audio_connection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
printf("Audio connection establishment failed with status %u\n", status);
|
||||
} else {
|
||||
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
|
||||
printf("Audio connection released.\n\n");
|
||||
sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
break;
|
||||
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
|
||||
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
|
||||
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_HS_COMMAND:{
|
||||
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
|
||||
unsigned int cmd_length = hsp_subevent_hs_command_get_value_length(event);
|
||||
unsigned int size = cmd_length <= sizeof(hs_cmd_buffer)? cmd_length : sizeof(hs_cmd_buffer);
|
||||
memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1);
|
||||
printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer);
|
||||
break;
|
||||
}
|
||||
case HSP_SUBEVENT_BUTTON_PRESSED:
|
||||
if (sco_handle == HCI_CON_HANDLE_INVALID){
|
||||
printf("Button event -> establish audio\n");
|
||||
hsp_ag_establish_audio_connection();
|
||||
} else {
|
||||
printf("Button event -> release audio\n");
|
||||
hsp_ag_release_audio_connection();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("event not handled %u\n", event[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
|
||||
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS)
|
||||
{
|
||||
printf("RFCOMM disconnection failed with status %u.\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("RFCOMM disconnected.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
|
||||
status = hsp_subevent_audio_connection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS)
|
||||
{
|
||||
printf("Audio connection establishment failed with status %u\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
|
||||
printf("Audio connection released.\n\n");
|
||||
sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
break;
|
||||
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
|
||||
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
|
||||
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_HS_COMMAND:
|
||||
{
|
||||
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
|
||||
unsigned int cmd_length = hsp_subevent_hs_command_get_value_length(event);
|
||||
unsigned int size = cmd_length <= sizeof(hs_cmd_buffer) ? cmd_length : sizeof(hs_cmd_buffer);
|
||||
memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1);
|
||||
printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer);
|
||||
break;
|
||||
}
|
||||
case HSP_SUBEVENT_BUTTON_PRESSED:
|
||||
if (sco_handle == HCI_CON_HANDLE_INVALID)
|
||||
{
|
||||
printf("Button event -> establish audio\n");
|
||||
hsp_ag_establish_audio_connection();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Button event -> release audio\n");
|
||||
hsp_ag_release_audio_connection();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("event not handled %u\n", event[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* @section Main Application Setup
|
||||
*
|
||||
* @text Listing MainConfiguration shows main application code.
|
||||
* To run a HSP Audio Gateway service you need to initialize the SDP, and to create and register HSP AG record with it.
|
||||
* @text Listing MainConfiguration shows main application code.
|
||||
* To run a HSP Audio Gateway service you need to initialize the SDP, and to create and register HSP AG record with it.
|
||||
* In this example, the SCO over HCI is used to receive and send an audio signal.
|
||||
*
|
||||
*
|
||||
* Two packet handlers are registered:
|
||||
* - The HCI SCO packet handler receives audio data.
|
||||
* - The HSP AG packet handler is used to trigger sending of audio data and commands to the HS. It also receives the AG's answers.
|
||||
*
|
||||
* The stdin_process callback allows for sending commands to the AG.
|
||||
*
|
||||
* The stdin_process callback allows for sending commands to the AG.
|
||||
* At the end the Bluetooth stack is started.
|
||||
*/
|
||||
|
||||
/* 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)argv;
|
||||
|
||||
|
@ -306,7 +323,7 @@ int btstack_main(int argc, const char * argv[]){
|
|||
hsp_ag_create_sdp_record(hsp_service_buffer, 0x10001, rfcomm_channel_nr, hsp_ag_service_name);
|
||||
printf("SDP service record size: %u\n", de_get_len(hsp_service_buffer));
|
||||
sdp_register_service(hsp_service_buffer);
|
||||
|
||||
|
||||
rfcomm_init();
|
||||
|
||||
hsp_ag_init(rfcomm_channel_nr);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -44,10 +44,10 @@
|
|||
// *****************************************************************************
|
||||
/* EXAMPLE_START(hsp_hs_demo): HSP HS - Headset
|
||||
*
|
||||
* @text This example implements a HSP Headset device that sends and receives
|
||||
* audio signal over HCI SCO. It demonstrates how to receive
|
||||
* an output from a remote audio gateway (AG), and,
|
||||
* if HAVE_BTSTACK_STDIN is defined, how to control the AG.
|
||||
* @text This example implements a HSP Headset device that sends and receives
|
||||
* audio signal over HCI SCO. It demonstrates how to receive
|
||||
* an output from a remote audio gateway (AG), and,
|
||||
* if HAVE_BTSTACK_STDIN is defined, how to control the AG.
|
||||
*/
|
||||
// *****************************************************************************
|
||||
|
||||
|
@ -66,41 +66,41 @@
|
|||
|
||||
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 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 char hs_cmd_buffer[100];
|
||||
// mac 2013:
|
||||
static const char * device_addr_string = "84:38:35:65:d1:15";
|
||||
// mac 2013:
|
||||
static const char *device_addr_string = "84:38:35:65:d1:15";
|
||||
static bd_addr_t device_addr;
|
||||
|
||||
/* @section Audio Transfer Setup
|
||||
/* @section Audio Transfer Setup
|
||||
*
|
||||
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
|
||||
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
|
||||
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
|
||||
* To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined.
|
||||
*
|
||||
* Tested working setups:
|
||||
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud
|
||||
* Tested working setups:
|
||||
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 460800 baud
|
||||
* - Ubuntu 14 64-bit, CSR USB dongle
|
||||
* - OS X 10.11, CSR USB dongle
|
||||
*
|
||||
* 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
|
||||
* - looks like bug in select->FTDI driver as it works correct on Linux
|
||||
*
|
||||
* SCO not routed over HCI yet:
|
||||
* - CSR UART dongle
|
||||
* - CSR UART dongle
|
||||
* - Broadcom USB dongle
|
||||
* - Broadcom UART chipset
|
||||
* - ..
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
static void show_usage(void){
|
||||
static void show_usage(void)
|
||||
{
|
||||
bd_addr_t iut_address;
|
||||
gap_local_bd_addr(iut_address);
|
||||
|
||||
|
@ -121,159 +121,179 @@ static void show_usage(void){
|
|||
}
|
||||
|
||||
#ifdef HAVE_BTSTACK_STDIN
|
||||
static void stdin_process(char c){
|
||||
switch (c){
|
||||
case 'c':
|
||||
printf("Connect to %s\n", bd_addr_to_str(device_addr));
|
||||
hsp_hs_connect(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect.\n");
|
||||
hsp_hs_disconnect();
|
||||
break;
|
||||
case 'a':
|
||||
printf("Establish audio connection\n");
|
||||
hsp_hs_establish_audio_connection();
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release audio connection\n");
|
||||
hsp_hs_release_audio_connection();
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
printf("Setting microphone gain 0\n");
|
||||
hsp_hs_set_microphone_gain(0);
|
||||
break;
|
||||
case 'm':
|
||||
printf("Setting microphone gain 8\n");
|
||||
hsp_hs_set_microphone_gain(8);
|
||||
break;
|
||||
case 'M':
|
||||
printf("Setting microphone gain 15\n");
|
||||
hsp_hs_set_microphone_gain(15);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Setting speaker gain 0\n");
|
||||
hsp_hs_set_speaker_gain(0);
|
||||
break;
|
||||
case 's':
|
||||
printf("Setting speaker gain 8\n");
|
||||
hsp_hs_set_speaker_gain(8);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Setting speaker gain 15\n");
|
||||
hsp_hs_set_speaker_gain(15);
|
||||
break;
|
||||
case 'b':
|
||||
printf("Press user button\n");
|
||||
hsp_hs_send_button_press();
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
static void stdin_process(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'c':
|
||||
printf("Connect to %s\n", bd_addr_to_str(device_addr));
|
||||
hsp_hs_connect(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect.\n");
|
||||
hsp_hs_disconnect();
|
||||
break;
|
||||
case 'a':
|
||||
printf("Establish audio connection\n");
|
||||
hsp_hs_establish_audio_connection();
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release audio connection\n");
|
||||
hsp_hs_release_audio_connection();
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
printf("Setting microphone gain 0\n");
|
||||
hsp_hs_set_microphone_gain(0);
|
||||
break;
|
||||
case 'm':
|
||||
printf("Setting microphone gain 8\n");
|
||||
hsp_hs_set_microphone_gain(8);
|
||||
break;
|
||||
case 'M':
|
||||
printf("Setting microphone gain 15\n");
|
||||
hsp_hs_set_microphone_gain(15);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Setting speaker gain 0\n");
|
||||
hsp_hs_set_speaker_gain(0);
|
||||
break;
|
||||
case 's':
|
||||
printf("Setting speaker gain 8\n");
|
||||
hsp_hs_set_speaker_gain(8);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Setting speaker gain 15\n");
|
||||
hsp_hs_set_speaker_gain(15);
|
||||
break;
|
||||
case 'b':
|
||||
printf("Press user button\n");
|
||||
hsp_hs_send_button_press();
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
uint8_t status;
|
||||
|
||||
switch (packet_type){
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
sco_demo_receive(event, event_size);
|
||||
switch (packet_type)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
case HCI_EVENT_SCO_CAN_SEND_NOW:
|
||||
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle) break;
|
||||
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);
|
||||
} else {
|
||||
printf("RFCOMM connection established.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
|
||||
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
printf("RFCOMM disconnection failed with status %u.\n", status);
|
||||
} else {
|
||||
printf("RFCOMM disconnected.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
|
||||
status = hsp_subevent_audio_connection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS){
|
||||
printf("Audio connection establishment failed with status %u\n", status);
|
||||
} else {
|
||||
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
|
||||
printf("Audio connection released.\n\n");
|
||||
sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
break;
|
||||
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
|
||||
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
|
||||
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_RING:
|
||||
printf("HS: RING RING!\n");
|
||||
break;
|
||||
case HSP_SUBEVENT_AG_INDICATION: {
|
||||
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
|
||||
unsigned int size = hsp_subevent_ag_indication_get_value_length(event);
|
||||
if (size >= sizeof(hs_cmd_buffer)-1){
|
||||
size = sizeof(hs_cmd_buffer)-1;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("event not handled %u\n", hci_event_hsp_meta_get_subevent_code(event));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case HCI_EVENT_SCO_CAN_SEND_NOW:
|
||||
if (READ_SCO_CONNECTION_HANDLE(event) != sco_handle)
|
||||
break;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("RFCOMM connection established.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
|
||||
status = hsp_subevent_rfcomm_disconnection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS)
|
||||
{
|
||||
printf("RFCOMM disconnection failed with status %u.\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("RFCOMM disconnected.\n");
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
|
||||
status = hsp_subevent_audio_connection_complete_get_status(event);
|
||||
if (status != ERROR_CODE_SUCCESS)
|
||||
{
|
||||
printf("Audio connection establishment failed with status %u\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
sco_handle = hsp_subevent_audio_connection_complete_get_handle(event);
|
||||
printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
|
||||
hci_request_sco_can_send_now_event();
|
||||
}
|
||||
break;
|
||||
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
|
||||
printf("Audio connection released.\n\n");
|
||||
sco_handle = HCI_CON_HANDLE_INVALID;
|
||||
break;
|
||||
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
|
||||
printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
|
||||
printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
|
||||
break;
|
||||
case HSP_SUBEVENT_RING:
|
||||
printf("HS: RING RING!\n");
|
||||
break;
|
||||
case HSP_SUBEVENT_AG_INDICATION:
|
||||
{
|
||||
memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
|
||||
unsigned int size = hsp_subevent_ag_indication_get_value_length(event);
|
||||
if (size >= sizeof(hs_cmd_buffer) - 1)
|
||||
{
|
||||
size = sizeof(hs_cmd_buffer) - 1;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("event not handled %u\n", hci_event_hsp_meta_get_subevent_code(event));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* @section Main Application Setup
|
||||
*
|
||||
* @text Listing MainConfiguration shows main application code.
|
||||
* To run a HSP Headset service you need to initialize the SDP, and to create and register HSP HS record with it.
|
||||
* @text Listing MainConfiguration shows main application code.
|
||||
* To run a HSP Headset service you need to initialize the SDP, and to create and register HSP HS record with it.
|
||||
* In this example, the SCO over HCI is used to receive and send an audio signal.
|
||||
*
|
||||
*
|
||||
* Two packet handlers are registered:
|
||||
* - The HCI SCO packet handler receives audio data.
|
||||
* - The HSP HS packet handler is used to trigger sending of audio data and commands to the AG. It also receives the AG's answers.
|
||||
*
|
||||
* The stdin_process callback allows for sending commands to the AG.
|
||||
*
|
||||
* The stdin_process callback allows for sending commands to the AG.
|
||||
* At the end the Bluetooth stack is started.
|
||||
*/
|
||||
|
||||
/* 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)argv;
|
||||
|
||||
|
@ -310,7 +330,7 @@ int btstack_main(int argc, const char * argv[]){
|
|||
|
||||
// Parse human readable Bluetooth address.
|
||||
sscanf_bd_addr(device_addr_string, device_addr);
|
||||
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
return 0;
|
||||
|
|
|
@ -56,9 +56,9 @@
|
|||
#include "btstack_debug.h"
|
||||
#include "btstack_util.h"
|
||||
#include <stdint.h>
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef __APPLE__
|
||||
|
@ -70,32 +70,35 @@
|
|||
#define BRIDGE_RX_BLOCKS_DROP 10
|
||||
|
||||
// data source for integration with BTstack Runloop
|
||||
static btstack_data_source_t sco_data_source;
|
||||
static sco_format_t sco_format;
|
||||
static hci_con_handle_t sco_handle;
|
||||
static btstack_data_source_t sco_data_source;
|
||||
static sco_format_t sco_format;
|
||||
static hci_con_handle_t sco_handle;
|
||||
|
||||
// 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_counter;
|
||||
|
||||
// TX
|
||||
static uint8_t sco_tx_packet[BRIDGE_BLOCK_SIZE_BYTES];
|
||||
static uint16_t sco_tx_packet_pos;
|
||||
static uint16_t sco_tx_counter;
|
||||
static uint8_t sco_tx_packet[BRIDGE_BLOCK_SIZE_BYTES];
|
||||
static uint16_t sco_tx_packet_pos;
|
||||
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_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_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");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
btstack_assert( (packet[2]+3) == length);
|
||||
btstack_assert((packet[2] + 3) == length);
|
||||
uint16_t i;
|
||||
switch (sco_format){
|
||||
case SCO_FORMAT_8_BIT:
|
||||
btstack_assert(length == 63);
|
||||
for (i=0;i<60;i++){
|
||||
big_endian_store_16(sco_tx_packet, i * 2, packet[ 3 + i ]);
|
||||
}
|
||||
break;
|
||||
case SCO_FORMAT_16_BIT:
|
||||
btstack_assert(length == 123);
|
||||
for (i=0;i<60;i++){
|
||||
sco_tx_packet[ i * 2 ] = packet[4 + i * 2];
|
||||
sco_tx_packet[ i * 2 + 1] = packet[3 + i * 2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
switch (sco_format)
|
||||
{
|
||||
case SCO_FORMAT_8_BIT:
|
||||
btstack_assert(length == 63);
|
||||
for (i = 0; i < 60; i++)
|
||||
{
|
||||
big_endian_store_16(sco_tx_packet, i * 2, packet[3 + i]);
|
||||
}
|
||||
break;
|
||||
case SCO_FORMAT_16_BIT:
|
||||
btstack_assert(length == 123);
|
||||
for (i = 0; i < 60; i++)
|
||||
{
|
||||
sco_tx_packet[i * 2] = packet[4 + i * 2];
|
||||
sco_tx_packet[i * 2 + 1] = packet[3 + i * 2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
if (bytes_read == 0){
|
||||
log_error("read zero bytes of %d bytes", (int) bytes_to_read);
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
log_error("read zero bytes of %d bytes", (int)bytes_to_read);
|
||||
return;
|
||||
}
|
||||
if (bytes_read < 0) {
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
log_error("read returned error");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -153,13 +164,15 @@ static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds) {
|
|||
sco_rx_bytes_read = 0;
|
||||
|
||||
// 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");
|
||||
return;
|
||||
}
|
||||
|
||||
// drop first packets
|
||||
if (sco_rx_counter < BRIDGE_RX_BLOCKS_DROP) {
|
||||
if (sco_rx_counter < BRIDGE_RX_BLOCKS_DROP)
|
||||
{
|
||||
sco_rx_counter++;
|
||||
log_info("drop packet %u/%u\n", sco_rx_counter, BRIDGE_RX_BLOCKS_DROP);
|
||||
return;
|
||||
|
@ -167,46 +180,53 @@ static void posix_i2s_test_bridge_process_read(btstack_data_source_t *ds) {
|
|||
|
||||
// setup SCO header
|
||||
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;
|
||||
switch (sco_format) {
|
||||
case SCO_FORMAT_8_BIT:
|
||||
// data is received big endian and transparent data is in lower byte
|
||||
packet[2] = BRIDGE_BLOCK_SIZE_BYTES / 2;
|
||||
for (index= 0 ; index < (BRIDGE_BLOCK_SIZE_BYTES / 2) ; index++) {
|
||||
packet[3+index] = sco_rx_buffer[2 * index + 1];
|
||||
}
|
||||
break;
|
||||
case SCO_FORMAT_16_BIT:
|
||||
// data is received big endian but sco packet contains little endian data -> swap bytes
|
||||
packet[2] = BRIDGE_BLOCK_SIZE_BYTES;
|
||||
for (index = 0 ; index < (BRIDGE_BLOCK_SIZE_BYTES / 2) ; index++) {
|
||||
packet[3 + 2 * index] = sco_rx_buffer[2 * index + 1];
|
||||
packet[4 + 2 * index] = sco_rx_buffer[2 * index];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
switch (sco_format)
|
||||
{
|
||||
case SCO_FORMAT_8_BIT:
|
||||
// data is received big endian and transparent data is in lower byte
|
||||
packet[2] = BRIDGE_BLOCK_SIZE_BYTES / 2;
|
||||
for (index = 0; index < (BRIDGE_BLOCK_SIZE_BYTES / 2); index++)
|
||||
{
|
||||
packet[3 + index] = sco_rx_buffer[2 * index + 1];
|
||||
}
|
||||
break;
|
||||
case SCO_FORMAT_16_BIT:
|
||||
// data is received big endian but sco packet contains little endian data -> swap bytes
|
||||
packet[2] = BRIDGE_BLOCK_SIZE_BYTES;
|
||||
for (index = 0; index < (BRIDGE_BLOCK_SIZE_BYTES / 2); index++)
|
||||
{
|
||||
packet[3 + 2 * index] = sco_rx_buffer[2 * index + 1];
|
||||
packet[4 + 2 * index] = sco_rx_buffer[2 * index];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
btstack_assert(false);
|
||||
break;
|
||||
}
|
||||
(*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) {
|
||||
if (ds->source.fd < 0) return;
|
||||
switch (callback_type){
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
posix_i2s_test_bridge_process_read(ds);
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
posix_i2s_test_bridge_process_write(ds);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
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)
|
||||
{
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
posix_i2s_test_bridge_process_read(ds);
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
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__
|
||||
|
||||
|
@ -218,7 +238,8 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
|
|||
// and output speed.
|
||||
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
@ -226,65 +247,104 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
|
|||
#else
|
||||
struct termios toptions;
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("set baud: Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
speed_t brate = baudrate; // let you override switch below if needed
|
||||
switch(baudrate) {
|
||||
case 9600: brate=B9600; break;
|
||||
case 19200: brate=B19200; break;
|
||||
case 38400: brate=B38400; break;
|
||||
case 57600: brate=B57600; break;
|
||||
case 115200: brate=B115200; break;
|
||||
switch (baudrate)
|
||||
{
|
||||
case 9600:
|
||||
brate = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
brate = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
brate = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
brate = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
brate = B115200;
|
||||
break;
|
||||
#ifdef B230400
|
||||
case 230400: brate=B230400; break;
|
||||
case 230400:
|
||||
brate = B230400;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B460800
|
||||
case 460800: brate=B460800; break;
|
||||
case 460800:
|
||||
brate = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B500000
|
||||
case 500000: brate=B500000; break;
|
||||
case 500000:
|
||||
brate = B500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B576000
|
||||
case 576000: brate=B576000; break;
|
||||
case 576000:
|
||||
brate = B576000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600: brate=B921600; break;
|
||||
#ifdef B460800
|
||||
case 460800:
|
||||
brate = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
case 1000000: brate=B1000000; break;
|
||||
case 1000000:
|
||||
brate = B1000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
case 1152000: brate=B1152000; break;
|
||||
case 1152000:
|
||||
brate = B1152000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
case 1500000: brate=B1500000; break;
|
||||
case 1500000:
|
||||
brate = B1500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
case 2000000: brate=B2000000; break;
|
||||
case 2000000:
|
||||
brate = B2000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
case 2500000: brate=B2500000; break;
|
||||
case 2500000:
|
||||
brate = B2500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
case 3000000: brate=B3000000; break;
|
||||
case 3000000:
|
||||
brate = B3000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
case 3500000: brate=B3500000; break;
|
||||
case 3500000:
|
||||
brate = B3500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B400000
|
||||
case 4000000: brate=B4000000; break;
|
||||
case 4000000:
|
||||
brate = B4000000;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
log_error("can't set baudrate %dn", baudrate );
|
||||
return -1;
|
||||
default:
|
||||
log_error("can't set baudrate %dn", baudrate);
|
||||
return -1;
|
||||
}
|
||||
cfsetospeed(&toptions, brate);
|
||||
cfsetispeed(&toptions, brate);
|
||||
|
||||
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
||||
if (tcsetattr(fd, TCSANOW, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't set term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
@ -293,43 +353,48 @@ static int posix_i2s_test_bridge_set_baudrate(int fd, uint32_t baudrate){
|
|||
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;
|
||||
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
|
||||
int fd = open(device_path, flags);
|
||||
if (fd == -1) {
|
||||
if (fd == -1)
|
||||
{
|
||||
log_error("Unable to open port %s", device_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfmakeraw(&toptions); // make raw
|
||||
cfmakeraw(&toptions); // make raw
|
||||
|
||||
// 8N1
|
||||
toptions.c_cflag &= ~CSTOPB;
|
||||
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
|
||||
|
||||
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VTIME] = 0;
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
||||
if (tcsetattr(fd, TCSANOW, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't set term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -350,7 +415,8 @@ static int posix_i2s_test_bridge_init(const char * device_path){
|
|||
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");
|
||||
// store config
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.open = posix_i2s_test_bridge_open,
|
||||
.close = posix_i2s_test_bridge_close,
|
||||
.open = posix_i2s_test_bridge_open,
|
||||
.close = posix_i2s_test_bridge_close,
|
||||
.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);
|
||||
if (err > 0) {
|
||||
if (err > 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
sco_format = SCO_FORMAT_8_BIT;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -48,9 +48,9 @@
|
|||
#include "btstack_run_loop.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef __APPLE__
|
||||
|
@ -59,57 +59,63 @@
|
|||
#endif
|
||||
|
||||
// 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
|
||||
static btstack_data_source_t transport_data_source;
|
||||
|
||||
// block write
|
||||
static int btstack_uart_block_write_bytes_len;
|
||||
static const uint8_t * btstack_uart_block_write_bytes_data;
|
||||
static int btstack_uart_block_write_bytes_len;
|
||||
static const uint8_t *btstack_uart_block_write_bytes_data;
|
||||
|
||||
// block read
|
||||
static uint16_t btstack_uart_block_read_bytes_len;
|
||||
static uint8_t * btstack_uart_block_read_bytes_data;
|
||||
static uint16_t btstack_uart_block_read_bytes_len;
|
||||
static uint8_t *btstack_uart_block_read_bytes_data;
|
||||
|
||||
// callbacks
|
||||
static void (*block_sent)(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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (btstack_uart_block_write_bytes_len == 0) return;
|
||||
static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds)
|
||||
{
|
||||
|
||||
if (btstack_uart_block_write_bytes_len == 0)
|
||||
return;
|
||||
|
||||
uint32_t start = btstack_run_loop_get_time_ms();
|
||||
|
||||
// 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();
|
||||
if (end - start > 10){
|
||||
if (end - start > 10)
|
||||
{
|
||||
// log_info("write took %u ms", end - start);
|
||||
}
|
||||
if (bytes_written == 0){
|
||||
if (bytes_written == 0)
|
||||
{
|
||||
// log_error("wrote zero bytes\n");
|
||||
return;
|
||||
}
|
||||
if (bytes_written < 0) {
|
||||
if (bytes_written < 0)
|
||||
{
|
||||
// log_error("write returned error\n");
|
||||
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -117,48 +123,57 @@ 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);
|
||||
|
||||
// notify done
|
||||
if (block_sent){
|
||||
if (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");
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
}
|
||||
|
||||
uint32_t start = btstack_run_loop_get_time_ms();
|
||||
|
||||
|
||||
// read up to bytes_to_read data in
|
||||
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);
|
||||
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);
|
||||
}
|
||||
if (bytes_read == 0){
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
// log_error("read zero bytes\n");
|
||||
return;
|
||||
}
|
||||
if (bytes_read < 0) {
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
// log_error("read returned error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
btstack_uart_block_read_bytes_len -= bytes_read;
|
||||
btstack_uart_block_read_bytes_data += bytes_read;
|
||||
if (btstack_uart_block_read_bytes_len > 0) return;
|
||||
|
||||
btstack_uart_block_read_bytes_len -= bytes_read;
|
||||
btstack_uart_block_read_bytes_data += bytes_read;
|
||||
if (btstack_uart_block_read_bytes_len > 0)
|
||||
return;
|
||||
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
|
||||
if (block_received){
|
||||
if (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;
|
||||
|
||||
|
@ -166,62 +181,100 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
|||
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
speed_t brate = baudrate; // let you override switch below if needed
|
||||
switch(baudrate) {
|
||||
case 9600: brate=B9600; break;
|
||||
case 19200: brate=B19200; break;
|
||||
case 38400: brate=B38400; break;
|
||||
case 57600: brate=B57600; break;
|
||||
case 115200: brate=B115200; break;
|
||||
switch (baudrate)
|
||||
{
|
||||
case 9600:
|
||||
brate = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
brate = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
brate = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
brate = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
brate = B115200;
|
||||
break;
|
||||
#ifdef B230400
|
||||
case 230400: brate=B230400; break;
|
||||
case 230400:
|
||||
brate = B230400;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B460800
|
||||
case 460800: brate=B460800; break;
|
||||
case 460800:
|
||||
brate = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B500000
|
||||
case 500000: brate=B500000; break;
|
||||
case 500000:
|
||||
brate = B500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B576000
|
||||
case 576000: brate=B576000; break;
|
||||
case 576000:
|
||||
brate = B576000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600: brate=B921600; break;
|
||||
#ifdef B460800
|
||||
case 460800:
|
||||
brate = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
case 1000000: brate=B1000000; break;
|
||||
case 1000000:
|
||||
brate = B1000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
case 1152000: brate=B1152000; break;
|
||||
case 1152000:
|
||||
brate = B1152000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
case 1500000: brate=B1500000; break;
|
||||
case 1500000:
|
||||
brate = B1500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
case 2000000: brate=B2000000; break;
|
||||
case 2000000:
|
||||
brate = B2000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
case 2500000: brate=B2500000; break;
|
||||
case 2500000:
|
||||
brate = B2500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
case 3000000: brate=B3000000; break;
|
||||
case 3000000:
|
||||
brate = B3000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
case 3500000: brate=B3500000; break;
|
||||
case 3500000:
|
||||
brate = B3500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B400000
|
||||
case 4000000: brate=B4000000; break;
|
||||
case 4000000:
|
||||
brate = B4000000;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
log_error("can't set baudrate %dn", baudrate );
|
||||
return -1;
|
||||
default:
|
||||
log_error("can't set baudrate %dn", baudrate);
|
||||
return -1;
|
||||
}
|
||||
cfsetospeed(&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
|
||||
// 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");
|
||||
return -1;
|
||||
}
|
||||
|
@ -244,7 +298,8 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
|||
// and output speed.
|
||||
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
@ -253,114 +308,130 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){
|
||||
switch (parity){
|
||||
case BTSTACK_UART_PARITY_OFF:
|
||||
toptions->c_cflag &= ~PARENB;
|
||||
toptions->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case BTSTACK_UART_PARITY_EVEN:
|
||||
toptions->c_cflag |= PARENB;
|
||||
toptions->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case BTSTACK_UART_PARITY_ODD:
|
||||
toptions->c_cflag |= PARENB;
|
||||
toptions->c_cflag |= PARODD;
|
||||
default:
|
||||
break;
|
||||
static void btstack_uart_posix_set_parity_option(struct termios *toptions, int parity)
|
||||
{
|
||||
switch (parity)
|
||||
{
|
||||
case BTSTACK_UART_PARITY_OFF:
|
||||
toptions->c_cflag &= ~PARENB;
|
||||
toptions->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case BTSTACK_UART_PARITY_EVEN:
|
||||
toptions->c_cflag |= PARENB;
|
||||
toptions->c_cflag &= ~PARODD;
|
||||
break;
|
||||
case BTSTACK_UART_PARITY_ODD:
|
||||
toptions->c_cflag |= PARENB;
|
||||
toptions->c_cflag |= PARODD;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){
|
||||
if (flowcontrol) {
|
||||
static void btstack_uart_posix_set_flowcontrol_option(struct termios *toptions, int flowcontrol)
|
||||
{
|
||||
if (flowcontrol)
|
||||
{
|
||||
// with flow control
|
||||
toptions->c_cflag |= CRTSCTS;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// no flow control
|
||||
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;
|
||||
struct termios toptions;
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
struct termios toptions;
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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 uint32_t baudrate = uart_config->baudrate;
|
||||
const int flowcontrol = uart_config->flowcontrol;
|
||||
const int parity = uart_config->parity;
|
||||
const char *device_name = uart_config->device_name;
|
||||
const uint32_t baudrate = uart_config->baudrate;
|
||||
const int flowcontrol = uart_config->flowcontrol;
|
||||
const int parity = uart_config->parity;
|
||||
|
||||
struct termios toptions;
|
||||
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
|
||||
int fd = open(device_name, flags);
|
||||
if (fd == -1) {
|
||||
if (fd == -1)
|
||||
{
|
||||
log_error("Unable to open port %s", device_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfmakeraw(&toptions); // make raw
|
||||
|
||||
cfmakeraw(&toptions); // make raw
|
||||
|
||||
// 8N1
|
||||
toptions.c_cflag &= ~CSTOPB;
|
||||
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
|
||||
|
||||
|
||||
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VTIME] = 0;
|
||||
|
||||
|
||||
// no parity
|
||||
btstack_uart_posix_set_parity_option(&toptions, parity);
|
||||
|
||||
// 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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store fd in data source
|
||||
transport_data_source.source.fd = fd;
|
||||
|
||||
|
||||
// also set baudrate
|
||||
if (btstack_uart_posix_set_baudrate(baudrate) < 0){
|
||||
if (btstack_uart_posix_set_baudrate(baudrate) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -373,35 +444,40 @@ static int btstack_uart_posix_open(void){
|
|||
usleep(100000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int btstack_uart_posix_close_new(void){
|
||||
static int btstack_uart_posix_close_new(void)
|
||||
{
|
||||
|
||||
// first remove run loop handler
|
||||
btstack_run_loop_remove_data_source(&transport_data_source);
|
||||
|
||||
// then close device
|
||||
|
||||
// then close device
|
||||
close(transport_data_source.source.fd);
|
||||
transport_data_source.source.fd = -1;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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_len = len;
|
||||
btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
|
||||
|
@ -412,26 +488,26 @@ static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
|
|||
// SLIP Implementation Start
|
||||
#include "btstack_slip.h"
|
||||
|
||||
// max size of outgoing SLIP chunks
|
||||
#define SLIP_TX_CHUNK_LEN 128
|
||||
// max size of outgoing SLIP chunks
|
||||
#define SLIP_TX_CHUNK_LEN 128
|
||||
|
||||
#define SLIP_RECEIVE_BUFFER_SIZE 128
|
||||
|
||||
// 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
|
||||
static int btstack_uart_slip_write_bytes_len;
|
||||
static const uint8_t * btstack_uart_slip_write_bytes_data;
|
||||
static int btstack_uart_slip_write_active;
|
||||
static int btstack_uart_slip_write_bytes_len;
|
||||
static const uint8_t *btstack_uart_slip_write_bytes_data;
|
||||
static int btstack_uart_slip_write_active;
|
||||
|
||||
// block read
|
||||
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_len;
|
||||
static uint8_t btstack_uart_slip_receive_track_start;
|
||||
static uint32_t btstack_uart_slip_receive_start_time;
|
||||
static int btstack_uart_slip_receive_active;
|
||||
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_len;
|
||||
static uint8_t btstack_uart_slip_receive_track_start;
|
||||
static uint32_t btstack_uart_slip_receive_start_time;
|
||||
static int btstack_uart_slip_receive_active;
|
||||
|
||||
// callbacks
|
||||
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_process_write(btstack_data_source_t *ds) {
|
||||
|
||||
if (btstack_uart_slip_write_bytes_len == 0) return;
|
||||
static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds)
|
||||
{
|
||||
|
||||
if (btstack_uart_slip_write_bytes_len == 0)
|
||||
return;
|
||||
|
||||
uint32_t start = btstack_run_loop_get_time_ms();
|
||||
|
||||
// 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);
|
||||
if (bytes_written < 0) {
|
||||
int bytes_written = (int)write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len);
|
||||
if (bytes_written < 0)
|
||||
{
|
||||
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
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);
|
||||
|
||||
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++]);
|
||||
frame_size = btstack_slip_decoder_frame_size();
|
||||
}
|
||||
|
||||
// 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_pos = 0;
|
||||
}
|
||||
|
||||
// deliver frame if frame complete
|
||||
if (frame_size) {
|
||||
if (frame_size)
|
||||
{
|
||||
|
||||
// receive done
|
||||
btstack_uart_slip_receive_active = 0;
|
||||
|
||||
// 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);
|
||||
btstack_uart_slip_receive_start_time = 0;
|
||||
}
|
||||
|
@ -505,27 +591,31 @@ static uint16_t btstack_uart_slip_posix_process_buffer(void){
|
|||
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();
|
||||
|
||||
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_start_time = start;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
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();
|
||||
if (end - start > 10){
|
||||
if (end - start > 10)
|
||||
{
|
||||
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_len = (uint16_t ) bytes_read;
|
||||
btstack_uart_slip_receive_len = (uint16_t)bytes_read;
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
||||
// setup async write and start sending
|
||||
log_debug("slip: send %d bytes", pos);
|
||||
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);
|
||||
}
|
||||
|
||||
static void btstack_uart_slip_posix_block_sent(void){
|
||||
static void btstack_uart_slip_posix_block_sent(void)
|
||||
{
|
||||
// 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();
|
||||
return;
|
||||
}
|
||||
|
@ -557,12 +651,14 @@ static void btstack_uart_slip_posix_block_sent(void){
|
|||
btstack_uart_slip_write_active = 0;
|
||||
|
||||
// notify done
|
||||
if (frame_sent){
|
||||
if (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
|
||||
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
|
||||
// -----------------------------
|
||||
|
||||
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
|
||||
btstack_uart_slip_receive_active = 1;
|
||||
|
@ -588,24 +685,26 @@ static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len)
|
|||
// setup SLIP decoder
|
||||
btstack_slip_decoder_init(buffer, 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
|
||||
if (btstack_uart_slip_receive_len){
|
||||
if (btstack_uart_slip_receive_len)
|
||||
{
|
||||
int frame_found = btstack_uart_slip_posix_process_buffer();
|
||||
if (frame_found) return;
|
||||
if (frame_found)
|
||||
return;
|
||||
}
|
||||
|
||||
// no frame delivered, enable posix 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -613,59 +712,70 @@ static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void))
|
|||
#endif
|
||||
|
||||
// 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) {
|
||||
if (ds->source.fd < 0) return;
|
||||
switch (callback_type){
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
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)
|
||||
{
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
#ifdef ENABLE_H5
|
||||
if (btstack_uart_slip_receive_active){
|
||||
btstack_uart_slip_posix_process_read(ds);
|
||||
} else
|
||||
if (btstack_uart_slip_receive_active)
|
||||
{
|
||||
btstack_uart_slip_posix_process_read(ds);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
btstack_uart_block_posix_process_read(ds);
|
||||
}
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
{
|
||||
btstack_uart_block_posix_process_read(ds);
|
||||
}
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
#ifdef ENABLE_H5
|
||||
if (btstack_uart_slip_write_active){
|
||||
btstack_uart_slip_posix_process_write(ds);
|
||||
} else
|
||||
if (btstack_uart_slip_write_active)
|
||||
{
|
||||
btstack_uart_slip_posix_process_write(ds);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
btstack_uart_block_posix_process_write(ds);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
{
|
||||
btstack_uart_block_posix_process_write(ds);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const btstack_uart_t btstack_uart_posix = {
|
||||
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
|
||||
/* int (*open)(void); */ &btstack_uart_posix_open,
|
||||
/* int (*close)(void); */ &btstack_uart_posix_close_new,
|
||||
/* 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,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
|
||||
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
|
||||
/* 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 (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
|
||||
/* int (*get_supported_sleep_modes); */ NULL,
|
||||
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
|
||||
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
|
||||
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
|
||||
/* int (*open)(void); */ &btstack_uart_posix_open,
|
||||
/* int (*close)(void); */ &btstack_uart_posix_close_new,
|
||||
/* 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,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
|
||||
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
|
||||
/* 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 (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
|
||||
/* int (*get_supported_sleep_modes); */ NULL,
|
||||
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
|
||||
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
|
||||
|
||||
#ifdef ENABLE_H5
|
||||
/* 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 (*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 (*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 (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame,
|
||||
#else
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
const btstack_uart_t * btstack_uart_posix_instance(void){
|
||||
return &btstack_uart_posix;
|
||||
const btstack_uart_t *btstack_uart_posix_instance(void)
|
||||
{
|
||||
return &btstack_uart_posix;
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @file hal_bt.c
|
||||
***************************************************************************/
|
||||
#include <stdint.h>
|
||||
|
@ -50,27 +50,27 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
|
|||
// debugging only
|
||||
// #include <stdio.h>
|
||||
|
||||
#define BT_PORT_OUT P9OUT
|
||||
#define BT_PORT_SEL P9SEL
|
||||
#define BT_PORT_DIR P9DIR
|
||||
#define BT_PORT_REN P9REN
|
||||
#define BT_PIN_TXD BIT4
|
||||
#define BT_PIN_RXD BIT5
|
||||
#define BT_PORT_OUT P9OUT
|
||||
#define BT_PORT_SEL P9SEL
|
||||
#define BT_PORT_DIR P9DIR
|
||||
#define BT_PORT_REN P9REN
|
||||
#define BT_PIN_TXD BIT4
|
||||
#define BT_PIN_RXD BIT5
|
||||
|
||||
// RXD P9.5
|
||||
// TXD P9.4
|
||||
// RTS P1.4
|
||||
// CTS P1.3
|
||||
|
||||
void dummy_handler(void){};
|
||||
void dummy_handler(void) {};
|
||||
|
||||
// rx state
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t * rx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t *rx_buffer_ptr = 0;
|
||||
|
||||
// tx state
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t * tx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t *tx_buffer_ptr = 0;
|
||||
|
||||
// handlers
|
||||
static void (*rx_done_handler)(void) = dummy_handler;
|
||||
|
@ -78,11 +78,11 @@ static void (*tx_done_handler)(void) = dummy_handler;
|
|||
static void (*cts_irq_handler)(void) = dummy_handler;
|
||||
|
||||
/**
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* to communicate with the PAN BT .. assuming 16 Mhz CPU
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void hal_uart_dma_init(void)
|
||||
|
@ -92,18 +92,18 @@ void hal_uart_dma_init(void)
|
|||
BT_PORT_DIR &= ~BT_PIN_RXD;
|
||||
|
||||
// set BT RTS (P1.3)
|
||||
P1SEL &= ~BIT3; // = 0 - I/O
|
||||
P1DIR |= BIT3; // = 1 - Output
|
||||
P1OUT |= BIT3; // = 1 - RTS high -> stop
|
||||
P1SEL &= ~BIT3; // = 0 - I/O
|
||||
P1DIR |= BIT3; // = 1 - Output
|
||||
P1OUT |= BIT3; // = 1 - RTS high -> stop
|
||||
|
||||
// set BT CTS (P1.4)
|
||||
P1SEL &= ~BIT4; // = 0 - I/O
|
||||
P1DIR &= ~BIT4; // = 0 - Input P1DIR |= BIT4; // RTS
|
||||
|
||||
P1SEL &= ~BIT4; // = 0 - I/O
|
||||
P1DIR &= ~BIT4; // = 0 - Input P1DIR |= BIT4; // RTS
|
||||
|
||||
// set BT SHUTDOWN (P2.7) to 1 (active low)
|
||||
P2SEL &= ~BIT7; // = 0 - I/O
|
||||
P2DIR |= BIT7; // = 1 - Output
|
||||
P2OUT |= BIT7; // = 1 - Active low -> ok
|
||||
P2SEL &= ~BIT7; // = 0 - I/O
|
||||
P2DIR |= BIT7; // = 1 - Output
|
||||
P2OUT |= BIT7; // = 1 - Active low -> ok
|
||||
|
||||
// Enable ACLK to provide 32 kHz clock to Bluetooth module
|
||||
P2SEL |= BIT6;
|
||||
|
@ -112,13 +112,13 @@ void hal_uart_dma_init(void)
|
|||
// wait for Bluetooth to power up properly after providing 32khz clock
|
||||
waitAboutOneSecond();
|
||||
|
||||
UCA2CTL1 |= UCSWRST; //Reset State
|
||||
UCA2CTL1 |= UCSWRST; // Reset State
|
||||
UCA2CTL0 = UCMODE_0;
|
||||
|
||||
UCA2CTL0 &= ~UC7BIT; // 8bit char
|
||||
|
||||
UCA2CTL0 &= ~UC7BIT; // 8bit char
|
||||
UCA2CTL1 |= UCSSEL_2;
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
hal_uart_dma_set_baud(115200);
|
||||
}
|
||||
|
@ -127,102 +127,108 @@ void hal_uart_dma_init(void)
|
|||
|
||||
UART used in low-frequency mode
|
||||
In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
|
||||
|
||||
|
||||
16000000 / 576000 = 277.77
|
||||
16000000 / 115200 = 138.88
|
||||
16000000 / 921600 = 17.36
|
||||
16000000 / 460800 = 17.36
|
||||
16000000 / 1000000 = 16.00
|
||||
16000000 / 2000000 = 8.00
|
||||
16000000 / 2400000 = 6.66
|
||||
16000000 / 3000000 = 3.33
|
||||
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;
|
||||
|
||||
UCA2CTL1 |= UCSWRST; //Reset State
|
||||
|
||||
switch (baud){
|
||||
UCA2CTL1 |= UCSWRST; // Reset State
|
||||
|
||||
case 4000000:
|
||||
UCA2BR0 = 2;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 3000000:
|
||||
UCA2BR0 = 3;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 2400000:
|
||||
UCA2BR0 = 6;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 5 << 1; // + 0.625
|
||||
break;
|
||||
switch (baud)
|
||||
{
|
||||
|
||||
case 2000000:
|
||||
UCA2BR0 = 8;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
case 4000000:
|
||||
UCA2BR0 = 2;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA2BR0 = 16;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 921600:
|
||||
UCA2BR0 = 17;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA2BR0 = 138; // from family user guide
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 3000000:
|
||||
UCA2BR0 = 3;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA2BR0 = 21;
|
||||
UCA2BR1 = 1;
|
||||
UCA2MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 2400000:
|
||||
UCA2BR0 = 6;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 5 << 1; // + 0.625
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
case 2000000:
|
||||
UCA2BR0 = 8;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA2BR0 = 16;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 460800:
|
||||
UCA2BR0 = 17;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA2BR0 = 138; // from family user guide
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA2BR0 = 21;
|
||||
UCA2BR1 = 1;
|
||||
UCA2MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
|
||||
if (the_irq_handler){
|
||||
P1IFG = 0; // no IRQ pending
|
||||
P1IV = 0; // no IRQ pending
|
||||
P1IES &= ~BIT4; // IRQ on 0->1 transition
|
||||
P1IE |= BIT4; // enable IRQ for P1.3
|
||||
void hal_uart_dma_set_csr_irq_handler(void (*the_irq_handler)(void))
|
||||
{
|
||||
if (the_irq_handler)
|
||||
{
|
||||
P1IFG = 0; // no IRQ pending
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
P1IE &= ~BIT4;
|
||||
|
||||
P1IE &= ~BIT4;
|
||||
cts_irq_handler = dummy_handler;
|
||||
}
|
||||
|
||||
|
@ -230,44 +236,49 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
|
|||
/**
|
||||
* @brief Disables the serial communications peripheral and clears the GPIO
|
||||
* settings used to communicate with the BT.
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
**************************************************************************/
|
||||
void hal_uart_dma_shutdown(void) {
|
||||
|
||||
void hal_uart_dma_shutdown(void)
|
||||
{
|
||||
|
||||
UCA2IE &= ~(UCRXIE | UCTXIE);
|
||||
UCA2CTL1 = UCSWRST; //Reset State
|
||||
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
|
||||
UCA2CTL1 = UCSWRST; // Reset State
|
||||
BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
|
||||
BT_PORT_DIR |= BT_PIN_TXD;
|
||||
BT_PORT_DIR |= 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){
|
||||
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
tx_buffer_ptr = (uint8_t *) data;
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
tx_buffer_ptr = (uint8_t *)data;
|
||||
bytes_to_write = len;
|
||||
|
||||
UCA2IE |= UCTXIE; // enable TX interrupts
|
||||
UCA2IE |= UCTXIE; // enable TX interrupts
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_enable_rx(void){
|
||||
P1OUT &= ~BIT3; // = 0 - RTS low -> ok
|
||||
static inline void hal_uart_dma_enable_rx(void)
|
||||
{
|
||||
P1OUT &= ~BIT3; // = 0 - RTS low -> ok
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_disable_rx(void){
|
||||
P1OUT |= BIT3; // = 1 - RTS high -> stop
|
||||
static inline void hal_uart_dma_disable_rx(void)
|
||||
{
|
||||
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
|
||||
UCA2IE &= ~UCRXIE ;
|
||||
UCA2IE &= ~UCRXIE;
|
||||
|
||||
rx_buffer_ptr = buffer;
|
||||
bytes_to_read = len;
|
||||
|
@ -279,13 +290,15 @@ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
|
|||
UCA2IE |= UCRXIE;
|
||||
|
||||
// if byte was pending, ISR controls RTS
|
||||
if (!pending) {
|
||||
if (!pending)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
}
|
||||
}
|
||||
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep){
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep)
|
||||
{
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
}
|
||||
|
||||
// block-wise "DMA" RX/TX UART driver
|
||||
|
@ -293,78 +306,86 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
|
|||
__attribute__((interrupt(USCI_A2_VECTOR)))
|
||||
#endif
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma vector=USCI_A2_VECTOR
|
||||
#pragma vector = USCI_A2_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void usbRxTxISR(void){
|
||||
void
|
||||
usbRxTxISR(void)
|
||||
{
|
||||
|
||||
// find reason
|
||||
switch (UCA2IV){
|
||||
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0) {
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA2IE &= ~UCRXIE ; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA2RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0) {
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
P1OUT |= BIT3; // = 1 - RTS high -> stop
|
||||
UCA2IE &= ~UCRXIE ; // disable RX interrupts
|
||||
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
switch (UCA2IV)
|
||||
{
|
||||
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0){
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA2TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0)
|
||||
{
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA2IE &= ~UCRXIE; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA2RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
P1OUT |= BIT3; // = 1 - RTS high -> stop
|
||||
UCA2IE &= ~UCRXIE; // disable RX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0)
|
||||
{
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA2TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CTS ISR
|
||||
|
||||
extern void ehcill_handle(uint8_t action);
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((interrupt(PORT1_VECTOR)))
|
||||
#endif
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma vector=PORT1_VECTOR
|
||||
#pragma vector = PORT1_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void ctsISR(void){
|
||||
void
|
||||
ctsISR(void)
|
||||
{
|
||||
P1IV = 0;
|
||||
(*cts_irq_handler)();
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @file hal_bt.c
|
||||
***************************************************************************/
|
||||
#include <stdint.h>
|
||||
|
@ -50,27 +50,27 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
|
|||
// debugging only
|
||||
// #include <stdio.h>
|
||||
|
||||
#define BT_PORT_OUT P9OUT
|
||||
#define BT_PORT_SEL P9SEL
|
||||
#define BT_PORT_DIR P9DIR
|
||||
#define BT_PORT_REN P9REN
|
||||
#define BT_PIN_TXD BIT4
|
||||
#define BT_PIN_RXD BIT5
|
||||
#define BT_PORT_OUT P9OUT
|
||||
#define BT_PORT_SEL P9SEL
|
||||
#define BT_PORT_DIR P9DIR
|
||||
#define BT_PORT_REN P9REN
|
||||
#define BT_PIN_TXD BIT4
|
||||
#define BT_PIN_RXD BIT5
|
||||
|
||||
// RXD P9.5
|
||||
// TXD P9.4
|
||||
// RTS P1.4
|
||||
// CTS P1.3
|
||||
|
||||
void dummy_handler(void){};
|
||||
void dummy_handler(void) {};
|
||||
|
||||
// rx state
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t * rx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t *rx_buffer_ptr = 0;
|
||||
|
||||
// tx state
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t * tx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t *tx_buffer_ptr = 0;
|
||||
|
||||
// handlers
|
||||
static void (*rx_done_handler)(void) = dummy_handler;
|
||||
|
@ -78,11 +78,11 @@ static void (*tx_done_handler)(void) = dummy_handler;
|
|||
static void (*cts_irq_handler)(void) = dummy_handler;
|
||||
|
||||
/**
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* to communicate with the PAN BT .. assuming 16 Mhz CPU
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void hal_uart_dma_init(void)
|
||||
|
@ -92,18 +92,18 @@ void hal_uart_dma_init(void)
|
|||
BT_PORT_DIR &= ~BT_PIN_RXD;
|
||||
|
||||
// set BT RTS (P1.4)
|
||||
P1SEL &= ~BIT4; // = 0 - I/O
|
||||
P1DIR |= BIT4; // = 1 - Output
|
||||
P1OUT |= BIT4; // = 1 - RTS high -> stop
|
||||
P1SEL &= ~BIT4; // = 0 - I/O
|
||||
P1DIR |= BIT4; // = 1 - Output
|
||||
P1OUT |= BIT4; // = 1 - RTS high -> stop
|
||||
|
||||
// set BT CTS
|
||||
P1SEL &= ~BIT3; // = 0 - I/O
|
||||
P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS
|
||||
|
||||
// set BT CTS
|
||||
P1SEL &= ~BIT3; // = 0 - I/O
|
||||
P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS
|
||||
|
||||
// set BT SHUTDOWN (P8.2) to 1 (active low)
|
||||
P8SEL &= ~BIT2; // = 0 - I/O
|
||||
P8DIR |= BIT2; // = 1 - Output
|
||||
P8OUT |= BIT2; // = 1 - Active low -> ok
|
||||
P8SEL &= ~BIT2; // = 0 - I/O
|
||||
P8DIR |= BIT2; // = 1 - Output
|
||||
P8OUT |= BIT2; // = 1 - Active low -> ok
|
||||
|
||||
// Enable ACLK to provide 32 kHz clock to Bluetooth module
|
||||
P11SEL |= BIT0;
|
||||
|
@ -112,13 +112,13 @@ void hal_uart_dma_init(void)
|
|||
// wait for Bluetooth to power up properly after providing 32khz clock
|
||||
waitAboutOneSecond();
|
||||
|
||||
UCA2CTL1 |= UCSWRST; //Reset State
|
||||
UCA2CTL1 |= UCSWRST; // Reset State
|
||||
UCA2CTL0 = UCMODE_0;
|
||||
|
||||
UCA2CTL0 &= ~UC7BIT; // 8bit char
|
||||
|
||||
UCA2CTL0 &= ~UC7BIT; // 8bit char
|
||||
UCA2CTL1 |= UCSSEL_2;
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
hal_uart_dma_set_baud(115200);
|
||||
}
|
||||
|
@ -127,102 +127,108 @@ void hal_uart_dma_init(void)
|
|||
|
||||
UART used in low-frequency mode
|
||||
In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
|
||||
|
||||
|
||||
16000000 / 576000 = 277.77
|
||||
16000000 / 115200 = 138.88
|
||||
16000000 / 921600 = 17.36
|
||||
16000000 / 460800 = 17.36
|
||||
16000000 / 1000000 = 16.00
|
||||
16000000 / 2000000 = 8.00
|
||||
16000000 / 2400000 = 6.66
|
||||
16000000 / 3000000 = 3.33
|
||||
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;
|
||||
|
||||
UCA2CTL1 |= UCSWRST; //Reset State
|
||||
|
||||
switch (baud){
|
||||
UCA2CTL1 |= UCSWRST; // Reset State
|
||||
|
||||
case 4000000:
|
||||
UCA2BR0 = 2;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 3000000:
|
||||
UCA2BR0 = 3;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 2400000:
|
||||
UCA2BR0 = 6;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 5 << 1; // + 0.625
|
||||
break;
|
||||
switch (baud)
|
||||
{
|
||||
|
||||
case 2000000:
|
||||
UCA2BR0 = 8;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
case 4000000:
|
||||
UCA2BR0 = 2;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA2BR0 = 16;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 921600:
|
||||
UCA2BR0 = 17;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA2BR0 = 138; // from family user guide
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 3000000:
|
||||
UCA2BR0 = 3;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA2BR0 = 21;
|
||||
UCA2BR1 = 1;
|
||||
UCA2MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 2400000:
|
||||
UCA2BR0 = 6;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 5 << 1; // + 0.625
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
case 2000000:
|
||||
UCA2BR0 = 8;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA2BR0 = 16;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 460800:
|
||||
UCA2BR0 = 17;
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA2BR0 = 138; // from family user guide
|
||||
UCA2BR1 = 0;
|
||||
UCA2MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA2BR0 = 21;
|
||||
UCA2BR1 = 1;
|
||||
UCA2MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA2CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
|
||||
if (the_irq_handler){
|
||||
P1IFG = 0; // no IRQ pending
|
||||
P1IV = 0; // no IRQ pending
|
||||
P1IES &= ~BIT3; // IRQ on 0->1 transition
|
||||
P1IE |= BIT3; // enable IRQ for P1.3
|
||||
void hal_uart_dma_set_csr_irq_handler(void (*the_irq_handler)(void))
|
||||
{
|
||||
if (the_irq_handler)
|
||||
{
|
||||
P1IFG = 0; // no IRQ pending
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
P1IE &= ~BIT3;
|
||||
|
||||
P1IE &= ~BIT3;
|
||||
cts_irq_handler = dummy_handler;
|
||||
}
|
||||
|
||||
|
@ -230,44 +236,49 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
|
|||
/**
|
||||
* @brief Disables the serial communications peripheral and clears the GPIO
|
||||
* settings used to communicate with the BT.
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
**************************************************************************/
|
||||
void hal_uart_dma_shutdown(void) {
|
||||
|
||||
void hal_uart_dma_shutdown(void)
|
||||
{
|
||||
|
||||
UCA2IE &= ~(UCRXIE | UCTXIE);
|
||||
UCA2CTL1 = UCSWRST; //Reset State
|
||||
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
|
||||
UCA2CTL1 = UCSWRST; // Reset State
|
||||
BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
|
||||
BT_PORT_DIR |= BT_PIN_TXD;
|
||||
BT_PORT_DIR |= 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){
|
||||
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
tx_buffer_ptr = (uint8_t *) data;
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
tx_buffer_ptr = (uint8_t *)data;
|
||||
bytes_to_write = len;
|
||||
|
||||
UCA2IE |= UCTXIE; // enable TX interrupts
|
||||
UCA2IE |= UCTXIE; // enable TX interrupts
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_enable_rx(void){
|
||||
P1OUT &= ~BIT4; // = 0 - RTS low -> ok
|
||||
static inline void hal_uart_dma_enable_rx(void)
|
||||
{
|
||||
P1OUT &= ~BIT4; // = 0 - RTS low -> ok
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_disable_rx(void){
|
||||
P1OUT |= BIT4; // = 1 - RTS high -> stop
|
||||
static inline void hal_uart_dma_disable_rx(void)
|
||||
{
|
||||
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
|
||||
UCA2IE &= ~UCRXIE ;
|
||||
UCA2IE &= ~UCRXIE;
|
||||
|
||||
rx_buffer_ptr = buffer;
|
||||
bytes_to_read = len;
|
||||
|
@ -279,13 +290,15 @@ void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
|
|||
UCA2IE |= UCRXIE;
|
||||
|
||||
// if byte was pending, ISR controls RTS
|
||||
if (!pending) {
|
||||
if (!pending)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
}
|
||||
}
|
||||
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep){
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep)
|
||||
{
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
}
|
||||
|
||||
// block-wise "DMA" RX/TX UART driver
|
||||
|
@ -293,78 +306,86 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
|
|||
__attribute__((interrupt(USCI_A2_VECTOR)))
|
||||
#endif
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma vector=USCI_A2_VECTOR
|
||||
#pragma vector = USCI_A2_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void usbRxTxISR(void){
|
||||
void
|
||||
usbRxTxISR(void)
|
||||
{
|
||||
|
||||
// find reason
|
||||
switch (UCA2IV){
|
||||
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0) {
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA2IE &= ~UCRXIE ; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA2RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0) {
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
P1OUT |= BIT4; // = 1 - RTS high -> stop
|
||||
UCA2IE &= ~UCRXIE ; // disable RX interrupts
|
||||
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
switch (UCA2IV)
|
||||
{
|
||||
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0){
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA2TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
UCA2IE &= ~UCTXIE ; // disable TX interrupts
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0)
|
||||
{
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA2IE &= ~UCRXIE; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA2RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
P1OUT |= BIT4; // = 1 - RTS high -> stop
|
||||
UCA2IE &= ~UCRXIE; // disable RX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0)
|
||||
{
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA2TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UCA2IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CTS ISR
|
||||
|
||||
extern void ehcill_handle(uint8_t action);
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((interrupt(PORT1_VECTOR)))
|
||||
#endif
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma vector=PORT1_VECTOR
|
||||
#pragma vector = PORT1_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void ctsISR(void){
|
||||
void
|
||||
ctsISR(void)
|
||||
{
|
||||
P1IV = 0;
|
||||
(*cts_irq_handler)();
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* @file hal_bt.c
|
||||
***************************************************************************/
|
||||
#include <stdint.h>
|
||||
|
@ -50,15 +50,14 @@ extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
|
|||
// debugging only
|
||||
// #include <stdio.h>
|
||||
|
||||
|
||||
// RXD 3.4
|
||||
// TXD 3.3
|
||||
#define BT_PORT_OUT P3OUT
|
||||
#define BT_PORT_SEL P3SEL
|
||||
#define BT_PORT_DIR P3DIR
|
||||
#define BT_PORT_REN P3REN
|
||||
#define BT_PIN_TXD BIT3
|
||||
#define BT_PIN_RXD BIT4
|
||||
#define BT_PORT_OUT P3OUT
|
||||
#define BT_PORT_SEL P3SEL
|
||||
#define BT_PORT_DIR P3DIR
|
||||
#define BT_PORT_REN P3REN
|
||||
#define BT_PIN_TXD BIT3
|
||||
#define BT_PIN_RXD BIT4
|
||||
|
||||
// RTS P2.3
|
||||
#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_PIN BIT1
|
||||
|
||||
void dummy_handler(void){};
|
||||
void dummy_handler(void) {};
|
||||
|
||||
// rx state
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t * rx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t *rx_buffer_ptr = 0;
|
||||
|
||||
// tx state
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t * tx_buffer_ptr = 0;
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t *tx_buffer_ptr = 0;
|
||||
|
||||
// handlers
|
||||
static void (*rx_done_handler)(void) = dummy_handler;
|
||||
|
@ -94,11 +93,11 @@ static void (*tx_done_handler)(void) = dummy_handler;
|
|||
static void (*cts_irq_handler)(void) = dummy_handler;
|
||||
|
||||
/**
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* @brief Initializes the serial communications peripheral and GPIO ports
|
||||
* to communicate with the PAN BT .. assuming 16 Mhz CPU
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void hal_uart_dma_init(void)
|
||||
|
@ -108,29 +107,29 @@ void hal_uart_dma_init(void)
|
|||
BT_PORT_DIR &= ~BT_PIN_RXD;
|
||||
|
||||
// set BT RTS
|
||||
RTS_SEL &= ~RTS_PIN; // = 0 - I/O
|
||||
RTS_DIR |= RTS_PIN; // = 1 - Output
|
||||
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
|
||||
RTS_SEL &= ~RTS_PIN; // = 0 - I/O
|
||||
RTS_DIR |= RTS_PIN; // = 1 - Output
|
||||
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
|
||||
|
||||
// set BT CTS
|
||||
CTS_SEL &= ~CTS_PIN; // = 0 - I/O
|
||||
CTS_DIR &= ~CTS_PIN; // = 0 - Input
|
||||
|
||||
CTS_SEL &= ~CTS_PIN; // = 0 - I/O
|
||||
CTS_DIR &= ~CTS_PIN; // = 0 - Input
|
||||
|
||||
// set BT SHUTDOWN to 1 (active low)
|
||||
N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN; // = 0 - I/O
|
||||
N_SHUTDOWN_DIR |= N_SHUTDOWN_PIN; // = 1 - Output
|
||||
N_SHUTDOWN_OUT |= N_SHUTDOWN_PIN; // = 1 - Active low -> ok
|
||||
N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN; // = 0 - I/O
|
||||
N_SHUTDOWN_DIR |= N_SHUTDOWN_PIN; // = 1 - Output
|
||||
N_SHUTDOWN_OUT |= N_SHUTDOWN_PIN; // = 1 - Active low -> ok
|
||||
|
||||
// wait for Bluetooth to power up properly after providing 32khz clock
|
||||
waitAboutOneSecond();
|
||||
|
||||
UCA0CTL1 |= UCSWRST; //Reset State
|
||||
UCA0CTL1 |= UCSWRST; // Reset State
|
||||
UCA0CTL0 = UCMODE_0;
|
||||
|
||||
UCA0CTL0 &= ~UC7BIT; // 8bit char
|
||||
|
||||
UCA0CTL0 &= ~UC7BIT; // 8bit char
|
||||
UCA0CTL1 |= UCSSEL_2;
|
||||
|
||||
UCA0CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA0CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
hal_uart_dma_set_baud(115200);
|
||||
}
|
||||
|
@ -139,102 +138,108 @@ void hal_uart_dma_init(void)
|
|||
|
||||
UART used in low-frequency mode
|
||||
In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
|
||||
|
||||
|
||||
16000000 / 576000 = 277.77
|
||||
16000000 / 115200 = 138.88
|
||||
16000000 / 921600 = 17.36
|
||||
16000000 / 460800 = 17.36
|
||||
16000000 / 1000000 = 16.00
|
||||
16000000 / 2000000 = 8.00
|
||||
16000000 / 2400000 = 6.66
|
||||
16000000 / 3000000 = 3.33
|
||||
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;
|
||||
|
||||
UCA0CTL1 |= UCSWRST; //Reset State
|
||||
|
||||
switch (baud){
|
||||
UCA0CTL1 |= UCSWRST; // Reset State
|
||||
|
||||
case 4000000:
|
||||
UCA0BR0 = 2;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 3000000:
|
||||
UCA0BR0 = 3;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 2400000:
|
||||
UCA0BR0 = 6;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 5 << 1; // + 0.625
|
||||
break;
|
||||
switch (baud)
|
||||
{
|
||||
|
||||
case 2000000:
|
||||
UCA0BR0 = 8;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
case 4000000:
|
||||
UCA0BR0 = 2;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA0BR0 = 16;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 921600:
|
||||
UCA0BR0 = 17;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA0BR0 = 138; // from family user guide
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 3000000:
|
||||
UCA0BR0 = 3;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA0BR0 = 21;
|
||||
UCA0BR1 = 1;
|
||||
UCA0MCTL= 7 << 1; // + 0.875
|
||||
break;
|
||||
case 2400000:
|
||||
UCA0BR0 = 6;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 5 << 1; // + 0.625
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
case 2000000:
|
||||
UCA0BR0 = 8;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 1000000:
|
||||
UCA0BR0 = 16;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 0 << 1; // + 0.000
|
||||
break;
|
||||
|
||||
case 460800:
|
||||
UCA0BR0 = 17;
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 7 << 1; // 3 << 1; // + 0.375
|
||||
break;
|
||||
|
||||
case 115200:
|
||||
UCA0BR0 = 138; // from family user guide
|
||||
UCA0BR1 = 0;
|
||||
UCA0MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
UCA0BR0 = 21;
|
||||
UCA0BR1 = 1;
|
||||
UCA0MCTL = 7 << 1; // + 0.875
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
UCA0CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
UCA0CTL1 &= ~UCSWRST; // continue
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
if (the_irq_handler){
|
||||
P2IFG = 0; // no IRQ pending
|
||||
P2IV = 0; // no IRQ pending
|
||||
P2IES &= ~ CTS_PIN; // IRQ on 0->1 transition
|
||||
P2IE |= CTS_PIN; // enable IRQ for P8.1
|
||||
if (the_irq_handler)
|
||||
{
|
||||
P2IFG = 0; // no IRQ pending
|
||||
P2IV = 0; // no IRQ pending
|
||||
P2IES &= ~CTS_PIN; // IRQ on 0->1 transition
|
||||
P2IE |= CTS_PIN; // enable IRQ for P8.1
|
||||
cts_irq_handler = the_irq_handler;
|
||||
return;
|
||||
}
|
||||
P2IE &= ~CTS_PIN;
|
||||
P2IE &= ~CTS_PIN;
|
||||
cts_irq_handler = dummy_handler;
|
||||
#endif
|
||||
}
|
||||
|
@ -243,62 +248,69 @@ void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
|
|||
/**
|
||||
* @brief Disables the serial communications peripheral and clears the GPIO
|
||||
* settings used to communicate with the BT.
|
||||
*
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
*
|
||||
* @return none
|
||||
**************************************************************************/
|
||||
void hal_uart_dma_shutdown(void) {
|
||||
|
||||
void hal_uart_dma_shutdown(void)
|
||||
{
|
||||
|
||||
UCA0IE &= ~(UCRXIE | UCTXIE);
|
||||
UCA0CTL1 = UCSWRST; //Reset State
|
||||
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
|
||||
UCA0CTL1 = UCSWRST; // Reset State
|
||||
BT_PORT_SEL &= ~(BT_PIN_RXD + BT_PIN_TXD);
|
||||
BT_PORT_DIR |= BT_PIN_TXD;
|
||||
BT_PORT_DIR |= 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){
|
||||
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA0IE &= ~UCTXIE ; // disable TX interrupts
|
||||
void hal_uart_dma_send_block(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
tx_buffer_ptr = (uint8_t *) data;
|
||||
// printf("hal_uart_dma_send_block, size %u\n\r", len);
|
||||
|
||||
UCA0IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
tx_buffer_ptr = (uint8_t *)data;
|
||||
bytes_to_write = len;
|
||||
|
||||
UCA0IE |= UCTXIE; // enable TX interrupts
|
||||
UCA0IE |= UCTXIE; // enable TX interrupts
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_enable_rx(void){
|
||||
RTS_OUT &= ~ RTS_PIN; // = 0 - RTS low -> ok
|
||||
static inline void hal_uart_dma_enable_rx(void)
|
||||
{
|
||||
RTS_OUT &= ~RTS_PIN; // = 0 - RTS low -> ok
|
||||
}
|
||||
|
||||
static inline void hal_uart_dma_disable_rx(void){
|
||||
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
|
||||
static inline void hal_uart_dma_disable_rx(void)
|
||||
{
|
||||
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
|
||||
UCA0IE &= ~UCRXIE;
|
||||
|
||||
rx_buffer_ptr = buffer;
|
||||
bytes_to_read = len;
|
||||
|
||||
|
||||
// check if byte already received
|
||||
int pending = UCA0IFG & UCRXIFG;
|
||||
|
||||
// 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 (!pending) {
|
||||
if (!pending)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
}
|
||||
}
|
||||
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep){
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep)
|
||||
{
|
||||
hal_cpu_set_uart_needed_during_sleep(!sleep);
|
||||
}
|
||||
|
||||
// block-wise "DMA" RX/TX UART driver
|
||||
|
@ -306,81 +318,88 @@ void hal_uart_dma_set_sleep(uint8_t sleep){
|
|||
__attribute__((interrupt(USCI_A0_VECTOR)))
|
||||
#endif
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#pragma vector=USCI_A0_VECTOR
|
||||
#pragma vector = USCI_A0_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void usbRxTxISR(void){
|
||||
void
|
||||
usbRxTxISR(void)
|
||||
{
|
||||
|
||||
// find reason
|
||||
switch (UCA0IV){
|
||||
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0) {
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA0IE &= ~UCRXIE ; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA0RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0) {
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
|
||||
UCA0IE &= ~UCRXIE ; // disable RX interrupts
|
||||
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
switch (UCA0IV)
|
||||
{
|
||||
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0){
|
||||
UCA0IE &= ~UCTXIE ; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA0TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
UCA0IE &= ~UCTXIE ; // disable TX interrupts
|
||||
case 2: // RXIFG
|
||||
if (bytes_to_read == 0)
|
||||
{
|
||||
hal_uart_dma_disable_rx();
|
||||
UCA0IE &= ~UCRXIE; // disable RX interrupts
|
||||
return;
|
||||
}
|
||||
*rx_buffer_ptr = UCA0RXBUF;
|
||||
++rx_buffer_ptr;
|
||||
--bytes_to_read;
|
||||
if (bytes_to_read > 0)
|
||||
{
|
||||
hal_uart_dma_enable_rx();
|
||||
return;
|
||||
}
|
||||
RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop
|
||||
UCA0IE &= ~UCRXIE; // disable RX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
(*rx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case 4: // TXIFG
|
||||
if (bytes_to_write == 0)
|
||||
{
|
||||
UCA0IE &= ~UCTXIE; // disable TX interrupts
|
||||
return;
|
||||
}
|
||||
UCA0TXBUF = *tx_buffer_ptr;
|
||||
++tx_buffer_ptr;
|
||||
--bytes_to_write;
|
||||
|
||||
if (bytes_to_write > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UCA0IE &= ~UCTXIE; // disable TX interrupts
|
||||
|
||||
(*tx_done_handler)();
|
||||
|
||||
// force exit low power mode
|
||||
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CTS ISR
|
||||
// CTS ISR
|
||||
#ifdef HAVE_CTS_IRQ
|
||||
// TODO: there's no PORT8_VECTOR, but configuration seems possible
|
||||
|
||||
extern void ehcill_handle(uint8_t action);
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
#define EHCILL_CTS_SIGNAL 0x034
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((interrupt(PORT2_VECTOR)))
|
||||
#elif defined( __IAR_SYSTEMS_ICC__)
|
||||
#pragma vector=PORT2_VECTOR
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#pragma vector = PORT2_VECTOR
|
||||
__interrupt
|
||||
#endif
|
||||
void ctsISR(void){
|
||||
void
|
||||
ctsISR(void)
|
||||
{
|
||||
P2IV = 0;
|
||||
(*cts_irq_handler)();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -67,34 +67,34 @@
|
|||
#include "hci.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_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
|
||||
static hci_transport_config_uart_t transport_config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
921600, // main baudrate
|
||||
0, // flow control
|
||||
460800, // main baudrate
|
||||
0, // flow control
|
||||
NULL,
|
||||
BTSTACK_UART_PARITY_EVEN, // parity
|
||||
};
|
||||
static btstack_uart_config_t uart_config;
|
||||
|
||||
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 void sigint_handler(int param){
|
||||
static void sigint_handler(int param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
|
@ -103,80 +103,85 @@ static void sigint_handler(int param){
|
|||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - 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;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void phase2(int status);
|
||||
int main(int argc, const char * argv[]){
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
|
||||
/// GET STARTED with BTstack ///
|
||||
btstack_memory_init();
|
||||
|
||||
// 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);
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
|
||||
// setup run loop
|
||||
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
|
||||
|
||||
|
||||
// pick serial port and configure uart block driver
|
||||
transport_config.device_name = "/dev/tty.usbserial-A9OVNX5P"; // RedBear IoT pHAT breakout board
|
||||
|
||||
// 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);
|
||||
|
||||
// set chipset name
|
||||
btstack_chipset_bcm_set_device_name("BCM43430A1");
|
||||
|
||||
// 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
|
||||
uart_config.baudrate = transport_config.baudrate_init;
|
||||
uart_config.baudrate = transport_config.baudrate_init;
|
||||
uart_config.flowcontrol = transport_config.flowcontrol;
|
||||
uart_config.device_name = transport_config.device_name;
|
||||
uart_driver->init(&uart_config);
|
||||
|
||||
|
||||
// setup HCI (to be able to use bcm chipset driver)
|
||||
// init HCI
|
||||
const hci_transport_t * transport = hci_transport_h5_instance(uart_driver);
|
||||
hci_init(transport, (void*) &transport_config);
|
||||
const hci_transport_t *transport = hci_transport_h5_instance(uart_driver);
|
||||
hci_init(transport, (void *)&transport_config);
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
|
||||
// inform about BTstack state
|
||||
|
@ -196,13 +201,15 @@ int main(int argc, const char * argv[]){
|
|||
btstack_chipset_bcm_download_firmware_with_uart(uart_driver, transport_config.baudrate_main, &phase2);
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
btstack_run_loop_execute();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void phase2(int status){
|
||||
static void phase2(int status)
|
||||
{
|
||||
|
||||
if (status){
|
||||
if (status)
|
||||
{
|
||||
printf("Download firmware failed\n");
|
||||
return;
|
||||
}
|
||||
|
@ -212,4 +219,3 @@ static void phase2(int status){
|
|||
// setup app
|
||||
btstack_main(main_argc, main_argv);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define ENABLE_SDP
|
||||
#define HAVE_TRANSPORT_H4
|
||||
#define UART_DEVICE "/dev/tty.bluetooth"
|
||||
#define UART_SPEED 921600
|
||||
#define UART_SPEED 460800
|
||||
#define USE_LAUNCHD
|
||||
#define USE_SPRINGBOARD
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -72,55 +72,60 @@
|
|||
#include "wilc3000_ble_firmware.h"
|
||||
|
||||
static int main_argc;
|
||||
static const char ** main_argv;
|
||||
static const btstack_uart_t * uart_driver;
|
||||
static const char **main_argv;
|
||||
static const btstack_uart_t *uart_driver;
|
||||
static btstack_uart_config_t uart_config;
|
||||
|
||||
#define TLV_DB_PATH_PREFIX "/tmp/btstack_"
|
||||
#define TLV_DB_PATH_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
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 = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
921600,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
460800,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
bd_addr_t addr;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
static void sigint_handler(int param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
|
@ -129,19 +134,22 @@ static void sigint_handler(int param){
|
|||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - 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");
|
||||
return;
|
||||
}
|
||||
|
@ -149,10 +157,10 @@ static void phase2(int status){
|
|||
printf("Phase 2: Main app\n");
|
||||
|
||||
// init HCI
|
||||
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void*) &transport_config);
|
||||
const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void *)&transport_config);
|
||||
hci_set_chipset(btstack_chipset_atwilc3000_instance());
|
||||
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
@ -164,17 +172,17 @@ static void phase2(int status){
|
|||
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());
|
||||
|
||||
// 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);
|
||||
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);
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
|
||||
|
@ -183,7 +191,7 @@ int main(int argc, const char * argv[]){
|
|||
uart_driver = btstack_uart_posix_instance();
|
||||
|
||||
// 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.device_name = transport_config.device_name;
|
||||
uart_driver->init(&uart_config);
|
||||
|
@ -195,9 +203,9 @@ int main(int argc, const char * argv[]){
|
|||
printf("Phase 1: Download firmware\n");
|
||||
|
||||
// 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
|
||||
btstack_run_loop_execute();
|
||||
btstack_run_loop_execute();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -76,72 +76,80 @@
|
|||
#include "btstack_chipset_stlc2500d.h"
|
||||
#include "btstack_chipset_tc3566x.h"
|
||||
|
||||
|
||||
#define TLV_DB_PATH_PREFIX "/tmp/btstack_"
|
||||
#define TLV_DB_PATH_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
|
||||
static int is_bcm;
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
static void local_version_information_handler(uint8_t * packet);
|
||||
int btstack_main(int argc, const char *argv[]);
|
||||
static void local_version_information_handler(uint8_t *packet);
|
||||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
bd_addr_t addr;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6+248] = 0;
|
||||
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);
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6 + 248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
if (is_bcm)
|
||||
{
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
|
||||
{
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
static void sigint_handler(int param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
|
@ -150,16 +158,18 @@ static void sigint_handler(int param){
|
|||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - 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)
|
||||
printf("Using 3000000 baud.\n");
|
||||
config.baudrate_main = 3000000;
|
||||
|
@ -167,86 +177,90 @@ static void use_fast_uart(void){
|
|||
printf("Using 2000000 baud.\n");
|
||||
config.baudrate_main = 2000000;
|
||||
#else
|
||||
printf("Using 921600 baud.\n");
|
||||
config.baudrate_main = 921600;
|
||||
printf("Using 460800 baud.\n");
|
||||
config.baudrate_main = 460800;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void local_version_information_handler(uint8_t * packet){
|
||||
static void local_version_information_handler(uint8_t *packet)
|
||||
{
|
||||
printf("Local version information:\n");
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Subversion 0x%04x\n", lmp_subversion);
|
||||
printf("- Manufacturer 0x%04x\n", manufacturer);
|
||||
switch (manufacturer){
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
switch (manufacturer)
|
||||
{
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
|
||||
{
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
#ifdef ENABLE_EHCILL
|
||||
printf("eHCILL enabled.\n");
|
||||
printf("eHCILL enabled.\n");
|
||||
#else
|
||||
printf("eHCILL disable.\n");
|
||||
printf("eHCILL disable.\n");
|
||||
#endif
|
||||
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom/Cypress - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semiconductor nRF5 chipset.\n");
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
|
||||
printf("Toshiba - using TC3566x driver.\n");
|
||||
hci_set_chipset(btstack_chipset_tc3566x_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom/Cypress - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semiconductor nRF5 chipset.\n");
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
|
||||
printf("Toshiba - using TC3566x driver.\n");
|
||||
hci_set_chipset(btstack_chipset_tc3566x_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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
|
||||
|
||||
// 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];
|
||||
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);
|
||||
|
||||
// init HCI
|
||||
const btstack_uart_t * uart_driver = btstack_uart_posix_instance();
|
||||
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void*) &config);
|
||||
const btstack_uart_t *uart_driver = btstack_uart_posix_instance();
|
||||
const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void *)&config);
|
||||
|
||||
#ifdef HAVE_PORTAUDIO
|
||||
btstack_audio_sink_set_instance(btstack_audio_portaudio_sink_get_instance());
|
||||
|
@ -277,7 +292,7 @@ int main(int argc, const char * argv[]){
|
|||
// set BD_ADDR for CSR without Flash/unique address
|
||||
// bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
|
||||
// btstack_chipset_csr_set_bd_addr(own_address);
|
||||
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
@ -289,7 +304,7 @@ int main(int argc, const char * argv[]){
|
|||
btstack_main(argc, argv);
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
btstack_run_loop_execute();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -74,30 +74,31 @@
|
|||
#include "btstack_chipset_stlc2500d.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_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
BTSTACK_UART_PARITY_EVEN, // parity
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
|
@ -106,109 +107,121 @@ static void sigint_handler(int param){
|
|||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - led_state;
|
||||
printf("LED State %u\n", led_state);
|
||||
}
|
||||
static void use_fast_uart(void){
|
||||
printf("Using 921600 baud.\n");
|
||||
config.baudrate_main = 921600;
|
||||
static void use_fast_uart(void)
|
||||
{
|
||||
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");
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Revision 0x%04x\n", lmp_subversion);
|
||||
printf("- Manufacturer 0x%04x\n", manufacturer);
|
||||
switch (manufacturer){
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom chipset. Not supported by posix-h5 port, please use port/posix-h5-bcm\n");
|
||||
exit(10);
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
switch (manufacturer)
|
||||
{
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom chipset. Not supported by posix-h5 port, please use port/posix-h5-bcm\n");
|
||||
exit(10);
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6+248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6 + 248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
|
||||
{
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// 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);
|
||||
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);
|
||||
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
|
||||
|
||||
// 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];
|
||||
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);
|
||||
|
||||
// init HCI
|
||||
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);
|
||||
hci_init(transport, (void*) &config);
|
||||
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);
|
||||
hci_init(transport, (void *)&config);
|
||||
|
||||
// set BD_ADDR for CSR without Flash/unique address
|
||||
// bd_addr_t own_address = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
|
||||
|
@ -249,7 +263,7 @@ int main(int argc, const char * argv[]){
|
|||
btstack_main(argc, argv);
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
btstack_run_loop_execute();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -86,14 +86,14 @@
|
|||
|
||||
#define TLV_DB_PATH_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static bd_addr_t local_addr;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static bd_addr_t local_addr;
|
||||
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 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 = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void use_fast_uart(void){
|
||||
printf("Using 921600 baud.\n");
|
||||
config.baudrate_main = 921600;
|
||||
static void use_fast_uart(void)
|
||||
{
|
||||
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");
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Subversion 0x%04x\n", lmp_subversion);
|
||||
printf("- Manufacturer 0x%04x\n", manufacturer);
|
||||
switch (manufacturer){
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
switch (manufacturer)
|
||||
{
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
|
||||
{
|
||||
printf("Error: LMP Subversion does not match initscript! ");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
#ifdef ENABLE_EHCILL
|
||||
printf("eHCILL enabled.\n");
|
||||
printf("eHCILL enabled.\n");
|
||||
#else
|
||||
printf("eHCILL disable.\n");
|
||||
printf("eHCILL disable.\n");
|
||||
#endif
|
||||
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom/Cypress - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom/Cypress - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
gap_local_bd_addr(local_addr);
|
||||
if (using_static_address){
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
return;
|
||||
gap_local_bd_addr(local_addr);
|
||||
if (using_static_address)
|
||||
{
|
||||
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
|
||||
// bd_addr_to_str use ":" which is not allowed in windows file names
|
||||
strcat(tlv_db_path, bd_addr_to_str(local_addr));
|
||||
// bd_addr_to_str use ":" which is not allowed in windows file names
|
||||
strcat(tlv_db_path, bd_addr_to_str(local_addr));
|
||||
#endif
|
||||
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);
|
||||
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
|
||||
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
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6+248] = 0;
|
||||
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);
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6 + 248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
if (is_bcm)
|
||||
{
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
|
||||
{
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
static void sigint_handler(int param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
|
@ -225,15 +238,17 @@ static void sigint_handler(int param){
|
|||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - led_state;
|
||||
printf("LED State %u\n", led_state);
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
|
@ -249,20 +264,20 @@ int main(int argc, char * argv[]){
|
|||
strcpy(pklg_path, "/tmp/hci_dump.pklg");
|
||||
#endif
|
||||
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);
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
|
||||
// init HCI
|
||||
#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";
|
||||
#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
|
||||
#endif
|
||||
const hci_transport_t * transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void*) &config);
|
||||
const hci_transport_t *transport = hci_transport_h4_instance_for_uart(uart_driver);
|
||||
hci_init(transport, (void *)&config);
|
||||
|
||||
#ifdef HAVE_PORTAUDIO
|
||||
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);
|
||||
|
||||
// setup app
|
||||
btstack_main(argc, (const char **) argv);
|
||||
btstack_main(argc, (const char **)argv);
|
||||
|
||||
// enter Qt run loop
|
||||
return a.exec();
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -81,12 +81,12 @@
|
|||
#include "btstack_chipset_bcm_download_firmware.h"
|
||||
#include "btstack_control_raspi.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_SOFTWARE_NO_FLOW,
|
||||
UART_HARDWARE_NO_FLOW,
|
||||
|
@ -97,98 +97,99 @@ typedef enum {
|
|||
static hci_transport_config_uart_t transport_config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
0, // flow control
|
||||
0, // main baudrate
|
||||
0, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
static btstack_uart_config_t uart_config;
|
||||
|
||||
static int main_argc;
|
||||
static const char ** main_argv;
|
||||
static const char **main_argv;
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
#define TLV_DB_PATH_PREFIX "/tmp/btstack_"
|
||||
#define TLV_DB_PATH_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
|
||||
static int raspi_speed_to_baud(speed_t baud)
|
||||
{
|
||||
switch (baud) {
|
||||
case B9600:
|
||||
return 9600;
|
||||
case B19200:
|
||||
return 19200;
|
||||
case B38400:
|
||||
return 38400;
|
||||
case B57600:
|
||||
return 57600;
|
||||
case B115200:
|
||||
return 115200;
|
||||
case B230400:
|
||||
return 230400;
|
||||
case B460800:
|
||||
return 460800;
|
||||
case B500000:
|
||||
return 500000;
|
||||
case B576000:
|
||||
return 576000;
|
||||
case B921600:
|
||||
return 921600;
|
||||
case B1000000:
|
||||
return 1000000;
|
||||
case B1152000:
|
||||
return 1152000;
|
||||
case B1500000:
|
||||
return 1500000;
|
||||
case B2000000:
|
||||
return 2000000;
|
||||
case B2500000:
|
||||
return 2500000;
|
||||
case B3000000:
|
||||
return 3000000;
|
||||
case B3500000:
|
||||
return 3500000;
|
||||
case B4000000:
|
||||
return 4000000;
|
||||
default:
|
||||
return -1;
|
||||
switch (baud)
|
||||
{
|
||||
case B9600:
|
||||
return 9600;
|
||||
case B19200:
|
||||
return 19200;
|
||||
case B38400:
|
||||
return 38400;
|
||||
case B57600:
|
||||
return 57600;
|
||||
case B115200:
|
||||
return 115200;
|
||||
case B230400:
|
||||
return 230400;
|
||||
case B460800:
|
||||
return 460800;
|
||||
case B500000:
|
||||
return 500000;
|
||||
case B576000:
|
||||
return 576000;
|
||||
case B460800:
|
||||
return 460800;
|
||||
case B1000000:
|
||||
return 1000000;
|
||||
case B1152000:
|
||||
return 1152000;
|
||||
case B1500000:
|
||||
return 1500000;
|
||||
case B2000000:
|
||||
return 2000000;
|
||||
case B2500000:
|
||||
return 2500000;
|
||||
case B3000000:
|
||||
return 3000000;
|
||||
case B3500000:
|
||||
return 3500000;
|
||||
case B4000000:
|
||||
return 4000000;
|
||||
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
|
||||
int fd = open( tc->device_name, O_RDONLY );
|
||||
if( fd < 0 )
|
||||
int fd = open(tc->device_name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror( "can't open serial port" );
|
||||
perror("can't open serial port");
|
||||
return;
|
||||
}
|
||||
struct termios tios;
|
||||
tcgetattr( fd, &tios );
|
||||
close( fd );
|
||||
tcgetattr(fd, &tios);
|
||||
close(fd);
|
||||
|
||||
speed_t ospeed = cfgetospeed( &tios );
|
||||
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" );
|
||||
speed_t ospeed = cfgetospeed(&tios);
|
||||
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");
|
||||
|
||||
// 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->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);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
|
@ -197,205 +198,240 @@ static void sigint_handler(int param){
|
|||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - 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;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
// setup TLV
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
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
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
hci_set_link_key_db(btstack_link_key_db_tlv_get_instance(tlv_impl, &tlv_context));
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6+248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6 + 248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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" );
|
||||
if( fd == NULL ){
|
||||
fprintf(stderr, "can't read serial number, %s\n", strerror( errno ) );
|
||||
FILE *fd = fopen("/proc/device-tree/serial-number", "r");
|
||||
if (fd == NULL)
|
||||
{
|
||||
fprintf(stderr, "can't read serial number, %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fscanf( fd, "%*08x" "%*02x" "%02" SCNx8 "%02" SCNx8 "%02" SCNx8, &addr[3], &addr[4], &addr[5] );
|
||||
fclose( fd );
|
||||
fscanf(fd, "%*08x"
|
||||
"%*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[3] ^= 0xaa; addr[4] ^= 0xaa; addr[5] ^= 0xaa;
|
||||
addr[0] = 0xb8;
|
||||
addr[1] = 0x27;
|
||||
addr[2] = 0xeb;
|
||||
addr[3] ^= 0xaa;
|
||||
addr[4] ^= 0xaa;
|
||||
addr[5] ^= 0xaa;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// see https://github.com/RPi-Distro/pi-bluetooth/blob/master/usr/bin/btuart
|
||||
// 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};
|
||||
FILE *fd = fopen("/proc/device-tree/aliases/uart0", "r");
|
||||
if (fd == NULL)
|
||||
return UART_INVALID;
|
||||
fscanf(fd, "%20s", deviceUart0);
|
||||
fclose(fd);
|
||||
|
||||
uint8_t deviceSerial1[21] = {0};
|
||||
fd = fopen("/proc/device-tree/aliases/serial1", "r");
|
||||
if (fd == NULL)
|
||||
return UART_INVALID;
|
||||
fscanf(fd, "%20s", deviceSerial1);
|
||||
fclose(fd);
|
||||
|
||||
uint8_t deviceUart0[21] = { 0 };
|
||||
FILE *fd = fopen( "/proc/device-tree/aliases/uart0", "r" );
|
||||
if( fd == NULL ) return UART_INVALID;
|
||||
fscanf( fd, "%20s", deviceUart0 );
|
||||
fclose( fd );
|
||||
|
||||
uint8_t deviceSerial1[21] = { 0 };
|
||||
fd = fopen( "/proc/device-tree/aliases/serial1", "r" );
|
||||
if( fd == NULL ) return UART_INVALID;
|
||||
fscanf( fd, "%20s", deviceSerial1 );
|
||||
fclose( fd );
|
||||
|
||||
// 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
|
||||
size_t count = 0;
|
||||
uint8_t buf[16];
|
||||
fd = fopen( "/proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm,pins", "r" );
|
||||
if( fd == NULL ) return UART_INVALID;
|
||||
count = fread( buf, 1, 16, fd );
|
||||
fclose( fd );
|
||||
fd = fopen("/proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm,pins", "r");
|
||||
if (fd == NULL)
|
||||
return UART_INVALID;
|
||||
count = fread(buf, 1, 16, fd);
|
||||
fclose(fd);
|
||||
|
||||
// contains assigned pins
|
||||
int pins = count / 4;
|
||||
if( pins == 4 ){
|
||||
if (pins == 4)
|
||||
{
|
||||
return UART_HARDWARE_FLOW;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return UART_HARDWARE_NO_FLOW;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return UART_SOFTWARE_NO_FLOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void phase2(int status);
|
||||
int main(int argc, const char * argv[]){
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
|
||||
/// GET STARTED with BTstack ///
|
||||
btstack_memory_init();
|
||||
|
||||
// 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);
|
||||
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);
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
|
||||
// setup run loop
|
||||
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
|
||||
|
||||
|
||||
// pick serial port and configure uart block driver
|
||||
transport_config.device_name = "/dev/serial1";
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
// set UART config based on raspi Bluetooth UART type
|
||||
int bt_reg_en_pin = -1;
|
||||
bool power_cycle = true;
|
||||
switch (raspi_get_bluetooth_uart_type()){
|
||||
case UART_INVALID:
|
||||
fprintf(stderr, "can't verify HW uart, %s\n", strerror( errno ) );
|
||||
return -1;
|
||||
case UART_SOFTWARE_NO_FLOW:
|
||||
// ??
|
||||
bt_reg_en_pin = 128;
|
||||
switch (raspi_get_bluetooth_uart_type())
|
||||
{
|
||||
case UART_INVALID:
|
||||
fprintf(stderr, "can't verify HW uart, %s\n", strerror(errno));
|
||||
return -1;
|
||||
case UART_SOFTWARE_NO_FLOW:
|
||||
// ??
|
||||
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.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 = 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_reg_en_pin = 129;
|
||||
transport_config.baudrate_main = 3000000;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CONTROLLER_WARM_BOOT
|
||||
power_cycle = false;
|
||||
power_cycle = false;
|
||||
#else
|
||||
// warn about power cycle on devices with shared reg_en pins
|
||||
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");
|
||||
}
|
||||
// warn about power cycle on devices with shared reg_en pins
|
||||
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");
|
||||
}
|
||||
#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
|
||||
const btstack_chipset_t * chipset = btstack_chipset_bcm_instance();
|
||||
const btstack_chipset_t *chipset = btstack_chipset_bcm_instance();
|
||||
chipset->init(&transport_config);
|
||||
|
||||
// set path to firmware files
|
||||
btstack_chipset_bcm_set_hcd_folder_path("/lib/firmware/brcm");
|
||||
|
||||
// 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
|
||||
uart_config.baudrate = transport_config.baudrate_init;
|
||||
uart_config.baudrate = transport_config.baudrate_init;
|
||||
uart_config.flowcontrol = transport_config.flowcontrol;
|
||||
uart_config.device_name = transport_config.device_name;
|
||||
uart_driver->init(&uart_config);
|
||||
|
||||
// HW with FlowControl -> we can use regular h4 mode
|
||||
const hci_transport_t * transport;
|
||||
if (transport_config.flowcontrol){
|
||||
const hci_transport_t *transport;
|
||||
if (transport_config.flowcontrol)
|
||||
{
|
||||
transport = hci_transport_h4_instance(uart_driver);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
transport = hci_transport_h5_instance(uart_driver);
|
||||
}
|
||||
|
||||
// setup HCI (to be able to use bcm chipset driver)
|
||||
hci_init(transport, (void*) &transport_config);
|
||||
hci_set_bd_addr( addr );
|
||||
hci_init(transport, (void *)&transport_config);
|
||||
hci_set_bd_addr(addr);
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
|
||||
// inform about BTstack state
|
||||
|
@ -409,26 +445,30 @@ int main(int argc, const char * argv[]){
|
|||
main_argv = argv;
|
||||
|
||||
// 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_t *control = btstack_control_raspi_get_instance();
|
||||
control->init(NULL);
|
||||
control->off();
|
||||
usleep( 100000 );
|
||||
usleep(100000);
|
||||
control->on();
|
||||
}
|
||||
|
||||
if (transport_config.flowcontrol){
|
||||
if (transport_config.flowcontrol)
|
||||
{
|
||||
|
||||
// re-use current terminal speed (if there was no power cycle)
|
||||
if (!power_cycle){
|
||||
raspi_get_terminal_params( &transport_config );
|
||||
if (!power_cycle)
|
||||
{
|
||||
raspi_get_terminal_params(&transport_config);
|
||||
}
|
||||
|
||||
// with flowcontrol, we use h4 and are done
|
||||
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
|
||||
btstack_chipset_bcm_set_device_name("BCM43430A1");
|
||||
|
@ -441,13 +481,15 @@ int main(int argc, const char * argv[]){
|
|||
}
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
btstack_run_loop_execute();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void phase2(int status){
|
||||
static void phase2(int status)
|
||||
{
|
||||
|
||||
if (status){
|
||||
if (status)
|
||||
{
|
||||
printf("Download firmware failed\n");
|
||||
return;
|
||||
}
|
||||
|
@ -457,4 +499,3 @@ static void phase2(int status){
|
|||
// setup app
|
||||
btstack_main(main_argc, main_argv);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -70,14 +70,14 @@
|
|||
#include "btstack_chipset_stlc2500d.h"
|
||||
#include "btstack_chipset_tc3566x.h"
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
static void local_version_information_handler(uint8_t * packet);
|
||||
int btstack_main(int argc, const char *argv[]);
|
||||
static void local_version_information_handler(uint8_t *packet);
|
||||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -88,16 +88,18 @@ static int led_state = 0;
|
|||
#define TLV_DB_PATH_PREFIX "btstack_"
|
||||
#define TLV_DB_PATH_POSTFIX ".tlv"
|
||||
static char tlv_db_path[100];
|
||||
static const btstack_tlv_t * tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static bd_addr_t local_addr;
|
||||
static const btstack_tlv_t *tlv_impl;
|
||||
static btstack_tlv_posix_t tlv_context;
|
||||
static bd_addr_t local_addr;
|
||||
|
||||
void hal_led_toggle(void){
|
||||
void hal_led_toggle(void)
|
||||
{
|
||||
led_state = 1 - led_state;
|
||||
printf("LED State %u\n", led_state);
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
static void sigint_handler(int param)
|
||||
{
|
||||
UNUSED(param);
|
||||
|
||||
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 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;
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
strcat(tlv_db_path, bd_addr_to_str(local_addr));
|
||||
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX);
|
||||
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path);
|
||||
btstack_tlv_set_instance(tlv_impl, &tlv_context);
|
||||
if (packet_type != HCI_EVENT_PACKET)
|
||||
return;
|
||||
switch (hci_event_packet_get_type(packet))
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING)
|
||||
break;
|
||||
gap_local_bd_addr(addr);
|
||||
printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
|
||||
strcpy(tlv_db_path, TLV_DB_PATH_PREFIX);
|
||||
strcat(tlv_db_path, bd_addr_to_str(local_addr));
|
||||
strcat(tlv_db_path, TLV_DB_PATH_POSTFIX);
|
||||
tlv_impl = btstack_tlv_posix_init_instance(&tlv_context, tlv_db_path);
|
||||
btstack_tlv_set_instance(tlv_impl, &tlv_context);
|
||||
#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
|
||||
#ifdef ENABLE_BLE
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
le_device_db_tlv_configure(tlv_impl, &tlv_context);
|
||||
#endif
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6+248] = 0;
|
||||
printf("Local name: %s\n", &packet[6]);
|
||||
if (is_bcm){
|
||||
btstack_chipset_bcm_set_device_name((const char *)&packet[6]);
|
||||
}
|
||||
printf("BTstack up and running at %s\n", bd_addr_to_str(addr));
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
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
|
||||
packet[6 + 248] = 0;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information))
|
||||
{
|
||||
local_version_information_handler(packet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void use_fast_uart(void){
|
||||
printf("Using 921600 baud.\n");
|
||||
config.baudrate_main = 921600;
|
||||
static void use_fast_uart(void)
|
||||
{
|
||||
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");
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t hci_version = packet[6];
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 7);
|
||||
uint16_t lmp_version = packet[9];
|
||||
uint16_t manufacturer = little_endian_read_16(packet, 10);
|
||||
uint16_t lmp_subversion = little_endian_read_16(packet, 12);
|
||||
printf("- HCI Version 0x%04x\n", hci_version);
|
||||
printf("- HCI Revision 0x%04x\n", hci_revision);
|
||||
printf("- LMP Version 0x%04x\n", lmp_version);
|
||||
printf("- LMP Revision 0x%04x\n", lmp_subversion);
|
||||
printf("- Manufacturer 0x%04x\n", manufacturer);
|
||||
switch (manufacturer){
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
|
||||
printf("Error: LMP Subversion does not match initscript!");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
switch (manufacturer)
|
||||
{
|
||||
case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset, Build ID: %u.\n", hci_revision);
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC:
|
||||
printf("Texas Instruments - CC256x compatible chipset.\n");
|
||||
if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion())
|
||||
{
|
||||
printf("Error: LMP Subversion does not match initscript!");
|
||||
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");
|
||||
exit(10);
|
||||
}
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_cc256x_instance());
|
||||
#ifdef ENABLE_EHCILL
|
||||
printf("eHCILL enabled.\n");
|
||||
printf("eHCILL enabled.\n");
|
||||
#else
|
||||
printf("eHCILL disable.\n");
|
||||
printf("eHCILL disable.\n");
|
||||
#endif
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semiconductor nRF5 chipset.\n");
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
|
||||
printf("Toshiba - using TC3566x driver.\n");
|
||||
hci_set_chipset(btstack_chipset_tc3566x_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:
|
||||
printf("Broadcom - using BCM driver.\n");
|
||||
hci_set_chipset(btstack_chipset_bcm_instance());
|
||||
use_fast_uart();
|
||||
is_bcm = 1;
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semiconductor nRF5 chipset.\n");
|
||||
break;
|
||||
case BLUETOOTH_COMPANY_ID_TOSHIBA_CORP:
|
||||
printf("Toshiba - using TC3566x driver.\n");
|
||||
hci_set_chipset(btstack_chipset_tc3566x_instance());
|
||||
use_fast_uart();
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]){
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
printf("BTstack on windows booting up\n");
|
||||
|
||||
/// 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());
|
||||
|
||||
// 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);
|
||||
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);
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
|
||||
|
@ -240,17 +255,18 @@ int main(int argc, const char * argv[]){
|
|||
config.device_name = "\\\\.\\COM7";
|
||||
|
||||
// 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];
|
||||
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);
|
||||
|
||||
// init HCI
|
||||
const btstack_uart_block_t * uart_driver = btstack_uart_block_windows_instance();
|
||||
const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
|
||||
hci_init(transport, (void*) &config);
|
||||
const btstack_uart_block_t *uart_driver = btstack_uart_block_windows_instance();
|
||||
const hci_transport_t *transport = hci_transport_h4_instance(uart_driver);
|
||||
hci_init(transport, (void *)&config);
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -48,9 +48,9 @@
|
|||
#include "btstack_run_loop.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef __APPLE__
|
||||
|
@ -59,51 +59,56 @@
|
|||
#endif
|
||||
|
||||
// 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
|
||||
static btstack_data_source_t transport_data_source;
|
||||
|
||||
// block write
|
||||
static int write_bytes_len;
|
||||
static const uint8_t * write_bytes_data;
|
||||
static int write_bytes_len;
|
||||
static const uint8_t *write_bytes_data;
|
||||
|
||||
// block read
|
||||
static uint16_t read_bytes_len;
|
||||
static uint8_t * read_bytes_data;
|
||||
static uint16_t read_bytes_len;
|
||||
static uint8_t *read_bytes_data;
|
||||
|
||||
// callbacks
|
||||
static void (*block_sent)(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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btstack_uart_posix_process_write(btstack_data_source_t *ds) {
|
||||
|
||||
if (write_bytes_len == 0) return;
|
||||
static void btstack_uart_posix_process_write(btstack_data_source_t *ds)
|
||||
{
|
||||
|
||||
if (write_bytes_len == 0)
|
||||
return;
|
||||
|
||||
uint32_t start = btstack_run_loop_get_time_ms();
|
||||
|
||||
// write up to write_bytes_len to fd
|
||||
int bytes_written = (int) write(ds->source.fd, write_bytes_data, write_bytes_len);
|
||||
if (bytes_written < 0) {
|
||||
int bytes_written = (int)write(ds->source.fd, write_bytes_data, write_bytes_len);
|
||||
if (bytes_written < 0)
|
||||
{
|
||||
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -111,55 +116,66 @@ static void btstack_uart_posix_process_write(btstack_data_source_t *ds) {
|
|||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
|
||||
// notify done
|
||||
if (block_sent){
|
||||
if (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");
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
}
|
||||
|
||||
uint32_t start = btstack_run_loop_get_time_ms();
|
||||
|
||||
|
||||
// read up to bytes_to_read data in
|
||||
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);
|
||||
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);
|
||||
}
|
||||
if (bytes_read < 0) return;
|
||||
|
||||
read_bytes_len -= bytes_read;
|
||||
read_bytes_data += bytes_read;
|
||||
if (read_bytes_len > 0) return;
|
||||
|
||||
if (bytes_read < 0)
|
||||
return;
|
||||
|
||||
read_bytes_len -= bytes_read;
|
||||
read_bytes_data += bytes_read;
|
||||
if (read_bytes_len > 0)
|
||||
return;
|
||||
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
|
||||
if (block_received){
|
||||
if (block_received)
|
||||
{
|
||||
block_received();
|
||||
}
|
||||
}
|
||||
|
||||
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){
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
btstack_uart_posix_process_read(ds);
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
btstack_uart_posix_process_write(ds);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
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)
|
||||
{
|
||||
case DATA_SOURCE_CALLBACK_READ:
|
||||
btstack_uart_posix_process_read(ds);
|
||||
break;
|
||||
case DATA_SOURCE_CALLBACK_WRITE:
|
||||
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);
|
||||
#if 0
|
||||
int fd = transport_data_source.source.fd;
|
||||
|
@ -199,16 +215,16 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
|||
#ifdef B460800
|
||||
case 460800: brate=B460800; break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600: brate=B921600; break;
|
||||
#ifdef B460800
|
||||
case 460800: brate=B460800; break;
|
||||
#endif
|
||||
|
||||
// Hacks to switch to 2/3 mbps on FTDI FT232 chipsets
|
||||
// requires special config in Info.plist or Registry
|
||||
case 2000000:
|
||||
case 2000000:
|
||||
#if defined(HAVE_POSIX_B300_MAPPED_TO_2000000)
|
||||
log_info("hci_transport_posix: using B300 for 2 mbps");
|
||||
brate=B300;
|
||||
brate=B300;
|
||||
#elif defined(HAVE_POSIX_B1200_MAPPED_TO_2000000)
|
||||
log_info("hci_transport_posix: using B1200 for 2 mbps");
|
||||
brate=B1200;
|
||||
|
@ -238,105 +254,123 @@ static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){
|
||||
if (parity){
|
||||
static void btstack_uart_posix_set_parity_option(struct termios *toptions, int parity)
|
||||
{
|
||||
if (parity)
|
||||
{
|
||||
// enable even parity
|
||||
toptions->c_cflag |= PARENB;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// disable even parity
|
||||
toptions->c_cflag &= ~PARENB;
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){
|
||||
if (flowcontrol) {
|
||||
static void btstack_uart_posix_set_flowcontrol_option(struct termios *toptions, int flowcontrol)
|
||||
{
|
||||
if (flowcontrol)
|
||||
{
|
||||
// with flow control
|
||||
toptions->c_cflag |= CRTSCTS;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// no flow control
|
||||
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;
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
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 int flowcontrol = uart_config->flowcontrol;
|
||||
const uint32_t baudrate = uart_config->baudrate;
|
||||
const char *device_name = uart_config->device_name;
|
||||
const int flowcontrol = uart_config->flowcontrol;
|
||||
const uint32_t baudrate = uart_config->baudrate;
|
||||
|
||||
struct termios toptions;
|
||||
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
|
||||
int fd = open(device_name, flags);
|
||||
if (fd == -1) {
|
||||
if (fd == -1)
|
||||
{
|
||||
log_error("posix_open: Unable to open port %s", device_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0) {
|
||||
|
||||
if (tcgetattr(fd, &toptions) < 0)
|
||||
{
|
||||
log_error("posix_open: Couldn't get term attributes");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfmakeraw(&toptions); // make raw
|
||||
|
||||
cfmakeraw(&toptions); // make raw
|
||||
|
||||
// 8N1
|
||||
toptions.c_cflag &= ~CSTOPB;
|
||||
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
|
||||
|
||||
|
||||
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VMIN] = 1;
|
||||
toptions.c_cc[VTIME] = 0;
|
||||
|
||||
|
||||
// no parity
|
||||
btstack_uart_posix_set_parity_option(&toptions, 0);
|
||||
|
||||
// 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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store fd in data source
|
||||
transport_data_source.source.fd = fd;
|
||||
|
||||
|
||||
// also set baudrate
|
||||
if (btstack_uart_posix_set_baudrate(baudrate) < 0){
|
||||
if (btstack_uart_posix_set_baudrate(baudrate) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -349,38 +383,43 @@ static int btstack_uart_posix_open(void){
|
|||
usleep(100000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int btstack_uart_posix_close_new(void){
|
||||
static int btstack_uart_posix_close_new(void)
|
||||
{
|
||||
|
||||
// first remove run loop handler
|
||||
btstack_run_loop_remove_data_source(&transport_data_source);
|
||||
|
||||
// then close device
|
||||
|
||||
// then close device
|
||||
close(transport_data_source.source.fd);
|
||||
transport_data_source.source.fd = -1;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
write_bytes_data = data;
|
||||
write_bytes_len = size;
|
||||
write_bytes_len = size;
|
||||
|
||||
// go
|
||||
// btstack_uart_posix_process_write(&transport_data_source);
|
||||
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_len = len;
|
||||
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 = {
|
||||
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
|
||||
/* int (*open)(void); */ &btstack_uart_posix_open,
|
||||
/* int (*close)(void); */ &btstack_uart_posix_close_new,
|
||||
/* 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,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
|
||||
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
|
||||
/* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol,
|
||||
/* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block,
|
||||
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
|
||||
/* int (*open)(void); */ &btstack_uart_posix_open,
|
||||
/* int (*close)(void); */ &btstack_uart_posix_close_new,
|
||||
/* 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,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
|
||||
/* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
|
||||
/* 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 (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
|
||||
/* int (*get_supported_sleep_modes); */ NULL,
|
||||
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
|
||||
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
/* int (*get_supported_sleep_modes); */ NULL,
|
||||
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
|
||||
/* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const btstack_uart_block_t * btstack_uart_posix_instance(void){
|
||||
return &btstack_uart_posix;
|
||||
const btstack_uart_block_t *btstack_uart_posix_instance(void)
|
||||
{
|
||||
return &btstack_uart_posix;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
@ -86,7 +86,7 @@ static void local_version_information_handler(uint8_t *packet);
|
|||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
921600,
|
||||
460800,
|
||||
0, // main baudrate
|
||||
0, // flow control
|
||||
NULL,
|
||||
|
|
|
@ -67,11 +67,11 @@ class ESP32BTDriver:
|
|||
serial_bridge = None
|
||||
serial_bridge_name = None
|
||||
serial_hci_thread = None
|
||||
serial_baudrate = 921600
|
||||
serial_baudrate = 460800
|
||||
serial_portname = None
|
||||
|
||||
# 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):
|
||||
|
||||
self.serial_portname = port_name
|
||||
|
|
Loading…
Reference in a new issue