From ddac77b5603fde5b774cf649ab2cc2bf709e7192 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 23 Dec 2015 11:17:04 +0100 Subject: [PATCH] port for WICED platform using threads for HCI Transport H4 RX/TX --- port/wiced/btstack-config.h | 41 +++++ port/wiced/hci_transport_h4_wiced.c | 242 ++++++++++++++++++++++++++++ port/wiced/main.c | 235 +++++++++++++++++++++++++++ port/wiced/run_loop_wiced.c | 183 +++++++++++++++++++++ port/wiced/wiced.mk | 28 ++++ 5 files changed, 729 insertions(+) create mode 100644 port/wiced/btstack-config.h create mode 100644 port/wiced/hci_transport_h4_wiced.c create mode 100644 port/wiced/main.c create mode 100644 port/wiced/run_loop_wiced.c create mode 100644 port/wiced/wiced.mk diff --git a/port/wiced/btstack-config.h b/port/wiced/btstack-config.h new file mode 100644 index 000000000..6aa1e3c53 --- /dev/null +++ b/port/wiced/btstack-config.h @@ -0,0 +1,41 @@ +#ifndef __BTSTACK_CONFIG +#define __BTSTACK_CONFIG + +#define EMBEDDED + +#define HAVE_WICED + +#define HAVE_BLE + +#define HAVE_INIT_SCRIPT +#define HAVE_BZERO +#define HAVE_TIME_MS + +#define HAVE_EHCILL + +#define ENABLE_LOG_INFO +#define ENABLE_LOG_ERROR + +#define HCI_ACL_PAYLOAD_SIZE 52 + +// +#define MAX_SPP_CONNECTIONS 1 +#define MAX_NO_GATT_CLIENTS 0 +#define MAX_NO_GATT_SUBCLIENTS 0 +#define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS +#define MAX_NO_L2CAP_SERVICES 2 +#define MAX_NO_L2CAP_CHANNELS (1+MAX_SPP_CONNECTIONS) +#define MAX_NO_RFCOMM_MULTIPLEXERS MAX_SPP_CONNECTIONS +#define MAX_NO_RFCOMM_SERVICES 1 +#define MAX_NO_RFCOMM_CHANNELS MAX_SPP_CONNECTIONS +#define MAX_NO_DB_MEM_DEVICE_LINK_KEYS 2 +#define MAX_NO_DB_MEM_DEVICE_NAMES 0 +#define MAX_NO_DB_MEM_SERVICES 1 +#define MAX_NO_BNEP_SERVICES 0 +#define MAX_NO_BNEP_CHANNELS 0 +#define MAX_NO_HFP_CONNECTIONS 0 +#define MAX_NO_WHITELIST_ENTRIES 1 +#define MAX_NO_SM_LOOKUP_ENTRIES 3 +#define MAX_NO_SERVICE_RECORD_ITEMS 1 + +#endif \ No newline at end of file diff --git a/port/wiced/hci_transport_h4_wiced.c b/port/wiced/hci_transport_h4_wiced.c new file mode 100644 index 000000000..a5db54c7e --- /dev/null +++ b/port/wiced/hci_transport_h4_wiced.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2015 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 + * + */ + +/* + * hci_h4_transport_wiced.c + * + * HCI Transport API implementation for basic H4 protocol for use with run_loop_wiced.c + */ + +#include "btstack-config.h" + +#include "wiced.h" +#include "platform_bluetooth.h" + +#include +#include + +#include "debug.h" +#include "hci.h" +#include "hci_transport.h" + +// assert pre-buffer for packet type is available +#if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0) +#error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h +#endif + +static wiced_result_t h4_rx_worker_receive_packet(void * arg); +static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size); + +typedef struct hci_transport_h4 { + hci_transport_t transport; + data_source_t *ds; + int uart_fd; // different from ds->fd for HCI reader thread + /* power management support, e.g. used by iOS */ + timer_source_t sleep_timer; +} hci_transport_h4_t; + +// single instance +static hci_transport_h4_t * hci_transport_h4 = NULL; + +static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler; + +static wiced_worker_thread_t tx_worker_thread; +static const uint8_t * tx_worker_data_buffer; +static uint16_t tx_worker_data_size; + +static wiced_worker_thread_t rx_worker_thread; +static int rx_worker_read_pos; + +static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 1 + HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data) +static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE]; + +// executed on main run loop +static wiced_result_t h4_main_deliver_packet(void *arg){ + // deliver packet + packet_handler(hci_packet[0], &hci_packet[1], rx_worker_read_pos-1); + // trigger receive of next packet + wiced_rtos_send_asynchronous_event(&rx_worker_thread, &h4_rx_worker_receive_packet, NULL); + return WICED_SUCCESS; +} + +// executed on main run loop +static wiced_result_t h4_main_notify_packet_send(void *arg){ + // prepare for next packet + tx_worker_data_size = 0; + // notify upper stack that it might be possible to send again + uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0}; + packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); + return WICED_SUCCESS; +} + +// executed on rx worker thread +static void h4_rx_worker_receive_bytes(int bytes_to_read){ + platform_uart_receive_bytes(wiced_bt_uart_driver, &hci_packet[rx_worker_read_pos], bytes_to_read, WICED_NEVER_TIMEOUT); + rx_worker_read_pos += bytes_to_read; +} +static wiced_result_t h4_rx_worker_receive_packet(void * arg){ + while (1){ + rx_worker_read_pos = 0; + h4_rx_worker_receive_bytes(1); + switch (hci_packet[0]){ + case HCI_EVENT_PACKET: + h4_rx_worker_receive_bytes(HCI_EVENT_HEADER_SIZE); + h4_rx_worker_receive_bytes(hci_packet[2]); + break; + case HCI_ACL_DATA_PACKET: + h4_rx_worker_receive_bytes(HCI_ACL_HEADER_SIZE); + h4_rx_worker_receive_bytes(READ_BT_16( hci_packet, 3)); + break; + case HCI_SCO_DATA_PACKET: + h4_rx_worker_receive_bytes(HCI_SCO_HEADER_SIZE); + h4_rx_worker_receive_bytes(hci_packet[3]); + break; + default: + // try again + log_error("h4_rx_worker_receive_packet: invalid packet type 0x%02x", hci_packet[0]); + continue; + } + // deliver packet on main thread + wiced_execute_code_on_run_loop(&h4_main_deliver_packet, NULL); + return WICED_SUCCESS; + } +} + +// executed on tx worker thread +static wiced_result_t h4_tx_worker_send_packet(void * arg){ + // blocking send + platform_uart_transmit_bytes(wiced_bt_uart_driver, tx_worker_data_buffer, tx_worker_data_size); + // let stack know + wiced_execute_code_on_run_loop(&h4_main_notify_packet_send, NULL); + return WICED_SUCCESS; +} + +static int h4_set_baudrate(uint32_t baudrate){ +#if 0 + log_info("h4_set_baudrate %u", baudrate); +#endif + return 0; +} + +static int h4_open(void *transport_config){ + wiced_uart_config_t uart_config = + { + .baud_rate = 115200, + .data_width = DATA_WIDTH_8BIT, + .parity = NO_PARITY, + .stop_bits = STOP_BITS_1, + .flow_control = FLOW_CONTROL_CTS_RTS, + }; + + // configure HOST and DEVICE WAKE PINs + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_HOST_WAKE], INPUT_HIGH_IMPEDANCE); + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE], OUTPUT_PUSH_PULL); + platform_gpio_output_low( wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE]); + wiced_rtos_delay_milliseconds( 100 ); + + // power cycle Bluetooth + platform_gpio_init( wiced_bt_control_pins[ WICED_BT_PIN_POWER ], OUTPUT_PUSH_PULL ); + platform_gpio_output_low( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); + wiced_rtos_delay_milliseconds( 100 ); + platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); + + wiced_rtos_delay_milliseconds( 500 ); + + // init UART + platform_uart_init( wiced_bt_uart_driver, wiced_bt_uart_peripheral, &uart_config, NULL ); + + // create worker threads for rx/tx + wiced_rtos_create_worker_thread(&tx_worker_thread, WICED_NETWORK_WORKER_PRIORITY, 1000, 1); + wiced_rtos_create_worker_thread(&rx_worker_thread, WICED_NETWORK_WORKER_PRIORITY, 1000, 5); + + // start receiving packet + wiced_rtos_send_asynchronous_event(&rx_worker_thread, &h4_rx_worker_receive_packet, NULL); + + // tx is ready + tx_worker_data_size = 0; + return 0; +} + +static int h4_close(void *transport_config){ + // not implementd + return 0; +} + +static int h4_send_packet(uint8_t packet_type, uint8_t * data, int size){ + // store packet type before actual data and increase size + size++; + data--; + *data = packet_type; + + // store in request + tx_worker_data_buffer = data; + tx_worker_data_size = size; + // send packet as single block + wiced_rtos_send_asynchronous_event(&tx_worker_thread, &h4_tx_worker_send_packet, NULL); + return 0; +} + +static void h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ + packet_handler = handler; +} + +static int h4_can_send_packet_now(uint8_t packet_type){ + return tx_worker_data_size == 0; +} + +static const char * h4_get_transport_name(void){ + return "H4"; +} + +static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ +} + +// get h4 singleton +hci_transport_t * hci_transport_h4_wiced_instance() { + if (hci_transport_h4 == NULL) { + hci_transport_h4 = (hci_transport_h4_t*)malloc( sizeof(hci_transport_h4_t)); + hci_transport_h4->ds = NULL; + hci_transport_h4->transport.open = h4_open; + hci_transport_h4->transport.close = h4_close; + hci_transport_h4->transport.send_packet = h4_send_packet; + hci_transport_h4->transport.register_packet_handler = h4_register_packet_handler; + hci_transport_h4->transport.get_transport_name = h4_get_transport_name; + hci_transport_h4->transport.set_baudrate = h4_set_baudrate; + hci_transport_h4->transport.can_send_packet_now = h4_can_send_packet_now; + } + return (hci_transport_t *) hci_transport_h4; +} diff --git a/port/wiced/main.c b/port/wiced/main.c new file mode 100644 index 000000000..e5d0c5d5e --- /dev/null +++ b/port/wiced/main.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2015 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 + * + */ + +#include "wiced.h" +#include "platform_bluetooth.h" +#include "btstack.h" + + +#if 0 +static void dummy_handler(void); + +// handlers +static void (*rx_done_handler)(void) = dummy_handler; +static void (*tx_done_handler)(void) = dummy_handler; +static void (*cts_irq_handler)(void) = dummy_handler; +static int hal_uart_needed_during_sleep = 1; + +// static wiced_worker_thread_t tick_worker; + +// worker thread to do blocking write +static wiced_worker_thread_t rx_worker; +static uint8_t * rx_worker_data_buffer; +static uint16_t rx_worker_data_size; + +// worker thread to do blocking read +static wiced_worker_thread_t tx_worker; +static const uint8_t * tx_worker_data_buffer; +static uint16_t tx_worker_data_size; + +static void dummy_handler(void){}; + +void hal_uart_dma_init(void){ + + wiced_uart_config_t uart_config = + { + .baud_rate = 115200, + .data_width = DATA_WIDTH_8BIT, + .parity = NO_PARITY, + .stop_bits = STOP_BITS_1, + .flow_control = FLOW_CONTROL_CTS_RTS, + }; + + // test RTS first + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_UART_RTS], OUTPUT_PUSH_PULL); + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_UART_TX], OUTPUT_PUSH_PULL); + while (1) { + platform_gpio_output_low( wiced_bt_control_pins[WICED_BT_PIN_UART_RTS]); + platform_gpio_output_low( wiced_bt_control_pins[WICED_BT_PIN_UART_TX]); + platform_gpio_output_high(wiced_bt_control_pins[WICED_BT_PIN_UART_RTS]); + platform_gpio_output_high(wiced_bt_control_pins[WICED_BT_PIN_UART_TX]); + } + + // configure HOST and DEVICE WAKE PINs + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_HOST_WAKE], INPUT_HIGH_IMPEDANCE); + platform_gpio_init( wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE], OUTPUT_PUSH_PULL); + platform_gpio_output_low( wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE]); + wiced_rtos_delay_milliseconds( 100 ); + + // power cycle Bluetooth + platform_gpio_init( wiced_bt_control_pins[ WICED_BT_PIN_POWER ], OUTPUT_PUSH_PULL ); + platform_gpio_output_low( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); + wiced_rtos_delay_milliseconds( 100 ); + platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); + + wiced_rtos_delay_milliseconds( 500 ); + + // init UART + platform_uart_init( wiced_bt_uart_driver, wiced_bt_uart_peripheral, &uart_config, NULL ); + + // create worker threads for rx/tx + wiced_rtos_create_worker_thread(&tx_worker, WICED_NETWORK_WORKER_PRIORITY, 1000, 1); + wiced_rtos_create_worker_thread(&rx_worker, WICED_NETWORK_WORKER_PRIORITY, 1000, 5); +} + +void hal_uart_dma_set_sleep(uint8_t sleep){ + hal_uart_needed_during_sleep = !sleep; +} + +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)){ + tx_done_handler = the_block_handler; +} + +void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ + cts_irq_handler = the_irq_handler; +} + +int hal_uart_dma_set_baud(uint32_t baud){ + return 0; +} + +static wiced_result_t tx_worker_task(void * arg){ + // printf("tx_worker_task len %u\n", tx_worker_data_size); + platform_uart_transmit_bytes(wiced_bt_uart_driver, tx_worker_data_buffer, tx_worker_data_size); + // printf("tx_worker_task done\n"); + tx_done_handler(); + return WICED_SUCCESS; +} + +static wiced_result_t rx_worker_task(void * arg){ + // printf("rx_worker_task len %u\n", rx_worker_data_size); + // printf("/%u\\\n", rx_worker_data_size); + platform_uart_receive_bytes(wiced_bt_uart_driver, rx_worker_data_buffer, rx_worker_data_size, WICED_NEVER_TIMEOUT); + // printf("rx_worker_task done\n"); + rx_done_handler(); + return WICED_SUCCESS; +} + +void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){ + // printf("hal_uart_dma_send_block len %u\n", size); + tx_worker_data_buffer = data; + tx_worker_data_size = size; +#if 0 + wiced_rtos_send_asynchronous_event(&tx_worker, &tx_worker_task, NULL); + printf("hal_uart_dma_send_block B\n"); + wiced_rtos_delay_milliseconds(100); +#endif + platform_uart_transmit_bytes(wiced_bt_uart_driver, tx_worker_data_buffer, tx_worker_data_size); + // printf("hal_uart_dma_send_block done\n"); + tx_done_handler(); + } + +void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){ + // printf("hal_uart_dma_receive_block len %u\n", size); + rx_worker_data_buffer = data; + rx_worker_data_size = size; + + if ( wiced_rtos_is_current_thread( &rx_worker.thread ) == WICED_SUCCESS ){ + // re-entrant call .. don't post to queue, just call it directlyh + // printf("/%u\\\n", rx_worker_data_size); + rx_worker_task(NULL); + } else { + // printf("\\%u/\n", rx_worker_data_size); + wiced_rtos_send_asynchronous_event(&rx_worker, &rx_worker_task, NULL); + wiced_rtos_delay_milliseconds(100); + } + // printf("hal_uart_dma_receive_block done\n"); +} +#endif +#if 0 + while (1) { + // send HCI Reset + uint8_t hci_reset[] = { 0x01, 0x03, 0x0c, 0x00}; + wiced_result_t res; + res = platform_uart_transmit_bytes(wiced_bt_uart_driver, hci_reset, sizeof(hci_reset) ); + printf("Send reset.. res %u\n", res); + + // receive event + uint8_t buffer[6]; + res = platform_uart_receive_bytes(wiced_bt_uart_driver, buffer, 6, 5000); + int i; + for (i=0;i // NULL + +#include "bk_linked_list.h" +#include "debug.h" +#include "run_loop.h" +#include "run_loop_private.h" + +typedef struct function_call { + wiced_result_t (*fn)(void * arg); + void * arg; +} function_call_t; + +static wiced_queue_t run_loop_queue; + +// the run loop +static bk_linked_list_t timers; + +/** + * Add data_source to run_loop + */ +static void wiced_add_data_source(data_source_t *ds){ + log_error("run_loop_add_data_source not supported in run_loop_wiced"); +} + +/** + * Remove data_source from run loop + */ +static int wiced_remove_data_source(data_source_t *ds){ + log_error("run_loop_add_data_source not supported in run_loop_wiced"); + return 0; +} + +static uint32_t wiced_get_time_ms(void){ + wiced_time_t time; + wiced_time_get_time(&time); + return time; +} + +// set timer +static void wiced_set_timer(timer_source_t *ts, uint32_t timeout_in_ms){ + ts->timeout = wiced_get_time_ms() + timeout_in_ms + 1; +} + +/** + * Add timer to run_loop (keep list sorted) + */ +static void wiced_add_timer(timer_source_t *ts){ + linked_item_t *it; + for (it = (linked_item_t *) &timers; it->next ; it = it->next){ + // don't add timer that's already in there + if ((timer_source_t *) it->next == ts){ + log_error( "run_loop_timer_add error: timer to add already in list!"); + return; + } + if (ts->timeout < ((timer_source_t *) it->next)->timeout) { + break; + } + } + ts->item.next = it->next; + it->next = (linked_item_t *) ts; +} + +/** + * Remove timer from run loop + */ +static int wiced_remove_timer(timer_source_t *ts){ + return linked_list_remove(&timers, (linked_item_t *) ts); +} + +static void wiced_dump_timer(void){ +#ifdef ENABLE_LOG_INFO + linked_item_t *it; + int i = 0; + for (it = (linked_item_t *) timers; it ; it = it->next){ + timer_source_t *ts = (timer_source_t*) it; + log_info("timer %u, timeout %u\n", i, (unsigned int) ts->timeout); + } +#endif +} + +// schedules execution similar to wiced_rtos_send_asynchronous_event for worker threads +void wiced_execute_code_on_run_loop(wiced_result_t (*fn)(void *arg), void * arg){ + function_call_t message; + message.fn = fn; + message.arg = arg; + wiced_rtos_push_to_queue(&run_loop_queue, &message, WICED_NEVER_TIMEOUT); +} + +/** + * Execute run_loop + */ +static void wiced_execute(void) { + while (1) { + // get next timeout + uint32_t timeout_ms = WICED_NEVER_TIMEOUT; + if (timers) { + timer_source_t * ts = (timer_source_t *) timers; + uint32_t now = wiced_get_time_ms(); + if (ts->timeout < now){ + // remove timer before processing it to allow handler to re-register with run loop + run_loop_remove_timer(ts); + // printf("RL: timer %p\n", ts->process); + ts->process(ts); + continue; + } + timeout_ms = ts->timeout - now; + } + + // pop function call + function_call_t message = { NULL, NULL }; + wiced_rtos_pop_from_queue( &run_loop_queue, &message, timeout_ms); + if (message.fn){ + // execute code on run loop + // printf("RL: execute %p\n", message.fn); + message.fn(message.arg); + } + } +} + +static void wiced_run_loop_init(void){ + timers = NULL; + + // queue to receive events: up to 2 calls from transport, up to 3 for app + wiced_rtos_init_queue(&run_loop_queue, "BTstack Run Loop", sizeof(function_call_t), 5); +} + +const run_loop_t run_loop_wiced = { + &wiced_run_loop_init, + &wiced_add_data_source, + &wiced_remove_data_source, + &wiced_set_timer, + &wiced_add_timer, + &wiced_remove_timer, + &wiced_execute, + &wiced_dump_timer, + &wiced_get_time_ms, +}; diff --git a/port/wiced/wiced.mk b/port/wiced/wiced.mk new file mode 100644 index 000000000..21a5e49c1 --- /dev/null +++ b/port/wiced/wiced.mk @@ -0,0 +1,28 @@ + +NAME := BTstack_for_BCM$(BT_CHIP)$(BT_CHIP_REVISION) + +GLOBAL_INCLUDES += . ../../src ../../platform/embedded + +$(NAME)_SOURCES += \ + main.c \ + run_loop_wiced.c \ + hci_transport_h4_wiced.c \ + ../../src/bk_linked_list.c \ + ../../src/btstack_memory.c \ + ../../src/classic/remote_device_db_memory.c \ + ../../src/classic/rfcomm.c \ + ../../src/classic/sdp.c \ + ../../src/classic/sdp_client.c \ + ../../src/classic/sdp_parser.c \ + ../../src/classic/sdp_query_rfcomm.c \ + ../../src/classic/sdp_query_util.c \ + ../../src/classic/sdp_util.c \ + ../../src/hci.c \ + ../../src/hci_cmds.c \ + ../../src/hci_dump.c \ + ../../src/l2cap.c \ + ../../src/l2cap_signaling.c \ + ../../src/memory_pool.c \ + ../../src/run_loop.c \ + ../../src/utils.c \ + ../../../drivers/bluetooth/firmware/$(BT_CHIP)$(BT_CHIP_REVISION)/bt_firmware_image.c \