diff --git a/components/bt/bluedroid/bta/sys/bta_sys_main.c b/components/bt/bluedroid/bta/sys/bta_sys_main.c index 8029db37c..c5a94648c 100755 --- a/components/bt/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/bluedroid/bta/sys/bta_sys_main.c @@ -604,7 +604,7 @@ void bta_sys_sendmsg(void *p_msg) if (btu_bta_msg_queue) { fixed_queue_enqueue(btu_bta_msg_queue, p_msg); //ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } } diff --git a/components/bt/bluedroid/device/controller.c b/components/bt/bluedroid/device/controller.c index 4721f4057..2d928b305 100755 --- a/components/bt/bluedroid/device/controller.c +++ b/components/bt/bluedroid/device/controller.c @@ -27,8 +27,8 @@ #include "hci_packet_parser.h" #include "btm_ble_api.h" #include "version.h" +#include "future.h" -//#include "bluedroid_test.h" /*FOr Test Case*/ const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" }; #if (BLE_INCLUDED) @@ -72,304 +72,176 @@ static bool ble_supported; static bool simple_pairing_supported; static bool secure_connections_supported; -devctl_reset_callback reset_cb; -static uint8_t page_number = 0; -static void devctl_hdl_cmd_complete(BT_HDR *response, void *context) { - BT_HDR *command = NULL; - command_opcode_t opcode; - uint8_t *stream = response->data + response->offset; +#define AWAIT_COMMAND(command) future_await(hci->transmit_command_futured(command)) - STREAM_SKIP_UINT16(stream); //skip event_code and total length field - STREAM_SKIP_UINT8(stream); //skip command_credits field - STREAM_TO_UINT16(opcode, stream); +// Module lifecycle functions - switch (opcode) { - case HCI_RESET: +static void start_up(void) { + BT_HDR *response; + + // Send the initial reset command + response = AWAIT_COMMAND(packet_factory->make_reset()); + packet_parser->parse_generic_command_complete(response); + + // Request the classic buffer size next + response = AWAIT_COMMAND(packet_factory->make_read_buffer_size()); + packet_parser->parse_read_buffer_size_response( + response, &acl_data_size_classic, &acl_buffer_count_classic); + + // Tell the controller about our buffer sizes and buffer counts next + // TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10? + response = AWAIT_COMMAND( + packet_factory->make_host_buffer_size( + L2CAP_MTU_SIZE, + SCO_HOST_BUFFER_SIZE, + L2CAP_HOST_FC_ACL_BUFS, + 10 + ) + ); + + packet_parser->parse_generic_command_complete(response); + + // Read the local version info off the controller next, including + // information such as manufacturer and supported HCI version + response = AWAIT_COMMAND(packet_factory->make_read_local_version_info()); + packet_parser->parse_read_local_version_info_response(response, &bt_version); + + // Read the bluetooth address off the controller next + response = AWAIT_COMMAND(packet_factory->make_read_bd_addr()); + packet_parser->parse_read_bd_addr_response(response, &address); + + // Request the controller's supported commands next + response = AWAIT_COMMAND(packet_factory->make_read_local_supported_commands()); + packet_parser->parse_read_local_supported_commands_response( + response, + supported_commands, + HCI_SUPPORTED_COMMANDS_ARRAY_SIZE + ); + + // Read page 0 of the controller features next + uint8_t page_number = 0; + response = AWAIT_COMMAND(packet_factory->make_read_local_extended_features(page_number)); + packet_parser->parse_read_local_extended_features_response( + response, + &page_number, + &last_features_classic_page_index, + features_classic, + MAX_FEATURES_CLASSIC_PAGE_COUNT + ); + + assert(page_number == 0); + page_number++; + + // Inform the controller what page 0 features we support, based on what + // it told us it supports. We need to do this first before we request the + // next page, because the controller's response for page 1 may be + // dependent on what we configure from page 0 + simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED(features_classic[0].as_array); + if (simple_pairing_supported) { + response = AWAIT_COMMAND(packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED)); packet_parser->parse_generic_command_complete(response); - command = packet_factory->make_read_buffer_size(); - break; - case HCI_READ_BUFFER_SIZE: - packet_parser->parse_read_buffer_size_response( - response, &acl_data_size_classic, &acl_buffer_count_classic); - command = packet_factory->make_host_buffer_size( - L2CAP_MTU_SIZE, SCO_HOST_BUFFER_SIZE, L2CAP_HOST_FC_ACL_BUFS, 10); - break; - case HCI_HOST_BUFFER_SIZE: + } + +#if (BLE_INCLUDED == TRUE) + if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) { + uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0; + response = AWAIT_COMMAND( + packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host) + ); + packet_parser->parse_generic_command_complete(response); - command = packet_factory->make_read_local_version_info(); - break; - case HCI_READ_LOCAL_VERSION_INFO: - packet_parser->parse_read_local_version_info_response(response, &bt_version); - command = packet_factory->make_read_bd_addr(); - break; - case HCI_READ_BD_ADDR: - packet_parser->parse_read_bd_addr_response(response, &address); - command = packet_factory->make_read_local_supported_commands(); - break; - case HCI_READ_LOCAL_SUPPORTED_CMDS: - packet_parser->parse_read_local_supported_commands_response( - response, supported_commands, HCI_SUPPORTED_COMMANDS_ARRAY_SIZE); - page_number = 0; - command = packet_factory->make_read_local_extended_features(page_number); - break; - case HCI_READ_LOCAL_EXT_FEATURES: - if (response) { - packet_parser->parse_read_local_extended_features_response( - response, &page_number,&last_features_classic_page_index, - features_classic, MAX_FEATURES_CLASSIC_PAGE_COUNT); - response = NULL; - page_number++; - } - if (1 == page_number) { - simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED(features_classic[0].as_array); - if (simple_pairing_supported) { - command = packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED); - break; - } - // BLOCK_BEGIN -#if (BLE_INCLUDED == TRUE) - if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) { - uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0; - command = packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host); - break; - } + } #endif - } - if (page_number <= last_features_classic_page_index && - page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) { - command = packet_factory->make_read_local_extended_features(page_number); - break; - } else { -#if (SC_MODE_INCLUDED == TRUE) - secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array); - if (secure_connections_supported) { - command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED); - break; - } -#endif -#if (BLE_INCLUDED == TRUE) - ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); - if (ble_supported) { - // Request the ble white list size next - command = packet_factory->make_ble_read_white_list_size(); - break; - } -#endif - if (simple_pairing_supported) { - command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK); - break; - } - } - // BLOCK_END + // Done telling the controller about what page 0 features we support + // Request the remaining feature pages + while (page_number <= last_features_classic_page_index && + page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) { + response = AWAIT_COMMAND(packet_factory->make_read_local_extended_features(page_number)); + packet_parser->parse_read_local_extended_features_response( + response, + &page_number, + &last_features_classic_page_index, + features_classic, + MAX_FEATURES_CLASSIC_PAGE_COUNT + ); - case HCI_WRITE_SIMPLE_PAIRING_MODE: - if (response) { - packet_parser->parse_generic_command_complete(response); - response = NULL; - } - // BLOCK_BEGIN -#if (BLE_INCLUDED == TRUE) - if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) { - uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0; - command = packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host); - break; - } -#endif - if (page_number <= last_features_classic_page_index && - page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) { - command = packet_factory->make_read_local_extended_features(page_number); - break; - } else { -#if (SC_MODE_INCLUDED == TRUE) - secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array); - if (secure_connections_supported) { - command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED); - break; - } -#endif -#if (BLE_INCLUDED == TRUE) - ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); - if (ble_supported) { - // Request the ble white list size next - command = packet_factory->make_ble_read_white_list_size(); - break; - } -#endif - if (simple_pairing_supported) { - command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK); - break; - } - } + page_number++; + } #if (SC_MODE_INCLUDED == TRUE) - case HCI_WRITE_SECURE_CONNS_SUPPORT: - if (response) { - packet_parser->parse_generic_command_complete(response); - response = NULL; - } -#if (BLE_INCLUDED == TRUE) - ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); - if (ble_supported) { - // Request the ble white list size next - command = packet_factory->make_ble_read_white_list_size(); - break; - } -#endif /* (BLE_INCLUDED == TRUE) */ - if (simple_pairing_supported) { - command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK); - break; - } -#endif /* (SC_MODE_INCLUDED == TRUE) */ + secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array); + if (secure_connections_supported) { + response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED)); + packet_parser->parse_generic_command_complete(response); + } +#endif #if (BLE_INCLUDED == TRUE) - case HCI_WRITE_LE_HOST_SUPPORT: - if (response) { - packet_parser->parse_generic_command_complete(response); - response = NULL; - } - if (page_number <= last_features_classic_page_index && - page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) { - command = packet_factory->make_read_local_extended_features(page_number); - break; - } else { -#if (SC_MODE_INCLUDED == TRUE) - secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array); - if (secure_connections_supported) { - command = packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED); - break; - } -#endif - ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); - if (ble_supported) { - // Request the ble white list size next - command = packet_factory->make_ble_read_white_list_size(); - break; - } - if (simple_pairing_supported) { - command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK); - break; - } - } - case HCI_BLE_READ_WHITE_LIST_SIZE: - if (response) { - packet_parser->parse_ble_read_white_list_size_response(response, &ble_white_list_size); - response = NULL; - } - if (ble_supported) { - // Request the ble buffer size next - command = packet_factory->make_ble_read_buffer_size(); - break; - } - // Fall Through if no next command generated - case HCI_BLE_READ_BUFFER_SIZE: - if (response) { - packet_parser->parse_ble_read_buffer_size_response( - response, &acl_data_size_ble, &acl_buffer_count_ble); - response = NULL; - } + ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); + if (ble_supported) { + // Request the ble white list size next + response = AWAIT_COMMAND(packet_factory->make_ble_read_white_list_size()); + packet_parser->parse_ble_read_white_list_size_response(response, &ble_white_list_size); + + // Request the ble buffer size next + response = AWAIT_COMMAND(packet_factory->make_ble_read_buffer_size()); + packet_parser->parse_ble_read_buffer_size_response( + response, + &acl_data_size_ble, + &acl_buffer_count_ble + ); + // Response of 0 indicates ble has the same buffer size as classic if (acl_data_size_ble == 0) acl_data_size_ble = acl_data_size_classic; - if (ble_supported) { - // Request the ble supported states next - command = packet_factory->make_ble_read_supported_states(); - break; - } - // Fall Through if no next command generated - case HCI_BLE_READ_SUPPORTED_STATES: - if (response) { - packet_parser->parse_ble_read_supported_states_response( - response, ble_supported_states, sizeof(ble_supported_states)); - response = NULL; + + // Request the ble supported states next + response = AWAIT_COMMAND(packet_factory->make_ble_read_supported_states()); + packet_parser->parse_ble_read_supported_states_response( + response, + ble_supported_states, + sizeof(ble_supported_states) + ); + + // Request the ble supported features next + response = AWAIT_COMMAND(packet_factory->make_ble_read_local_supported_features()); + packet_parser->parse_ble_read_local_supported_features_response( + response, + &features_ble + ); + + if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) { + response = AWAIT_COMMAND(packet_factory->make_ble_read_resolving_list_size()); + packet_parser->parse_ble_read_resolving_list_size_response( + response, + &ble_resolving_list_max_size); } - if (ble_supported) { - // Request the ble supported features next - command = packet_factory->make_ble_read_local_supported_features(); - break; - } - // Fall Through if no next command generated - case HCI_BLE_READ_LOCAL_SPT_FEAT: - if (response) { - packet_parser->parse_ble_read_local_supported_features_response( - response, &features_ble); - response = NULL; + if (HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) { + response = AWAIT_COMMAND(packet_factory->make_ble_read_suggested_default_data_length()); + packet_parser->parse_ble_read_suggested_default_data_length_response( + response, + &ble_suggested_default_data_length); } - if (ble_supported && - HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) { - command = packet_factory->make_ble_read_resolving_list_size(); - break; - } - case HCI_BLE_READ_RESOLVING_LIST_SIZE: - if (response) { - packet_parser->parse_ble_read_resolving_list_size_response( - response, &ble_resolving_list_max_size); - response = NULL; - } - - if (ble_supported && - HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) { - command = packet_factory->make_ble_read_suggested_default_data_length(); - break; - } - case HCI_BLE_READ_DEFAULT_DATA_LENGTH: - if (response) { - packet_parser->parse_ble_read_suggested_default_data_length_response( - response, &ble_suggested_default_data_length); - response = NULL; - } - - if (ble_supported) { - // Set the ble event mask next - command = packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK); - break; - } - case HCI_BLE_SET_EVENT_MASK: - if (response) { - packet_parser->parse_generic_command_complete(response); - response = NULL; - } - if (simple_pairing_supported) { - command = packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK); - break; - } + // Set the ble event mask next + response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK)); + packet_parser->parse_generic_command_complete(response); + } #endif - case HCI_SET_EVENT_MASK: - if (response) { - packet_parser->parse_generic_command_complete(response); - response = command = NULL; - } - //At this point, Reset Thread should be completed well. - readable = true; - page_number = 0; - if (reset_cb) - reset_cb(); - break; - default: - LOG_ERROR("%s: No available opcode matched.", __func__); - break; + if (simple_pairing_supported) { + response = AWAIT_COMMAND(packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK)); + packet_parser->parse_generic_command_complete(response); } - if (command) - hci->transmit_command(command, devctl_hdl_cmd_complete, NULL, NULL); + readable = true; + // return future_new_immediate(FUTURE_SUCCESS); + return; } -// Interface functions -static void devctl_reset(devctl_reset_callback reset_callback) { - reset_cb = reset_callback; - BT_HDR *command = packet_factory->make_read_buffer_size(); - //BT_HDR *command = packet_factory->make_reset(); - LOG_ERROR("Device Control Send Device Read Buffer Size Command\n"); - page_number = 0; - if (command) - hci->transmit_command(command, devctl_hdl_cmd_complete, NULL, NULL); -} - -static void devctl_shutdown(void) { - reset_cb = NULL; +static void shut_down(void) { readable = false; } @@ -531,8 +403,8 @@ static void set_ble_resolving_list_max_size(int resolving_list_max_size) { } static const controller_t interface = { - devctl_reset, - devctl_shutdown, + start_up, + shut_down, get_is_ready, get_address, diff --git a/components/bt/bluedroid/device/include/controller.h b/components/bt/bluedroid/device/include/controller.h index 939853ab0..03a63c0fc 100755 --- a/components/bt/bluedroid/device/include/controller.h +++ b/components/bt/bluedroid/device/include/controller.h @@ -29,11 +29,9 @@ #include "hci_packet_factory.h" #include "hci_packet_parser.h" -typedef void (*devctl_reset_callback)(void); - typedef struct controller_t { - void (*devctl_reset)(devctl_reset_callback reset_callback); - void (*devctl_shutdown)(void); + void (*start_up)(void); + void (*shut_down)(void); bool (*get_is_ready)(void); const bt_bdaddr_t *(*get_address)(void); diff --git a/components/bt/bluedroid/hci/hci_layer.c b/components/bt/bluedroid/hci/hci_layer.c index 17d1022a9..8aa4ed163 100755 --- a/components/bt/bluedroid/hci/hci_layer.c +++ b/components/bt/bluedroid/hci/hci_layer.c @@ -34,6 +34,7 @@ typedef struct { uint16_t opcode; + future_t *complete_future; command_complete_cb complete_callback; command_status_cb status_callback; void *context; @@ -43,7 +44,7 @@ typedef struct { typedef struct { bool timer_is_set; - osi_alarm_t *command_response_timer; + osi_alarm_t *command_response_timer; list_t *commands_pending_response; pthread_mutex_t commands_pending_response_lock; } command_waiting_response_t; @@ -280,8 +281,27 @@ static void transmit_command( hci_host_task_post(); } +static future_t *transmit_command_futured(BT_HDR *command) { + waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t)); + assert(wait_entry != NULL); + + future_t *future = future_new(); + + uint8_t *stream = command->data + command->offset; + STREAM_TO_UINT16(wait_entry->opcode, stream); + wait_entry->complete_future = future; + wait_entry->command = command; + + // Store the command message type in the event field + // in case the upper layer didn't already + command->event = MSG_STACK_TO_HC_HCI_CMD; + + fixed_queue_enqueue(hci_host_env.command_queue, wait_entry); + hci_host_task_post(); + return future; +} + static void transmit_downward(uint16_t type, void *data) { - BT_HDR *tmp = (BT_HDR *)data; if (type == MSG_STACK_TO_HC_HCI_CMD) { transmit_command((BT_HDR *)data, NULL, NULL, NULL); LOG_WARN("%s legacy transmit of command. Use transmit_command instead.\n", __func__); @@ -441,6 +461,8 @@ static bool filter_incoming_event(BT_HDR *packet) { LOG_WARN("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode); else if (wait_entry->complete_callback) wait_entry->complete_callback(packet, wait_entry->context); + else if (wait_entry->complete_future) + future_ready(wait_entry->complete_future, packet); goto intercepted; } else if (event_code == HCI_COMMAND_STATUS_EVT) { @@ -473,7 +495,7 @@ intercepted: if (wait_entry) { // If it has a callback, it's responsible for freeing the packet if (event_code == HCI_COMMAND_STATUS_EVT || - !wait_entry->complete_callback) + (!wait_entry->complete_callback && !wait_entry->complete_future)) buffer_allocator->free(packet); // If it has a callback, it's responsible for freeing the command @@ -494,7 +516,7 @@ static void dispatch_reassembled(BT_HDR *packet) { if (hci_host_env.upwards_data_queue) { fixed_queue_enqueue(hci_host_env.upwards_data_queue, packet); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); //Tell Up-layer received packet. } else { LOG_DEBUG("%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__); @@ -548,6 +570,7 @@ static void init_layer_interface() { if (!interface_created) { interface.set_data_queue = set_data_queue; interface.transmit_command = transmit_command; + interface.transmit_command_futured = transmit_command_futured; interface.transmit_downward = transmit_downward; interface_created = true; } diff --git a/components/bt/bluedroid/hci/include/hci_layer.h b/components/bt/bluedroid/hci/include/hci_layer.h index 7c3739139..ed291077f 100755 --- a/components/bt/bluedroid/hci/include/hci_layer.h +++ b/components/bt/bluedroid/hci/include/hci_layer.h @@ -23,7 +23,7 @@ #include "allocator.h" #include "fixed_queue.h" #include "osi.h" - +#include "future.h" ///// LEGACY DEFINITIONS ///// /* Message event mask across Host/Controller lib and stack */ @@ -88,6 +88,8 @@ typedef struct hci_t { void *context ); + future_t *(*transmit_command_futured)(BT_HDR *command); + // Send some data downward through the HCI layer void (*transmit_downward)(uint16_t type, void *data); } hci_t; diff --git a/components/bt/bluedroid/hci/packet_fragmenter.c b/components/bt/bluedroid/hci/packet_fragmenter.c index e9e0d9548..675f22286 100755 --- a/components/bt/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/bluedroid/hci/packet_fragmenter.c @@ -66,7 +66,7 @@ static BT_HDR *fragment_get_current_packet() { } static void fragment_and_dispatch(BT_HDR *packet) { - uint16_t continuation_handle, current_pkt_size; + uint16_t continuation_handle; uint16_t max_data_size, max_packet_size, remaining_length; uint16_t event = packet->event & MSG_EVT_MASK; uint8_t *stream = packet->data + packet->offset; diff --git a/components/bt/bluedroid/osi/future.c b/components/bt/bluedroid/osi/future.c new file mode 100644 index 000000000..7c816f9e4 --- /dev/null +++ b/components/bt/bluedroid/osi/future.c @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +// #define LOG_TAG "bt_osi_future" +// #include +#include "bt_trace.h" + +#include "allocator.h" +#include "future.h" +#include "osi.h" +//#include "osi/include/log.h" +#include "osi_arch.h" + +struct future_t { + bool ready_can_be_called; + osi_sem_t semaphore; // NULL semaphore means immediate future + void *result; +}; + +static void future_free(future_t *future); + +future_t *future_new(void) { + future_t *ret = osi_calloc(sizeof(future_t)); + if (!ret) { + LOG_ERROR("%s unable to allocate memory for return value.", __func__); + goto error; + } + + if (osi_sem_new(&ret->semaphore, 1, 0)!=0) { + LOG_ERROR("%s unable to allocate memory for the semaphore.", __func__); + goto error; + } + + ret->ready_can_be_called = true; + return ret; +error:; + future_free(ret); + return NULL; +} + +future_t *future_new_immediate(void *value) { + future_t *ret = osi_calloc(sizeof(future_t)); + if (!ret) { + LOG_ERROR("%s unable to allocate memory for return value.", __func__); + goto error; + } + + ret->result = value; + ret->ready_can_be_called = false; + return ret; +error:; + future_free(ret); + return NULL; +} + +void future_ready(future_t *future, void *value) { + assert(future != NULL); + assert(future->ready_can_be_called); + + future->ready_can_be_called = false; + future->result = value; + osi_sem_signal(&future->semaphore); +} + +void *future_await(future_t *future) { + assert(future != NULL); + + // If the future is immediate, it will not have a semaphore + if (future->semaphore) + osi_sem_wait(&future->semaphore, 0); + + void *result = future->result; + future_free(future); + return result; +} + +static void future_free(future_t *future) { + if (!future) + return; + + if (!future->semaphore) + osi_sem_free(&future->semaphore); + + osi_free(future); +} diff --git a/components/bt/bluedroid/osi/include/future.h b/components/bt/bluedroid/osi/include/future.h new file mode 100644 index 000000000..d4601a93f --- /dev/null +++ b/components/bt/bluedroid/osi/include/future.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef __FUTURE_H__ +#define __FUTURE_H__ +// #pragma once + +typedef struct future_t future_t; + +#define FUTURE_SUCCESS ((void *)1) +#define FUTURE_FAIL ((void *)0) + +// Constructs a new future_t object. Returns NULL on failure. +future_t *future_new(void); + +// Constructs a new future_t object with an immediate |value|. No waiting will +// occur in the call to |future_await| because the value is already present. +// Returns NULL on failure. +future_t *future_new_immediate(void *value); + +// Signals that the |future| is ready, passing |value| back to the context +// waiting for the result. Must only be called once for every future. +// |future| may not be NULL. +void future_ready(future_t *future, void *value); + +// Waits for the |future| to be ready. Returns the value set in |future_ready|. +// Frees the future before return. |future| may not be NULL. +void *future_await(future_t *async_result); + +#endif /* __FUTURE_H__ */ diff --git a/components/bt/bluedroid/osi/include/thread.h b/components/bt/bluedroid/osi/include/thread.h index 5d869ccb3..e2c932367 100644 --- a/components/bt/bluedroid/osi/include/thread.h +++ b/components/bt/bluedroid/osi/include/thread.h @@ -15,7 +15,12 @@ struct task_evt { }; typedef struct task_evt TaskEvt_t; -void btu_task_post(void); +enum { + SIG_BTU_START_UP = 0xfe, + SIG_BTU_WORK = 0xff +}; + +void btu_task_post(uint32_t sig); void hci_host_task_post(void); void hci_hal_h4_task_post(void); void hci_drv_task_post(void); diff --git a/components/bt/bluedroid/stack/btm/btm_devctl.c b/components/bt/bluedroid/stack/btm/btm_devctl.c index a4aa638f4..9773ffd6e 100755 --- a/components/bt/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/bluedroid/stack/btm/btm_devctl.c @@ -204,7 +204,10 @@ void BTM_DeviceReset (UNUSED_ATTR tBTM_CMPL_CB *p_cb) { /* Clear the callback, so application would not hang on reset */ btm_db_reset(); - controller_get_interface()->devctl_reset(reset_complete); + /* todo: review the below logic; start_up executes under another task context + * reset_complete runs in btu task */ + controller_get_interface()->start_up(); + reset_complete(); } /******************************************************************************* diff --git a/components/bt/bluedroid/stack/btu/btu_hcif.c b/components/bt/bluedroid/stack/btu/btu_hcif.c index 80e24e163..4644d7a27 100755 --- a/components/bt/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/bluedroid/stack/btu/btu_hcif.c @@ -981,7 +981,7 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context) fixed_queue_enqueue(btu_hci_msg_queue, event); // ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } @@ -1182,7 +1182,7 @@ static void btu_hcif_command_status_evt(uint8_t status, BT_HDR *command, void *c fixed_queue_enqueue(btu_hci_msg_queue, event); //ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } /******************************************************************************* diff --git a/components/bt/bluedroid/stack/btu/btu_init.c b/components/bt/bluedroid/stack/btu/btu_init.c index 9831263d5..85a8c8a58 100755 --- a/components/bt/bluedroid/stack/btu/btu_init.c +++ b/components/bt/bluedroid/stack/btu/btu_init.c @@ -25,6 +25,7 @@ #include "fixed_queue.h" #include "hash_map.h" #include "hash_functions.h" +#include "thread.h" #include "l2c_int.h" #include "dyn_mem.h" @@ -71,9 +72,14 @@ static const size_t BTU_L2CAP_ALARM_HASH_MAP_SIZE = 17; //thread_t *bt_workqueue_thread; //static const char *BT_WORKQUEUE_NAME = "bt_workqueue"; +xTaskHandle xBtuTaskHandle = NULL; +xQueueHandle xBtuQueue = 0; extern void PLATFORM_DisableHciTransport(UINT8 bDisable); +extern void btu_task_thread_handler(void *arg); +void btu_task_start_up(void); +void btu_task_shut_down(void); /***************************************************************************** ** V A R I A B L E S * ******************************************************************************/ @@ -187,8 +193,9 @@ void BTU_StartUp(void) if (btu_l2cap_alarm_queue == NULL) goto error_exit; - btu_task_start_up(); - + xBtuQueue = xQueueCreate(15, sizeof(void *)); + xTaskCreate(btu_task_thread_handler, "BtuT", 8192, NULL, configMAX_PRIORITIES - 1, &xBtuTaskHandle); + btu_task_post(SIG_BTU_START_UP); /* // Continue startup on bt workqueue thread. thread_post(bt_workqueue_thread, btu_task_start_up, NULL); @@ -218,6 +225,8 @@ void BTU_ShutDown(void) { fixed_queue_free(btu_l2cap_alarm_queue, NULL); //thread_free(bt_workqueue_thread); + vTaskDelete(xBtuTaskHandle); + vQueueDelete(xBtuQueue); btu_bta_msg_queue = NULL; @@ -231,6 +240,8 @@ void BTU_ShutDown(void) { btu_l2cap_alarm_queue = NULL; // bt_workqueue_thread = NULL; + xBtuTaskHandle = NULL; + xBtuQueue = 0; } /***************************************************************************** diff --git a/components/bt/bluedroid/stack/btu/btu_task.c b/components/bt/bluedroid/stack/btu/btu_task.c index e7152e341..50c96ca65 100755 --- a/components/bt/bluedroid/stack/btu/btu_task.c +++ b/components/bt/bluedroid/stack/btu/btu_task.c @@ -94,10 +94,6 @@ extern void BTE_InitStack(void); tBTU_CB btu_cb; #endif -static xTaskHandle xBtuTaskHandle; -static xQueueHandle xBtuQueue; - - // Communication queue between btu_task and bta. extern fixed_queue_t *btu_bta_msg_queue; @@ -126,7 +122,8 @@ extern fixed_queue_t *event_queue; //extern fixed_queue_t *btif_msg_queue; //extern thread_t *bt_workqueue_thread; - +extern xTaskHandle xBtuTaskHandle; +extern xQueueHandle xBtuQueue; extern bluedroid_init_done_cb_t bluedroid_init_done_cb; /* Define a function prototype to allow a generic timeout handler */ @@ -305,7 +302,7 @@ static void btu_bta_alarm_process(TIMER_LIST_ENT *p_tle) { ** ** Description Process BTU Task Thread. ******************************************************************************/ -static void btu_task_thread_handler(void *arg) +void btu_task_thread_handler(void *arg) { //ke_event_clear(KE_EVENT_BTU_TASK_THREAD); @@ -314,7 +311,7 @@ static void btu_task_thread_handler(void *arg) for (;;) { if (pdTRUE == xQueueReceive(xBtuQueue, &e, (portTickType)portMAX_DELAY)) { - if (e->sig == 0xff) { + if (e->sig == SIG_BTU_WORK) { fixed_queue_process(btu_hci_msg_queue); #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE) fixed_queue_process(btu_bta_msg_queue); @@ -324,19 +321,22 @@ static void btu_task_thread_handler(void *arg) fixed_queue_process(btu_oneshot_alarm_queue); fixed_queue_process(btu_l2cap_alarm_queue); } + else if (e->sig == SIG_BTU_START_UP) { + btu_task_start_up(); + } osi_free(e); } } } -void btu_task_post(void) +void btu_task_post(uint32_t sig) { TaskEvt_t *evt = (TaskEvt_t *)osi_malloc(sizeof(TaskEvt_t)); if (evt == NULL) return; - evt->sig = 0xff; + evt->sig = sig; evt->par = 0; if (xQueueSend(xBtuQueue, &evt, 10/portTICK_RATE_MS) != pdTRUE) { @@ -347,9 +347,6 @@ void btu_task_post(void) void btu_task_start_up(void) { // ke_event_callback_set(KE_EVENT_BTU_TASK_THREAD, &btu_task_thread_handler); - xBtuQueue = xQueueCreate(15, sizeof(void *)); - xTaskCreate(btu_task_thread_handler, "BtuT", 8192, NULL, configMAX_PRIORITIES - 1, &xBtuTaskHandle); - #if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE) fixed_queue_register_dequeue(btu_bta_msg_queue, btu_bta_msg_ready); #endif @@ -391,9 +388,6 @@ void btu_task_shut_down(void) { #endif btu_free_core(); - - vTaskDelete(xBtuTaskHandle); - vQueueDelete(xBtuQueue); } /******************************************************************************* @@ -518,7 +512,7 @@ void btu_general_alarm_cb(void *data) { fixed_queue_enqueue(btu_general_alarm_queue, p_tle); //ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) { @@ -603,7 +597,7 @@ static void btu_l2cap_alarm_cb(void *data) { fixed_queue_enqueue(btu_l2cap_alarm_queue, p_tle); //ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ticks) { @@ -667,7 +661,7 @@ void btu_oneshot_alarm_cb(void *data) { fixed_queue_enqueue(btu_oneshot_alarm_queue, p_tle); //ke_event_set(KE_EVENT_BTU_TASK_THREAD); - btu_task_post(); + btu_task_post(SIG_BTU_WORK); } /*