mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 10:21:49 +00:00
Merge branch 'develop' into a2dp
This commit is contained in:
commit
cab4a0b539
@ -61,7 +61,9 @@ Status | Platform
|
||||
-------------- | ------
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-posix-h4-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-posix-h4-develop) | posix: Unix-based system connected to Bluetooth module via serial port
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-libusb-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-libusb-develop) | libusb: Unix-based system with dedicated USB Bluetooth dongle
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-daemon-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-daemon-develop) | daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-daemon-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/.. | windows-h4: Win32-based system connected to Bluetooth module via serial port
|
||||
.. | windwos-winusb: Win32-based system with dedicated USB Bluetooth dongle
|
||||
port-daemon-develop) | daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=java-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/java-develop) | java: Java wrapper for daemon
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-ios-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-ios-develop) | iOS: daemon for iOS jailbreak devices, C client-server API
|
||||
[<img src="http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=port-mtk-develop">](https://buildbot.bluekitchen-gmbh.com/btstack/builders/port-mtk-develop) | mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API
|
||||
|
@ -58,6 +58,10 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
static int send_download_command;
|
||||
static uint32_t init_script_offset;
|
||||
|
||||
@ -134,8 +138,11 @@ static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
|
||||
close(hcd_fd);
|
||||
|
||||
// wait for firmware patch to be applied - shorter delay possible
|
||||
#ifdef _WIN32
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
|
||||
#endif
|
||||
return BTSTACK_CHIPSET_DONE;
|
||||
}
|
||||
if (res < 0){
|
||||
|
@ -1,33 +1,18 @@
|
||||
|
||||
## General Tools
|
||||
|
||||
Most ports use a regular Makefile to build the examples.
|
||||
|
||||
On Unix-based systems, git, make, and Python are usually installed. If
|
||||
not, use the system’s packet manager to install them.
|
||||
|
||||
On Windows, you need to manually install and configure GNU Make, Python,
|
||||
and optionally git :
|
||||
On Windows, there is no packet manager, but it's easy to download and install all requires development packets quickly by hand. You'll need:
|
||||
|
||||
- [GNU Make](http://gnuwin32.sourceforge.net/packages/make.htm)
|
||||
for Windows: Add its bin folder to the Windows Path in Environment
|
||||
Variables. The bin folder is where make.exe resides, and it’s
|
||||
usually located in [C:\Program Files\GnuWin32\bin]().
|
||||
|
||||
- [Python](http://www.python.org/getit/) for
|
||||
Windows: Add Python installation folder to the Windows Path in
|
||||
Environment Variables.
|
||||
|
||||
### Adding paths to the Windows Path variable {#sec:windowsPathQuickStart}
|
||||
|
||||
- Go to: Control Panel->System->Advanced tab->Environment Variables.
|
||||
|
||||
- The top part contains a list of User variables.
|
||||
|
||||
- Click on the Path variable and then click edit.
|
||||
|
||||
- Go to the end of the line, then append the path to the list, for
|
||||
example, [C:\Program Files\GnuWin32\bin]() for GNU Make.
|
||||
|
||||
- Ensure that there is a semicolon before and after [C:\Program Files\GnuWin32\bin]().
|
||||
- [Python](http://www.python.org/getit/) for Windows. When using the official installer, please confirm adding Python to the Windows Path.
|
||||
- [MSYS2](https://msys2.github.io) is used to provide the bash shell and most standard POSIX command line tools.
|
||||
- [MinGW64](https://mingw-w64.org/doku.php) GCC for Windows 64 & 32 bits incl. make. To install with MYS2: pacman -S mingw-w64-x86_64-gcc
|
||||
- [git](https://git-scm.com) is used to download BTstack source code. To install with MYS2: pacman -S git
|
||||
- [winpty](https://github.com/rprichard/winpty) a wrapper to allow for console input when running in msys2: To install with MYS2: pacman -S winpty
|
||||
|
||||
## Getting BTstack from GitHub
|
||||
|
||||
@ -35,7 +20,6 @@ Use git to clone the latest version:
|
||||
|
||||
git clone https://github.com/bluekitchen/btstack.git
|
||||
|
||||
|
||||
Alternatively, you can download it as a ZIP archive from
|
||||
[BTstack’s page](https://github.com/bluekitchen/btstack/archive/master.zip) on
|
||||
GitHub.
|
||||
@ -69,7 +53,7 @@ setups, toolchains, programmers, and init scripts.
|
||||
### libusb
|
||||
|
||||
The quickest way to try BTstack is on a Linux or OS X system with an
|
||||
additional USB Bluetooth module. The Makefile [platforms/libusb]() in requires
|
||||
additional USB Bluetooth module. The Makefile [port/libusb]() in requires
|
||||
[pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/)
|
||||
and [libusb-1.0](http://libusb.info) or higher to be
|
||||
installed.
|
||||
@ -82,28 +66,22 @@ Bluetooth. For this, execute:
|
||||
|
||||
sudo nvram bluetoothHostControllerSwitchBehavior=never
|
||||
|
||||
It’s also possible to run the examples on Win32 systems. For this:
|
||||
## Windows-WinUSB
|
||||
|
||||
- Install [MSYS](http://www.mingw.org/wiki/msys) and
|
||||
[MINGW32](http://www.mingw.org) using the MINGW installer
|
||||
While libusb basically also works on Windows, we recommend to use the Windows-WinUSB port that uses a native run loop and the native WinUSB API to access the USB Bluetooth dongle.
|
||||
|
||||
- Compile and install libusb-1.0.19 to [/usr/local/]() in msys command
|
||||
shell
|
||||
For libusb or WinUSB, you need to install a special device driver to make the USB dongle accessible to user space. It works like this:
|
||||
|
||||
- Setup a USB Bluetooth dongle for use with libusb-1.0:
|
||||
- Start [Zadig](http://zadig.akeo.ie)
|
||||
- Select Options -> “List all devices”
|
||||
- Select USB Bluetooth dongle in the big pull down list
|
||||
- Select WinUSB (libusb) in the right pull pull down list
|
||||
- Select “Replace Driver”
|
||||
|
||||
- Start [Zadig](http://zadig.akeo.ie)
|
||||
When running the examples in the MSYS2, the console input (via btstack_stdin_support) doesn't work. It works in the older MSYS and also the regular
|
||||
CMD.exe environment. Another option is to install WinPTY and then start the example via WinPTY like this:
|
||||
|
||||
- Select Options -> “List all devices”
|
||||
|
||||
- Select USB Bluetooth dongle in the big pull down list
|
||||
|
||||
- Select WinUSB (libusb) in the right pull pull down list
|
||||
|
||||
- Select “Replace Driver”
|
||||
|
||||
Now, you can run the examples from the *msys* shell the same way as on
|
||||
Linux/OS X.
|
||||
$ winpty ./hfp_hf_demo.exe
|
||||
|
||||
### Texas Instruments MSP430-based boards
|
||||
|
||||
|
@ -68,8 +68,8 @@ const char hfp_ag_service_name[] = "BTstack HFP AG Test";
|
||||
static bd_addr_t device_addr;
|
||||
static const char * device_addr_string = "00:15:83:5F:9D:46";
|
||||
|
||||
// static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC};
|
||||
static uint8_t codecs[] = {HFP_CODEC_CVSD};
|
||||
static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC};
|
||||
// static uint8_t codecs[] = {HFP_CODEC_CVSD};
|
||||
static uint8_t negotiated_codec = HFP_CODEC_CVSD;
|
||||
|
||||
static hci_con_handle_t acl_handle = -1;
|
||||
|
@ -45,7 +45,11 @@
|
||||
|
||||
#include "btstack_util.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define LINK_KEY_PATH ""
|
||||
#else
|
||||
#define LINK_KEY_PATH "/tmp/"
|
||||
#endif
|
||||
#define LINK_KEY_PREFIX "btstack_at_"
|
||||
#define LINK_KEY_FOR "_link_key_for_"
|
||||
#define LINK_KEY_SUFFIX ".txt"
|
||||
|
@ -44,52 +44,34 @@
|
||||
|
||||
#include "stdin_support.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
// From MSDN:
|
||||
// __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64.
|
||||
// Otherwise, undefined.
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <conio.h> //provides non standard getch() function
|
||||
#include <signal.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
static btstack_data_source_t stdin_source;
|
||||
static int activated = 0;
|
||||
|
||||
void btstack_stdin_setup(void (*stdin_process)(btstack_data_source_t *_ds, btstack_data_source_callback_type_t callback_type)){
|
||||
#ifdef _WIN32
|
||||
static HANDLE stdin_reader_thread_handle;
|
||||
static char key_read_buffer;
|
||||
static HANDLE key_processed_handle;
|
||||
|
||||
#ifndef _WIN32
|
||||
struct termios term = {0};
|
||||
if (tcgetattr(0, &term) < 0)
|
||||
perror("tcsetattr()");
|
||||
term.c_lflag &= ~ICANON;
|
||||
term.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(0, TCSANOW, &term) < 0) {
|
||||
perror("tcsetattr ICANON");
|
||||
static WINAPI DWORD stdin_reader_thread_process(void * p){
|
||||
while (1){
|
||||
key_read_buffer = getch();
|
||||
SignalObjectAndWait(stdin_source.handle , key_processed_handle, INFINITE, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
btstack_run_loop_set_data_source_fd(&stdin_source, 0); // stdin
|
||||
btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process);
|
||||
btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ);
|
||||
btstack_run_loop_add_data_source(&stdin_source);
|
||||
|
||||
activated = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btstack_stdin_reset(void){
|
||||
if (!activated) return;
|
||||
activated = 0;
|
||||
|
||||
btstack_run_loop_remove_data_source(&stdin_source);
|
||||
|
||||
#ifndef _WIN32
|
||||
struct termios term = {0};
|
||||
if (tcgetattr(0, &term) < 0){
|
||||
perror("tcsetattr()");
|
||||
}
|
||||
term.c_lflag |= ICANON;
|
||||
term.c_lflag |= ECHO;
|
||||
if (tcsetattr(0, TCSANOW, &term) < 0){
|
||||
perror("tcsetattr ICANON");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int getstring(char *line, int size)
|
||||
@ -114,10 +96,87 @@ static int getstring(char *line, int size)
|
||||
}
|
||||
#endif
|
||||
|
||||
// read single byte after data source callback was triggered
|
||||
char btstack_stdin_read(void){
|
||||
char buffer;
|
||||
read(stdin_source.fd, &buffer, 1);
|
||||
return buffer;
|
||||
void btstack_stdin_setup(void (*stdin_process)(btstack_data_source_t *_ds, btstack_data_source_callback_type_t callback_type)){
|
||||
|
||||
if (activated) return;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// asynchronous io on stdin via OVERLAPPED seems to be problematic.
|
||||
|
||||
// Use separate thread and event objects instead
|
||||
stdin_source.handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
key_processed_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
// default attributes, default stack size, proc, args, start immediately, don't care for thread id
|
||||
stdin_reader_thread_handle = CreateThread(NULL, 0, &stdin_reader_thread_process, NULL, 0, NULL);
|
||||
|
||||
#else
|
||||
// disable line buffering
|
||||
struct termios term = {0};
|
||||
if (tcgetattr(0, &term) < 0)
|
||||
perror("tcsetattr()");
|
||||
term.c_lflag &= ~ICANON;
|
||||
term.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(0, TCSANOW, &term) < 0) {
|
||||
perror("tcsetattr ICANON");
|
||||
}
|
||||
|
||||
btstack_run_loop_set_data_source_fd(&stdin_source, 0); // stdin
|
||||
#endif
|
||||
|
||||
btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ);
|
||||
btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process);
|
||||
btstack_run_loop_add_data_source(&stdin_source);
|
||||
|
||||
activated = 1;
|
||||
}
|
||||
|
||||
void btstack_stdin_reset(void){
|
||||
if (!activated) return;
|
||||
activated = 0;
|
||||
|
||||
btstack_run_loop_remove_data_source(&stdin_source);
|
||||
|
||||
#ifdef _WIN32
|
||||
// shutdown thread
|
||||
TerminateThread(stdin_reader_thread_handle, 0);
|
||||
WaitForSingleObject(stdin_reader_thread_handle, INFINITE);
|
||||
CloseHandle(stdin_reader_thread_handle);
|
||||
|
||||
// free events
|
||||
CloseHandle(stdin_source.handle);
|
||||
CloseHandle(key_processed_handle);
|
||||
#else
|
||||
struct termios term = {0};
|
||||
if (tcgetattr(0, &term) < 0){
|
||||
perror("tcsetattr()");
|
||||
}
|
||||
term.c_lflag |= ICANON;
|
||||
term.c_lflag |= ECHO;
|
||||
if (tcsetattr(0, TCSANOW, &term) < 0){
|
||||
perror("tcsetattr ICANON");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// read single byte after data source callback was triggered
|
||||
char btstack_stdin_read(void){
|
||||
char data;
|
||||
#ifdef _WIN32
|
||||
|
||||
// raise SIGINT for CTRL-c on main thread
|
||||
if (key_read_buffer == 0x03){
|
||||
raise(SIGINT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = key_read_buffer;
|
||||
SetEvent(key_processed_handle);
|
||||
|
||||
#else
|
||||
read(stdin_source.fd, &data, 1);
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
266
platform/windows/btstack_run_loop_windows.c
Normal file
266
platform/windows/btstack_run_loop_windows.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_run_loop_windows.c
|
||||
*/
|
||||
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_run_loop_windows.h"
|
||||
#include "btstack_linked_list.h"
|
||||
#include "btstack_debug.h"
|
||||
#include <Windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static void btstack_run_loop_windows_dump_timer(void);
|
||||
|
||||
// the run loop
|
||||
static btstack_linked_list_t data_sources;
|
||||
static int data_sources_modified;
|
||||
static btstack_linked_list_t timers;
|
||||
// start time.
|
||||
static ULARGE_INTEGER start_time;
|
||||
|
||||
/**
|
||||
* Add data_source to run_loop
|
||||
*/
|
||||
static void btstack_run_loop_windows_add_data_source(btstack_data_source_t *ds){
|
||||
data_sources_modified = 1;
|
||||
// log_info("btstack_run_loop_windows_add_data_source %x with fd %u\n", (int) ds, ds->fd);
|
||||
btstack_linked_list_add(&data_sources, (btstack_linked_item_t *) ds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove data_source from run loop
|
||||
*/
|
||||
static int btstack_run_loop_windows_remove_data_source(btstack_data_source_t *ds){
|
||||
data_sources_modified = 1;
|
||||
// log_info("btstack_run_loop_windows_remove_data_source %x\n", (int) ds);
|
||||
return btstack_linked_list_remove(&data_sources, (btstack_linked_item_t *) ds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add timer to run_loop (keep list sorted)
|
||||
*/
|
||||
static void btstack_run_loop_windows_add_timer(btstack_timer_source_t *ts){
|
||||
btstack_linked_item_t *it;
|
||||
for (it = (btstack_linked_item_t *) &timers; it->next ; it = it->next){
|
||||
btstack_timer_source_t * next = (btstack_timer_source_t *) it->next;
|
||||
if (next == ts){
|
||||
log_error( "btstack_run_loop_timer_add error: timer to add already in list!");
|
||||
return;
|
||||
}
|
||||
if (next->timeout > ts->timeout) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ts->item.next = it->next;
|
||||
it->next = (btstack_linked_item_t *) ts;
|
||||
log_debug("Added timer %p at %u\n", ts, ts->timeout);
|
||||
// btstack_run_loop_windows_dump_timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove timer from run loop
|
||||
*/
|
||||
static int btstack_run_loop_windows_remove_timer(btstack_timer_source_t *ts){
|
||||
// log_info("Removed timer %x at %u\n", (int) ts, (unsigned int) ts->timeout.tv_sec);
|
||||
// btstack_run_loop_windows_dump_timer();
|
||||
return btstack_linked_list_remove(&timers, (btstack_linked_item_t *) ts);
|
||||
}
|
||||
|
||||
static void btstack_run_loop_windows_dump_timer(void){
|
||||
btstack_linked_item_t *it;
|
||||
int i = 0;
|
||||
for (it = (btstack_linked_item_t *) timers; it ; it = it->next){
|
||||
btstack_timer_source_t *ts = (btstack_timer_source_t*) it;
|
||||
log_info("timer %u, timeout %u\n", i, ts->timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_run_loop_windows_enable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){
|
||||
ds->flags |= callback_types;
|
||||
}
|
||||
|
||||
static void btstack_run_loop_windows_disable_data_source_callbacks(btstack_data_source_t * ds, uint16_t callback_types){
|
||||
ds->flags &= ~callback_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Queries the current time in ms since start
|
||||
*/
|
||||
static uint32_t btstack_run_loop_windows_get_time_ms(void){
|
||||
|
||||
FILETIME file_time;
|
||||
SYSTEMTIME system_time;
|
||||
ULARGE_INTEGER now_time;
|
||||
GetSystemTime(&system_time);
|
||||
SystemTimeToFileTime(&system_time, &file_time);
|
||||
now_time.LowPart = file_time.dwLowDateTime;
|
||||
now_time.HighPart = file_time.dwHighDateTime;
|
||||
uint32_t time_ms = (now_time.QuadPart - start_time.QuadPart) / 10000;
|
||||
log_debug("btstack_run_loop_windows_get_time_ms: %u", time_ms);
|
||||
return time_ms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute run_loop
|
||||
*/
|
||||
static void btstack_run_loop_windows_execute(void) {
|
||||
|
||||
btstack_timer_source_t *ts;
|
||||
btstack_linked_list_iterator_t it;
|
||||
|
||||
while (1) {
|
||||
|
||||
// collect handles to wait for
|
||||
HANDLE handles[100];
|
||||
memset(handles, 0, sizeof(handles));
|
||||
int num_handles = 0;
|
||||
btstack_linked_list_iterator_init(&it, &data_sources);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (ds->handle == 0) continue;
|
||||
if (ds->flags & (DATA_SOURCE_CALLBACK_READ | DATA_SOURCE_CALLBACK_WRITE)){
|
||||
handles[num_handles++] = ds->handle;
|
||||
log_debug("btstack_run_loop_execute adding handle %p", ds->handle);
|
||||
}
|
||||
}
|
||||
|
||||
// get next timeout
|
||||
uint32_t timeout_ms = INFINITE;
|
||||
if (timers) {
|
||||
ts = (btstack_timer_source_t *) timers;
|
||||
uint32_t now_ms = btstack_run_loop_windows_get_time_ms();
|
||||
timeout_ms = ts->timeout - now_ms;
|
||||
if (timeout_ms < 0){
|
||||
timeout_ms = 0;
|
||||
}
|
||||
log_debug("btstack_run_loop_execute next timeout in %u ms", timeout_ms);
|
||||
}
|
||||
|
||||
int res;
|
||||
if (num_handles){
|
||||
// wait for ready Events or timeout
|
||||
res = WaitForMultipleObjects(num_handles, &handles[0], 0, timeout_ms);
|
||||
} else {
|
||||
// just wait for timeout
|
||||
Sleep(timeout_ms);
|
||||
res = WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
// process data source
|
||||
if (WAIT_OBJECT_0 <= res && res < (WAIT_OBJECT_0 + num_handles)){
|
||||
void * triggered_handle = handles[res - WAIT_OBJECT_0];
|
||||
btstack_linked_list_iterator_init(&it, &data_sources);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
btstack_data_source_t *ds = (btstack_data_source_t*) btstack_linked_list_iterator_next(&it);
|
||||
log_debug("btstack_run_loop_windows_execute: check ds %p with handle %p\n", ds, ds->handle);
|
||||
if (triggered_handle == ds->handle){
|
||||
if (ds->flags & DATA_SOURCE_CALLBACK_READ){
|
||||
log_debug("btstack_run_loop_windows_execute: process read ds %p with handle %p\n", ds, ds->handle);
|
||||
ds->process(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
} else if (ds->flags & DATA_SOURCE_CALLBACK_WRITE){
|
||||
log_debug("btstack_run_loop_windows_execute: process write ds %p with handle %p\n", ds, ds->handle);
|
||||
ds->process(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process timers
|
||||
uint32_t now_ms = btstack_run_loop_windows_get_time_ms();
|
||||
while (timers) {
|
||||
ts = (btstack_timer_source_t *) timers;
|
||||
if (ts->timeout > now_ms) break;
|
||||
log_debug("btstack_run_loop_windows_execute: process timer %p\n", ts);
|
||||
|
||||
// remove timer before processing it to allow handler to re-register with run loop
|
||||
btstack_run_loop_remove_timer(ts);
|
||||
ts->process(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set timer
|
||||
static void btstack_run_loop_windows_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){
|
||||
uint32_t time_ms = btstack_run_loop_windows_get_time_ms();
|
||||
a->timeout = time_ms + timeout_in_ms;
|
||||
log_debug("btstack_run_loop_windows_set_timer to %u ms (now %u, timeout %u)", a->timeout, time_ms, timeout_in_ms);
|
||||
}
|
||||
|
||||
static void btstack_run_loop_windows_init(void){
|
||||
data_sources = NULL;
|
||||
timers = NULL;
|
||||
|
||||
// store start time
|
||||
FILETIME file_time;
|
||||
SYSTEMTIME system_time;
|
||||
GetSystemTime(&system_time);
|
||||
SystemTimeToFileTime(&system_time, &file_time);
|
||||
start_time.LowPart = file_time.dwLowDateTime;
|
||||
start_time.HighPart = file_time.dwHighDateTime;
|
||||
|
||||
log_debug("btstack_run_loop_windows_init");
|
||||
}
|
||||
|
||||
|
||||
static const btstack_run_loop_t btstack_run_loop_windows = {
|
||||
&btstack_run_loop_windows_init,
|
||||
&btstack_run_loop_windows_add_data_source,
|
||||
&btstack_run_loop_windows_remove_data_source,
|
||||
&btstack_run_loop_windows_enable_data_source_callbacks,
|
||||
&btstack_run_loop_windows_disable_data_source_callbacks,
|
||||
&btstack_run_loop_windows_set_timer,
|
||||
&btstack_run_loop_windows_add_timer,
|
||||
&btstack_run_loop_windows_remove_timer,
|
||||
&btstack_run_loop_windows_execute,
|
||||
&btstack_run_loop_windows_dump_timer,
|
||||
&btstack_run_loop_windows_get_time_ms,
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide btstack_run_loop_windows instance
|
||||
*/
|
||||
const btstack_run_loop_t * btstack_run_loop_windows_get_instance(void){
|
||||
return &btstack_run_loop_windows;
|
||||
}
|
||||
|
63
platform/windows/btstack_run_loop_windows.h
Normal file
63
platform/windows/btstack_run_loop_windows.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_run_loop_windows.h
|
||||
* Functionality special to the windows run loop
|
||||
*/
|
||||
|
||||
#ifndef __btstack_run_loop_WINDOWS_H
|
||||
#define __btstack_run_loop_WINDOWS_H
|
||||
|
||||
#include "btstack_run_loop.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Provide btstack_run_loop_windows instance
|
||||
*/
|
||||
const btstack_run_loop_t * btstack_run_loop_windows_get_instance(void);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __btstack_run_loop_WINDOWS_H
|
417
platform/windows/btstack_uart_block_windows.c
Normal file
417
platform/windows/btstack_uart_block_windows.c
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_uart_block_windows.c
|
||||
*
|
||||
* Common code to access serial port via asynchronous block read/write commands
|
||||
*
|
||||
*/
|
||||
|
||||
#include "btstack_uart_block.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_debug.h"
|
||||
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
// 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_read;
|
||||
static btstack_data_source_t transport_data_source_write;
|
||||
|
||||
// block write
|
||||
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;
|
||||
|
||||
// callbacks
|
||||
static void (*block_sent)(void);
|
||||
static void (*block_received)(void);
|
||||
|
||||
// port and async control structure
|
||||
static HANDLE serial_port_handle;
|
||||
static OVERLAPPED overlapped_read;
|
||||
static OVERLAPPED overlapped_write;
|
||||
|
||||
|
||||
static int btstack_uart_windows_init(const btstack_uart_config_t * config){
|
||||
uart_config = config;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_process_write(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
|
||||
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
|
||||
DWORD bytes_written;
|
||||
BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_write, &bytes_written, FALSE);
|
||||
if(!ok){
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_IO_INCOMPLETE){
|
||||
// IO_INCOMPLETE -> wait for completed
|
||||
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
|
||||
} else {
|
||||
log_error("btstack_uart_windows_process_write: error writing");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// assert all bytes written
|
||||
if (bytes_written != write_bytes_len){
|
||||
log_error("btstack_uart_windows_process_write: requested write %u but %u were written", (int) write_bytes_len, (int) bytes_written);
|
||||
return;
|
||||
}
|
||||
|
||||
// notify done
|
||||
if (block_sent){
|
||||
block_sent();
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_process_read(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
|
||||
|
||||
btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
|
||||
DWORD bytes_read;
|
||||
BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_read, &bytes_read, FALSE);
|
||||
if(!ok){
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_IO_INCOMPLETE){
|
||||
// IO_INCOMPLETE -> wait for completed
|
||||
btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
|
||||
} else {
|
||||
log_error("btstack_uart_windows_process_write: error writing");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// assert all bytes read
|
||||
if (bytes_read != read_bytes_len){
|
||||
log_error("btstack_uart_windows_process_read: requested read %u but %u were read", (int) read_bytes_len, (int) bytes_read);
|
||||
return;
|
||||
}
|
||||
|
||||
// notify done
|
||||
if (block_received){
|
||||
block_received();
|
||||
}
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){
|
||||
|
||||
// setup async write
|
||||
write_bytes_data = data;
|
||||
write_bytes_len = size;
|
||||
|
||||
// start write
|
||||
DWORD bytes_written;
|
||||
BOOL ok = WriteFile(serial_port_handle, // handle
|
||||
write_bytes_data, // (LPCSTR) 8-bit data
|
||||
write_bytes_len, // length
|
||||
&bytes_written, // amount written
|
||||
&overlapped_write); // overlapped structure
|
||||
|
||||
if (ok){
|
||||
|
||||
// assert all bytes written
|
||||
if (bytes_written != write_bytes_len){
|
||||
log_error("btstack_uart_windows_send_block: requested write %u but %u were written", (int) write_bytes_len, (int) bytes_written);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: to defer sending done event by enabling POLL Callback for Write
|
||||
//
|
||||
|
||||
// notify done
|
||||
if (block_sent){
|
||||
block_sent();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_IO_PENDING){
|
||||
log_error("btstack_uart_windows_send_block: error writing");
|
||||
return;
|
||||
}
|
||||
|
||||
// IO_PENDING -> wait for completed
|
||||
btstack_run_loop_enable_data_source_callbacks(&transport_data_source_write, DATA_SOURCE_CALLBACK_WRITE);
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){
|
||||
|
||||
// setup async read
|
||||
read_bytes_data = buffer;
|
||||
read_bytes_len = len;
|
||||
|
||||
// go
|
||||
DWORD bytes_read;
|
||||
BOOL ok = ReadFile(serial_port_handle, // handle
|
||||
read_bytes_data, // (LPCSTR) 8-bit data
|
||||
read_bytes_len, // length
|
||||
&bytes_read, // amount read
|
||||
&overlapped_read); // overlapped structure
|
||||
|
||||
if (ok){
|
||||
|
||||
// assert all bytes read
|
||||
if (bytes_read != read_bytes_len){
|
||||
log_error("btstack_uart_windows_receive_block: requested read %u but %u were read", (int) read_bytes_len, (int) bytes_read);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: to defer sending done event by enabling POLL Callback
|
||||
//
|
||||
|
||||
// notify done
|
||||
if (block_received){
|
||||
block_received();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_IO_PENDING){
|
||||
log_error("btstack_uart_windows_receive_block: error reading");
|
||||
return;
|
||||
}
|
||||
|
||||
// IO_PENDING -> wait for completed
|
||||
btstack_run_loop_enable_data_source_callbacks(&transport_data_source_read, DATA_SOURCE_CALLBACK_READ);
|
||||
}
|
||||
|
||||
|
||||
static int btstack_uart_windows_set_baudrate(uint32_t baudrate){
|
||||
DCB serial_params;
|
||||
memset(&serial_params, 0, sizeof(DCB));
|
||||
serial_params.DCBlength = sizeof(DCB);
|
||||
|
||||
int ok = GetCommState(serial_port_handle, &serial_params);
|
||||
|
||||
if (!ok){
|
||||
log_error("windows_set_baudrate: Couldn't get serial parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
serial_params.BaudRate = baudrate;
|
||||
|
||||
ok = SetCommState(serial_port_handle, &serial_params);
|
||||
if (!ok){
|
||||
log_error("windows_set_baudrate: Couldn't serial parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int btstack_uart_windows_set_parity(int parity){
|
||||
DCB serial_params;
|
||||
memset(&serial_params, 0, sizeof(DCB));
|
||||
serial_params.DCBlength = sizeof(DCB);
|
||||
|
||||
int ok = GetCommState(serial_port_handle, &serial_params);
|
||||
|
||||
if (!ok){
|
||||
log_error("windows_set_parity: Couldn't get serial parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
serial_params.Parity = parity;
|
||||
|
||||
ok = SetCommState(serial_port_handle, &serial_params);
|
||||
if (!ok){
|
||||
log_error("windows_set_parity: Couldn't serial parameters");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btstack_uart_windows_open(void){
|
||||
|
||||
const char * device_name = uart_config->device_name;
|
||||
const uint32_t baudrate = uart_config->baudrate;
|
||||
const int flowcontrol = uart_config->flowcontrol;
|
||||
|
||||
serial_port_handle = CreateFile( device_name,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
0);
|
||||
|
||||
if (device_name == INVALID_HANDLE_VALUE){
|
||||
log_error("windows_open: Unable to open port %s", device_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DCB serial_params;
|
||||
memset(&serial_params, 0, sizeof(DCB));
|
||||
serial_params.DCBlength = sizeof(DCB);
|
||||
|
||||
int ok;
|
||||
|
||||
#if 0
|
||||
// test - try to set internal buffer
|
||||
ok = SetupComm(serial_port_handle, 64, 64);
|
||||
printf("SetupCommL ok %u\n", ok);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// test - read internal buffer sizes
|
||||
COMMPROP comm_prop;
|
||||
GetCommProperties(serial_port_handle, &comm_prop);
|
||||
printf("dwMaxTxQueue %ld\n", comm_prop.dwMaxTxQueue);
|
||||
printf("dwMaxRxQueue %ld\n", comm_prop.dwMaxRxQueue);
|
||||
printf("dwCurrentTxQueue %ld\n", comm_prop.dwCurrentTxQueue);
|
||||
printf("dwCurrentRxQueue %ld\n", comm_prop.dwCurrentRxQueue);
|
||||
#endif
|
||||
|
||||
// Caveat: with the default FTDI driver and a FT232R on Windows 10, the default USB RX/TX buffer sizes are 4096
|
||||
// this causes a problem when data is received back to back, like with SCO audio data
|
||||
|
||||
// Workaround: manually set these values in the Device Manager to 64 bytes
|
||||
|
||||
ok = GetCommState(serial_port_handle, &serial_params);
|
||||
|
||||
if (!ok){
|
||||
log_error("windows_open: Couldn't get serial parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 8-N-1
|
||||
serial_params.ByteSize = 8;
|
||||
serial_params.StopBits = ONESTOPBIT;
|
||||
serial_params.Parity = NOPARITY;
|
||||
|
||||
// Flowcontrol
|
||||
serial_params.fOutxCtsFlow = flowcontrol;
|
||||
serial_params.fRtsControl = flowcontrol ? RTS_CONTROL_HANDSHAKE : 0;
|
||||
|
||||
ok = SetCommState(serial_port_handle, &serial_params);
|
||||
if (!ok){
|
||||
log_error("windows_open: Couldn't serial parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// also set baudrate
|
||||
if (btstack_uart_windows_set_baudrate(baudrate) < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
// setup overlapped structures for async io
|
||||
memset(&overlapped_read, 0, sizeof(overlapped_read));
|
||||
memset(&overlapped_write, 0, sizeof(overlapped_write));
|
||||
overlapped_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
overlapped_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
// setup read + write data sources
|
||||
transport_data_source_read.handle = overlapped_read.hEvent;
|
||||
transport_data_source_write.handle = overlapped_write.hEvent;
|
||||
btstack_run_loop_set_data_source_handler(&transport_data_source_read, &btstack_uart_windows_process_read);
|
||||
btstack_run_loop_set_data_source_handler(&transport_data_source_write, &btstack_uart_windows_process_write);
|
||||
btstack_run_loop_add_data_source(&transport_data_source_read);
|
||||
btstack_run_loop_add_data_source(&transport_data_source_write);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btstack_uart_windows_close_new(void){
|
||||
|
||||
// first remove run loop handler
|
||||
btstack_run_loop_remove_data_source(&transport_data_source_read);
|
||||
btstack_run_loop_remove_data_source(&transport_data_source_write);
|
||||
|
||||
// note: an event cannot be freed while a kernel function is waiting.
|
||||
// in our single-threaded environment, this cannot happen.
|
||||
|
||||
// free events
|
||||
CloseHandle(overlapped_read.hEvent);
|
||||
CloseHandle(overlapped_write.hEvent);
|
||||
CloseHandle(serial_port_handle);
|
||||
|
||||
// set pointers to zero
|
||||
overlapped_read.hEvent = NULL;
|
||||
overlapped_write.hEvent = NULL;
|
||||
serial_port_handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_set_block_received( void (*block_handler)(void)){
|
||||
block_received = block_handler;
|
||||
}
|
||||
|
||||
static void btstack_uart_windows_set_block_sent( void (*block_handler)(void)){
|
||||
block_sent = block_handler;
|
||||
}
|
||||
|
||||
// static void btstack_uart_windows_set_sleep(uint8_t sleep){
|
||||
// }
|
||||
// static void btstack_uart_windows_set_csr_irq_handler( void (*csr_irq_handler)(void)){
|
||||
// }
|
||||
|
||||
static const btstack_uart_block_t btstack_uart_windows = {
|
||||
/* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_windows_init,
|
||||
/* int (*open)(void); */ &btstack_uart_windows_open,
|
||||
/* int (*close)(void); */ &btstack_uart_windows_close_new,
|
||||
/* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_windows_set_block_received,
|
||||
/* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_windows_set_block_sent,
|
||||
/* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_windows_set_baudrate,
|
||||
/* int (*set_parity)(int parity); */ &btstack_uart_windows_set_parity,
|
||||
/* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_windows_receive_block,
|
||||
/* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_windows_send_block,
|
||||
/* int (*get_supported_sleep_modes); */ NULL,
|
||||
/* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL
|
||||
};
|
||||
|
||||
const btstack_uart_block_t * btstack_uart_block_windows_instance(void){
|
||||
return &btstack_uart_windows;
|
||||
}
|
1299
platform/windows/hci_transport_h2_winusb.c
Normal file
1299
platform/windows/hci_transport_h2_winusb.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -75,13 +75,14 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
|
||||
static void sigint_handler(int param){
|
||||
UNUSED(param);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
#endif
|
||||
|
||||
log_info(" <= SIGINT received, shutting down..\n");
|
||||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
|
@ -108,13 +108,15 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
#ifndef _WIN32
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
#endif
|
||||
|
||||
log_info(" <= SIGINT received, shutting down..\n");
|
||||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
|
@ -79,13 +79,15 @@ static hci_transport_config_uart_t config = {
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void sigint_handler(int param){
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
#ifndef _WIN32
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
#endif
|
||||
|
||||
log_info(" <= SIGINT received, shutting down..\n");
|
||||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
|
39
port/windows-h4/.gitignore
vendored
Normal file
39
port/windows-h4/.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
ancs_client_demo
|
||||
ancs_client_demo.h
|
||||
ble_central_test
|
||||
ble_peripheral_test
|
||||
bnep_test
|
||||
classic_test
|
||||
gap_dedicated_bonding
|
||||
gap_inquiry
|
||||
gap_inquiry_and_bond
|
||||
gap_le_advertisements
|
||||
gap_le_advertisements
|
||||
gatt_battery_query
|
||||
gatt_browser
|
||||
hfp_ag_demo
|
||||
hfp_hf_demo
|
||||
hsp_ag_demo
|
||||
hsp_hs_demo
|
||||
l2cap_test
|
||||
le_counter
|
||||
le_counter.h
|
||||
le_streamer
|
||||
le_streamer
|
||||
le_streamer.h
|
||||
led_counter
|
||||
panu_demo
|
||||
profile.h
|
||||
sdp_bnep_query
|
||||
sdp_general_query
|
||||
sdp_rfcomm_query
|
||||
sm_pairing_central
|
||||
sm_pairing_peripheral
|
||||
sm_pairing_peripheral.h
|
||||
spp_and_le_counter
|
||||
spp_and_le_counter.h
|
||||
spp_counter
|
||||
spp_streamer
|
||||
spp_streamer
|
||||
sco_input*
|
||||
sco_output*
|
57
port/windows-h4/Makefile
Normal file
57
port/windows-h4/Makefile
Normal file
@ -0,0 +1,57 @@
|
||||
# Makefile for windows-h4 examples
|
||||
BTSTACK_ROOT = ../..
|
||||
|
||||
CORE += main.c stdin_support.c
|
||||
|
||||
COMMON += \
|
||||
btstack_run_loop_windows.c \
|
||||
hci_transport_h4.c \
|
||||
btstack_uart_block_windows.c \
|
||||
le_device_db_fs.c \
|
||||
btstack_link_key_db_fs.c \
|
||||
bluetooth_init_cc2564B_1.4_BT_Spec_4.1.c \
|
||||
btstack_chipset_cc256x.c \
|
||||
btstack_chipset_csr.c \
|
||||
btstack_chipset_em9301.c \
|
||||
btstack_chipset_stlc2500d.c \
|
||||
btstack_chipset_tc3566x.c \
|
||||
btstack_chipset_bcm.c \
|
||||
|
||||
# examples
|
||||
include ${BTSTACK_ROOT}/example/Makefile.inc
|
||||
|
||||
# fetch and convert TI init scripts
|
||||
include ${BTSTACK_ROOT}/chipset/cc256x/Makefile.inc
|
||||
|
||||
# fetch Broadcom init scripts
|
||||
# include ${BTSTACK_ROOT}/chipset/bcm/Makefile.inc
|
||||
|
||||
# CC = gcc-fsf-4.9
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror
|
||||
# CFLAGS += -Werror
|
||||
|
||||
CFLAGS += -I${BTSTACK_ROOT}/platform/posix \
|
||||
-I${BTSTACK_ROOT}/platform/windows \
|
||||
-I${BTSTACK_ROOT}/platform/embedded \
|
||||
-I$(BTSTACK_ROOT)/chipset/bcm \
|
||||
-I$(BTSTACK_ROOT)/chipset/cc256x \
|
||||
-I$(BTSTACK_ROOT)/chipset/csr \
|
||||
-I$(BTSTACK_ROOT)/chipset/em9301 \
|
||||
-I$(BTSTACK_ROOT)/chipset/stlc2500d \
|
||||
-I$(BTSTACK_ROOT)/chipset/tc3566x \
|
||||
|
||||
VPATH += ${BTSTACK_ROOT}/platform/windows
|
||||
VPATH += ${BTSTACK_ROOT}/platform/posix
|
||||
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/bcm
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/cc256x
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/csr
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/em9301
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/stlc2500d
|
||||
VPATH += ${BTSTACK_ROOT}/chipset/tc3566x
|
||||
|
||||
# assume portaudio is installed in /usr/local
|
||||
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
|
||||
# LDFLAGS += -L/sw/lib -lportaudio
|
||||
|
||||
all: ${EXAMPLES}
|
30
port/windows-h4/btstack_config.h
Normal file
30
port/windows-h4/btstack_config.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// btstack_config.h for libusb port
|
||||
//
|
||||
|
||||
#ifndef __BTSTACK_CONFIG
|
||||
#define __BTSTACK_CONFIG
|
||||
|
||||
// Port related features
|
||||
#define HAVE_MALLOC
|
||||
#define HAVE_POSIX_FILE_IO
|
||||
#define HAVE_POSIX_STDIN
|
||||
#define HAVE_POSIX_TIME
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
#define ENABLE_SCO_OVER_HCI
|
||||
#define ENABLE_SDP_DES_DUMP
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
|
||||
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy
|
||||
|
||||
#endif
|
188
port/windows-h4/main.c
Normal file
188
port/windows-h4/main.c
Normal file
@ -0,0 +1,188 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "btstack_config.h"
|
||||
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_run_loop_windows.h"
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
#include "hal_led.h"
|
||||
#include "btstack_link_key_db_fs.h"
|
||||
|
||||
#include "stdin_support.h"
|
||||
|
||||
#include "btstack_chipset_bcm.h"
|
||||
#include "btstack_chipset_csr.h"
|
||||
#include "btstack_chipset_cc256x.h"
|
||||
#include "btstack_chipset_em9301.h"
|
||||
#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);
|
||||
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
1, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
int is_bcm;
|
||||
|
||||
static int led_state = 0;
|
||||
|
||||
void hal_led_toggle(void){
|
||||
led_state = 1 - led_state;
|
||||
printf("LED State %u\n", led_state);
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C = SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
|
||||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break;
|
||||
printf("BTstack up and running.\n");
|
||||
break;
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
static void use_fast_uart(void){
|
||||
printf("Using 921600 baud.\n");
|
||||
config.baudrate_main = 921600;
|
||||
}
|
||||
|
||||
static void local_version_information_handler(uint8_t * packet){
|
||||
printf("Local version information:\n");
|
||||
uint16_t hci_version = little_endian_read_16(packet, 4);
|
||||
uint16_t hci_revision = little_endian_read_16(packet, 6);
|
||||
uint16_t lmp_version = little_endian_read_16(packet, 8);
|
||||
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 COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
|
||||
printf("Cambridge Silicon Radio - CSR chipset.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_csr_instance());
|
||||
break;
|
||||
case 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");
|
||||
#else
|
||||
printf("eHCILL disable.\n");
|
||||
#endif
|
||||
break;
|
||||
case 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 COMPANY_ID_ST_MICROELECTRONICS:
|
||||
printf("ST Microelectronics - using STLC2500d driver.\n");
|
||||
use_fast_uart();
|
||||
hci_set_chipset(btstack_chipset_stlc2500d_instance());
|
||||
break;
|
||||
case COMPANY_ID_EM_MICROELECTRONICS_MARIN:
|
||||
printf("EM Microelectronics - using EM9301 driver.\n");
|
||||
hci_set_chipset(btstack_chipset_em9301_instance());
|
||||
break;
|
||||
case COMPANY_ID_NORDIC_SEMICONDUCTOR_ASA:
|
||||
printf("Nordic Semiconductor nRF5 chipset.\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown manufacturer / manufacturer not supported yet.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]){
|
||||
printf("BTstack on windows booting up\n");
|
||||
|
||||
/// GET STARTED with BTstack ///
|
||||
btstack_memory_init();
|
||||
btstack_run_loop_init(btstack_run_loop_windows_get_instance());
|
||||
|
||||
hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||
|
||||
// pick serial port
|
||||
config.device_name = "\\\\.\\COM7";
|
||||
|
||||
// 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);
|
||||
const btstack_link_key_db_t * link_key_db = btstack_link_key_db_fs_instance();
|
||||
hci_init(transport, (void*) &config);
|
||||
hci_set_link_key_db(link_key_db);
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
||||
// handle CTRL-c
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
// setup app
|
||||
btstack_main(argc, argv);
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
|
||||
return 0;
|
||||
}
|
39
port/windows-winusb/.gitignore
vendored
Normal file
39
port/windows-winusb/.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
ancs_client_demo
|
||||
ancs_client_demo.h
|
||||
ble_central_test
|
||||
ble_peripheral_test
|
||||
bnep_test
|
||||
classic_test
|
||||
gap_dedicated_bonding
|
||||
gap_inquiry
|
||||
gap_inquiry_and_bond
|
||||
gap_le_advertisements
|
||||
gap_le_advertisements
|
||||
gatt_battery_query
|
||||
gatt_browser
|
||||
hfp_ag_demo
|
||||
hfp_hf_demo
|
||||
hsp_ag_demo
|
||||
hsp_hs_demo
|
||||
l2cap_test
|
||||
le_counter
|
||||
le_counter.h
|
||||
le_streamer
|
||||
le_streamer
|
||||
le_streamer.h
|
||||
led_counter
|
||||
panu_demo
|
||||
profile.h
|
||||
sdp_bnep_query
|
||||
sdp_general_query
|
||||
sdp_rfcomm_query
|
||||
sm_pairing_central
|
||||
sm_pairing_peripheral
|
||||
sm_pairing_peripheral.h
|
||||
spp_and_le_counter
|
||||
spp_and_le_counter.h
|
||||
spp_counter
|
||||
spp_streamer
|
||||
spp_streamer
|
||||
sco_input*
|
||||
sco_output*
|
33
port/windows-winusb/Makefile
Normal file
33
port/windows-winusb/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
# Makefile for windows WinUSB based examples
|
||||
BTSTACK_ROOT = ../..
|
||||
|
||||
CORE += main.c stdin_support.c
|
||||
|
||||
COMMON += hci_transport_h2_winusb.c btstack_run_loop_windows.c le_device_db_fs.c btstack_link_key_db_fs.c
|
||||
|
||||
include ${BTSTACK_ROOT}/example/Makefile.inc
|
||||
|
||||
# CC = gcc-fsf-4.9
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror
|
||||
# CFLAGS += -Werror
|
||||
|
||||
CFLAGS += -I${BTSTACK_ROOT}/platform/windows \
|
||||
-I${BTSTACK_ROOT}/platform/posix \
|
||||
-I${BTSTACK_ROOT}/platform/embedded
|
||||
|
||||
VPATH += ${BTSTACK_ROOT}/platform/embedded
|
||||
VPATH += ${BTSTACK_ROOT}/platform/posix
|
||||
VPATH += ${BTSTACK_ROOT}/platform/windows
|
||||
|
||||
# use pkg-config for portaudio
|
||||
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO
|
||||
# LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
|
||||
# hard coded flags for portaudio in /usr/local/lib
|
||||
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
|
||||
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
|
||||
|
||||
LDFLAGS += -lsetupapi -lwinusb
|
||||
|
||||
EXAMPLES=le_counter hfp_hf_demo
|
||||
|
||||
all: ${EXAMPLES}
|
30
port/windows-winusb/btstack_config.h
Normal file
30
port/windows-winusb/btstack_config.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// btstack_config.h for libusb port
|
||||
//
|
||||
|
||||
#ifndef __BTSTACK_CONFIG
|
||||
#define __BTSTACK_CONFIG
|
||||
|
||||
// Port related features
|
||||
#define HAVE_MALLOC
|
||||
#define HAVE_POSIX_FILE_IO
|
||||
#define HAVE_POSIX_STDIN
|
||||
#define HAVE_POSIX_TIME
|
||||
|
||||
// BTstack features that can be enabled
|
||||
#define ENABLE_BLE
|
||||
#define ENABLE_CLASSIC
|
||||
#define ENABLE_LE_PERIPHERAL
|
||||
#define ENABLE_LE_CENTRAL
|
||||
#define ENABLE_LE_SECURE_CONNECTIONS
|
||||
#define ENABLE_LOG_ERROR
|
||||
#define ENABLE_LOG_INFO
|
||||
#define ENABLE_LOG_INTO_HCI_DUMP
|
||||
#define ENABLE_SCO_OVER_HCI
|
||||
#define ENABLE_SDP_DES_DUMP
|
||||
|
||||
// BTstack configuration. buffers, sizes, ...
|
||||
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
|
||||
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy
|
||||
|
||||
#endif
|
173
port/windows-winusb/main.c
Normal file
173
port/windows-winusb/main.c
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
// *****************************************************************************
|
||||
//
|
||||
// minimal setup for HCI code
|
||||
//
|
||||
// *****************************************************************************
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "btstack_config.h"
|
||||
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_link_key_db_fs.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "btstack_run_loop_windows.h"
|
||||
#include "hal_led.h"
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
#include "stdin_support.h"
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
|
||||
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
|
||||
printf("BTstack up and running.\n");
|
||||
}
|
||||
|
||||
static void sigint_handler(int param){
|
||||
UNUSED(param);
|
||||
|
||||
printf("CTRL-C - SIGINT received, shutting down..\n");
|
||||
log_info("sigint_handler: shutting down");
|
||||
|
||||
// reset anyway
|
||||
btstack_stdin_reset();
|
||||
|
||||
// power down
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
hci_close();
|
||||
log_info("Good bye, see you.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int led_state = 0;
|
||||
void hal_led_toggle(void){
|
||||
led_state = 1 - led_state;
|
||||
printf("LED State %u\n", led_state);
|
||||
}
|
||||
|
||||
|
||||
#define USB_MAX_PATH_LEN 7
|
||||
int main(int argc, const char * argv[]){
|
||||
|
||||
// Prevent stdout buffering
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
printf("BTstack/windows-winusb booting up\n");
|
||||
|
||||
#if 0
|
||||
int usb_path_len = 0;
|
||||
uint8_t usb_path[USB_MAX_PATH_LEN];
|
||||
if (argc >= 3 && strcmp(argv[1], "-u") == 0){
|
||||
// parse command line options for "-u 11:22:33"
|
||||
const char * port_str = argv[2];
|
||||
printf("Specified USB Path: ");
|
||||
while (1){
|
||||
char * delimiter;
|
||||
int port = strtol(port_str, &delimiter, 16);
|
||||
usb_path[usb_path_len] = port;
|
||||
usb_path_len++;
|
||||
printf("%02x ", port);
|
||||
if (!delimiter) break;
|
||||
if (*delimiter != ':' && *delimiter != '-') break;
|
||||
port_str = delimiter+1;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/// GET STARTED with BTstack ///
|
||||
btstack_memory_init();
|
||||
btstack_run_loop_init(btstack_run_loop_windows_get_instance());
|
||||
|
||||
// if (usb_path_len){
|
||||
// hci_transport_usb_set_path(usb_path_len, usb_path);
|
||||
// }
|
||||
|
||||
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
|
||||
|
||||
#if 1
|
||||
char pklg_path[100];
|
||||
strcpy(pklg_path, "hci_dump");
|
||||
#if 0
|
||||
if (usb_path_len){
|
||||
strcat(pklg_path, "_");
|
||||
strcat(pklg_path, argv[2]);
|
||||
}
|
||||
#endif
|
||||
strcat(pklg_path, ".pklg");
|
||||
printf("Packet Log: %s\n", pklg_path);
|
||||
hci_dump_open(pklg_path, HCI_DUMP_PACKETLOGGER);
|
||||
#else
|
||||
hci_dump_open(NULL, HCI_DUMP_STDOUT);
|
||||
#endif
|
||||
|
||||
// init HCI
|
||||
hci_init(hci_transport_usb_instance(), NULL);
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
hci_set_link_key_db(btstack_link_key_db_fs_instance());
|
||||
#endif
|
||||
|
||||
// inform about BTstack state
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
||||
// handle CTRL-c
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
// setup app
|
||||
btstack_main(argc, argv);
|
||||
|
||||
// go
|
||||
btstack_run_loop_execute();
|
||||
|
||||
return 0;
|
||||
}
|
@ -65,14 +65,23 @@ typedef enum {
|
||||
} btstack_data_source_callback_type_t;
|
||||
|
||||
typedef struct btstack_data_source {
|
||||
//
|
||||
// linked item
|
||||
btstack_linked_item_t item;
|
||||
// file descriptor to watch for run loops that support file descriptors
|
||||
int fd;
|
||||
|
||||
// item to watch in run loop
|
||||
union {
|
||||
// file descriptor for posix systems
|
||||
int fd;
|
||||
// handle on windows
|
||||
void * handle;
|
||||
};
|
||||
|
||||
// callback to call for enabled callback types
|
||||
void (*process)(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type);
|
||||
|
||||
// flags storing enabled callback types
|
||||
uint16_t flags;
|
||||
|
||||
} btstack_data_source_t;
|
||||
|
||||
typedef struct btstack_timer_source {
|
||||
|
@ -136,6 +136,7 @@ typedef struct {
|
||||
|
||||
// common implementations
|
||||
const btstack_uart_block_t * btstack_uart_block_posix_instance(void);
|
||||
const btstack_uart_block_t * btstack_uart_block_windows_instance(void);
|
||||
const btstack_uart_block_t * btstack_uart_block_embedded_instance(void);
|
||||
|
||||
#endif
|
||||
|
@ -530,6 +530,8 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
|
||||
hfp_connection->codec_confirmed = hfp_connection->suggested_codec;
|
||||
hfp_connection->ok_pending = 1;
|
||||
hfp_connection->codecs_state = HFP_CODECS_HF_CONFIRMED_CODEC;
|
||||
hfp_connection->negotiated_codec = hfp_connection->suggested_codec;
|
||||
log_info("hfp: codec confirmed: %s", hfp_connection->negotiated_codec == HFP_CODEC_MSBC ? "mSBC" : "CVSD");
|
||||
hfp_hf_cmd_confirm_codec(hfp_connection->rfcomm_cid, hfp_connection->codec_confirmed);
|
||||
} else {
|
||||
hfp_connection->codec_confirmed = 0;
|
||||
@ -965,8 +967,6 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){
|
||||
break;
|
||||
case HFP_CODECS_HF_CONFIRMED_CODEC:
|
||||
hfp_connection->codecs_state = HFP_CODECS_EXCHANGED;
|
||||
hfp_connection->negotiated_codec = hfp_connection->suggested_codec;
|
||||
log_info("hfp: codec confirmed: %s", hfp_connection->negotiated_codec == HFP_CODEC_MSBC ? "mSBC" : "CVSD");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -176,7 +176,7 @@ static void printf_timestamp(void){
|
||||
}
|
||||
#endif
|
||||
|
||||
void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
|
||||
void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
|
||||
|
||||
if (dump_file < 0) return; // not activated yet
|
||||
|
||||
|
@ -204,7 +204,6 @@ static int media_initialized = 0;
|
||||
static int init_media_processing(avdtp_media_codec_configuration_sbc_t configuration){
|
||||
int num_channels = configuration.num_channels;
|
||||
int sample_rate = configuration.sampling_frequency;
|
||||
int frames_per_buffer = configuration.frames_per_buffer;
|
||||
|
||||
#ifdef STORE_SBC_TO_WAV_FILE
|
||||
btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL);
|
||||
@ -216,6 +215,7 @@ static int init_media_processing(avdtp_media_codec_configuration_sbc_t configura
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PORTAUDIO
|
||||
int frames_per_buffer = configuration.frames_per_buffer;
|
||||
PaError err;
|
||||
PaStreamParameters outputParameters;
|
||||
|
||||
@ -314,6 +314,8 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
|
||||
media_header.synchronization_source = big_endian_read_32(packet, pos);
|
||||
pos+=4;
|
||||
|
||||
UNUSED(media_header);
|
||||
|
||||
// TODO: read csrc list
|
||||
|
||||
// printf_hexdump( packet, pos );
|
||||
@ -329,6 +331,7 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
|
||||
sbc_header.num_frames = packet[pos] & 0x0f;
|
||||
pos++;
|
||||
|
||||
UNUSED(sbc_header);
|
||||
// printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet);
|
||||
// printf_hexdump( packet+pos, size-pos );
|
||||
|
||||
@ -476,14 +479,13 @@ static const uint8_t media_sbc_codec_info[] = {
|
||||
};
|
||||
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
if (app_state != AVDTP_APPLICATION_IDLE) {
|
||||
printf("Application is not idle.\n");
|
||||
return;
|
||||
}
|
||||
char buffer;
|
||||
read(ds->fd, &buffer, 1);
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
int cmd = btstack_stdin_read();
|
||||
|
||||
sep.seid = 1;
|
||||
switch (buffer){
|
||||
switch (cmd){
|
||||
case 'c':
|
||||
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(remote));
|
||||
avdtp_sink_connect(remote);
|
||||
|
Loading…
x
Reference in New Issue
Block a user