From 1fc2c15a29c78fdbd0da5f4b0f096ed4a85c362e Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 13 Jan 2016 15:06:28 +0100 Subject: [PATCH 01/31] posix-cc2564b: fix compile, use high uart speed --- platforms/posix-cc2564b/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platforms/posix-cc2564b/main.c b/platforms/posix-cc2564b/main.c index e757c1559..b37a630d1 100644 --- a/platforms/posix-cc2564b/main.c +++ b/platforms/posix-cc2564b/main.c @@ -56,7 +56,7 @@ #include "hci.h" #include "hci_dump.h" #include "stdin_support.h" -#include "hal_led.h" +#include #include "bt_control_cc256x.h" int btstack_main(int argc, const char * argv[]); @@ -64,6 +64,7 @@ int btstack_main(int argc, const char * argv[]); static hci_uart_config_t hci_uart_config_cc256x = { NULL, 115200, + 921600 }; static void sigint_handler(int param){ @@ -96,7 +97,7 @@ int main(int argc, const char * argv[]){ hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); // pick serial port - hci_uart_config_cc256x.device_name = "/dev/tty.usbserial-AD025KU2"; + hci_uart_config_cc256x.device_name = "/dev/tty.usbserial-A900K0VK"; // init HCI hci_transport_t * transport = hci_transport_h4_instance(); From 0ebae5fdf31f98cc2c257e134530d3292415d4dc Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Wed, 13 Jan 2016 15:06:36 +0100 Subject: [PATCH 02/31] hfp: add new call state --- src/hfp_gsm_model.c | 39 ++++++++++++++++++++++++++++------- src/hfp_gsm_model.h | 2 ++ test/hfp/hfp_ag_client_test.c | 3 ++- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index 77ab7b6c8..383085691 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -65,6 +65,7 @@ typedef enum{ CALL_NONE, + CALL_INITIATED, CALL_ACTIVE, CALL_HELD } hfp_gsm_call_status_t; @@ -106,6 +107,10 @@ static inline int get_active_call_index(){ return get_call_index_with_status(CALL_ACTIVE); } +static inline int get_initiated_call_index(){ + return get_call_index_with_status(CALL_INITIATED); +} + // static inline int get_number_none_calls(){ // return get_number_calls_with_status(CALL_NONE); // } @@ -140,32 +145,50 @@ hfp_callsetup_status_t hfp_gsm_callsetup_status(){ return callsetup_status; } +int hfp_gsm_call_possible(void){ + int next_free_slot = get_none_call_index(); + return next_free_slot != -1; +} + void hfp_gsm_handle_event(hfp_ag_call_event_t event){ int next_free_slot = get_none_call_index(); int current_call_index = get_active_call_index(); - + int initiated_call_index = get_initiated_call_index(); + switch (event){ case HFP_AG_OUTGOING_CALL_INITIATED: case HFP_AG_OUTGOING_REDIAL_INITIATED: - if (next_free_slot == -1){ - log_error("max nr gsm call exceeded"); + log_error("gsm: max call nr exceeded"); return; } + break; + case HFP_AG_OUTGOING_CALL_REJECTED: + if (current_call_index != -1){ + gsm_calls[current_call_index].status = CALL_NONE; + } + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + + case HFP_AG_OUTGOING_CALL_ACCEPTED: if (current_call_index != -1){ gsm_calls[current_call_index].status = CALL_HELD; } - gsm_calls[next_free_slot].status = CALL_ACTIVE; + gsm_calls[next_free_slot].status = CALL_INITIATED; callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE; break; - case HFP_AG_OUTGOING_CALL_REJECTED: - break; - case HFP_AG_OUTGOING_CALL_ACCEPTED: - break; + case HFP_AG_OUTGOING_CALL_RINGING: + if (current_call_index == -1){ + log_error("gsm: no active call"); + return; + } + callsetup_status = HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE; break; case HFP_AG_OUTGOING_CALL_ESTABLISHED: + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; default: break; diff --git a/src/hfp_gsm_model.h b/src/hfp_gsm_model.h index dd72c3d7b..75f25926e 100644 --- a/src/hfp_gsm_model.h +++ b/src/hfp_gsm_model.h @@ -63,6 +63,8 @@ hfp_callheld_status_t hfp_gsm_callheld_status(); hfp_call_status_t hfp_gsm_call_status(); hfp_callsetup_status_t hfp_gsm_callsetup_status(); +int hfp_gsm_call_possible(void); + void hfp_gsm_handle_event(hfp_ag_call_event_t event); // /** diff --git a/test/hfp/hfp_ag_client_test.c b/test/hfp/hfp_ag_client_test.c index febe4dbd9..525339a1c 100644 --- a/test/hfp/hfp_ag_client_test.c +++ b/test/hfp/hfp_ag_client_test.c @@ -337,7 +337,8 @@ static void simulate_test_sequence(hfp_test_item_t * test_item){ int previous_step = -1; while ( i < test_item->len){ previous_step++; - if (i < previous_step) exit(0); + CHECK_EQUAL(i >= previous_step, 1); + char * expected_cmd = test_steps[i]; int expected_cmd_len = strlen(expected_cmd); printf("\nStep %d, %s \n", i, expected_cmd); From 5472ae221e75e236c32d832e45c85f87cc1be836 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 13 Jan 2016 15:13:52 +0100 Subject: [PATCH 03/31] add chipset-bcm from ble-api-cleanup branch --- chipset-bcm/bt_control_bcm.c | 131 +++++++++++++++++++++++++++++++++++ chipset-bcm/bt_control_bcm.h | 59 ++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 chipset-bcm/bt_control_bcm.c create mode 100644 chipset-bcm/bt_control_bcm.h diff --git a/chipset-bcm/bt_control_bcm.c b/chipset-bcm/bt_control_bcm.c new file mode 100644 index 000000000..e850e6aa8 --- /dev/null +++ b/chipset-bcm/bt_control_bcm.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009-2012 by Matthias Ringwald + * + * 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 MATTHIAS RINGWALD 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 btstack@ringwald.ch + * + */ + +/* + * bt_control_bcm.c + * + * Adapter to use Broadcom-based chipsets with BTstack + */ + + +#include "btstack-config.h" +#include "bt_control_bcm.h" + +#include /* NULL */ +#include +#include /* memcpy */ + +#include "bt_control.h" +#include "debug.h" + +// actual init script provided by separate bt_firmware_image.c from WICED SDK +extern const uint8_t brcm_patchram_buf[]; +extern const int brcm_patch_ram_length; +extern const char brcm_patch_version[]; + +// +static uint32_t init_script_offset; +static int send_download_command; + +static int bt_control_bcm_on(void *config){ + log_info("Broadcom init script %s, len %u", brcm_patch_version, brcm_patch_ram_length); + init_script_offset = 0; + send_download_command = 1; + return 0; +} + +// @note: Broadcom chips require higher UART clock for baud rate > 3000000 -> limit baud rate in hci.c +static int bcm_baudrate_cmd(void * config, uint32_t baudrate, uint8_t *hci_cmd_buffer){ + hci_cmd_buffer[0] = 0x18; + hci_cmd_buffer[1] = 0xfc; + hci_cmd_buffer[2] = 0x06; + hci_cmd_buffer[3] = 0x00; + hci_cmd_buffer[4] = 0x00; + bt_store_32(hci_cmd_buffer, 5, baudrate); + return 0; +} + +// @note: bd addr has to be set after sending init script (it might just get re-set) +static int bt_control_bcm_set_bd_addr_cmd(void * config, bd_addr_t addr, uint8_t *hci_cmd_buffer){ + hci_cmd_buffer[0] = 0x01; + hci_cmd_buffer[1] = 0xfc; + hci_cmd_buffer[2] = 0x06; + bt_flip_addr(&hci_cmd_buffer[3], addr); + return 0; +} + +static int bt_control_bcm_next_cmd(void *config, uint8_t *hci_cmd_buffer){ + + // send download firmware command + if (send_download_command){ + send_download_command = 0; + hci_cmd_buffer[0] = 0x2e; + hci_cmd_buffer[1] = 0xfc; + hci_cmd_buffer[2] = 0x00; + return 1; + } + + if (init_script_offset >= brcm_patch_ram_length) { + return 0; + } + + // use memcpy with pointer + int cmd_len = 3 + brcm_patchram_buf[init_script_offset+2]; + memcpy(&hci_cmd_buffer[0], &brcm_patchram_buf[init_script_offset], cmd_len); + init_script_offset += cmd_len; + return 1; +} + +// MARK: const structs + +static const bt_control_t bt_control_bcm = { + bt_control_bcm_on, // on + NULL, // off + NULL, // sleep + NULL, // wake + NULL, // valid + NULL, // name + bcm_baudrate_cmd, // baudrate_cmd + bt_control_bcm_next_cmd, // next_cmd + NULL, // register_for_power_notifications + NULL, // hw_error + bt_control_bcm_set_bd_addr_cmd, // set_bd_addr_cmd +}; + +// MARK: public API +bt_control_t * bt_control_bcm_instance(void){ + return (bt_control_t*) &bt_control_bcm; +} diff --git a/chipset-bcm/bt_control_bcm.h b/chipset-bcm/bt_control_bcm.h new file mode 100644 index 000000000..6de9f3370 --- /dev/null +++ b/chipset-bcm/bt_control_bcm.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009-2012 by Matthias Ringwald + * + * 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 MATTHIAS RINGWALD 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 btstack@ringwald.ch + * + */ + +/* + * bt_control_bcm.h + * + * Adapter to use Broadcom-based chipsets with BTstack + */ + +#ifndef __BT_CONTROL_BCM_H +#define __BT_CONTROL_BCM_H + +#if defined __cplusplus +extern "C" { +#endif + +#include +#include "bt_control.h" + +bt_control_t * bt_control_bcm_instance(void); + +#if defined __cplusplus +} +#endif + +#endif // __BT_CONTROL_BCM_H From 37cb5f0da9f5222d0ac6d2e52d15f1716a36b2df Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 13 Jan 2016 15:15:37 +0100 Subject: [PATCH 04/31] fix indention --- chipset-bcm/bt_control_bcm.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/chipset-bcm/bt_control_bcm.c b/chipset-bcm/bt_control_bcm.c index e850e6aa8..8f21f53ec 100644 --- a/chipset-bcm/bt_control_bcm.c +++ b/chipset-bcm/bt_control_bcm.c @@ -62,9 +62,9 @@ static int send_download_command; static int bt_control_bcm_on(void *config){ log_info("Broadcom init script %s, len %u", brcm_patch_version, brcm_patch_ram_length); - init_script_offset = 0; + init_script_offset = 0; send_download_command = 1; - return 0; + return 0; } // @note: Broadcom chips require higher UART clock for baud rate > 3000000 -> limit baud rate in hci.c @@ -112,15 +112,15 @@ static int bt_control_bcm_next_cmd(void *config, uint8_t *hci_cmd_buffer){ // MARK: const structs static const bt_control_t bt_control_bcm = { - bt_control_bcm_on, // on - NULL, // off - NULL, // sleep - NULL, // wake - NULL, // valid - NULL, // name - bcm_baudrate_cmd, // baudrate_cmd - bt_control_bcm_next_cmd, // next_cmd - NULL, // register_for_power_notifications + bt_control_bcm_on, // on + NULL, // off + NULL, // sleep + NULL, // wake + NULL, // valid + NULL, // name + bcm_baudrate_cmd, // baudrate_cmd + bt_control_bcm_next_cmd, // next_cmd + NULL, // register_for_power_notifications NULL, // hw_error bt_control_bcm_set_bd_addr_cmd, // set_bd_addr_cmd }; From fceac7d65700699d56f9e98193d439ccbbbbe9d4 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Wed, 13 Jan 2016 16:56:55 +0100 Subject: [PATCH 05/31] hfp gsm: implement all events, untested --- src/hfp_gsm_model.c | 111 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index 383085691..722e65f43 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -66,6 +66,7 @@ typedef enum{ CALL_NONE, CALL_INITIATED, + CALL_RESPONSE_HOLD, CALL_ACTIVE, CALL_HELD } hfp_gsm_call_status_t; @@ -73,6 +74,8 @@ typedef enum{ typedef struct { hfp_gsm_call_status_t status; + uint8_t clip_type; + char clip_number[25]; } hfp_gsm_call_t; @@ -111,6 +114,14 @@ static inline int get_initiated_call_index(){ return get_call_index_with_status(CALL_INITIATED); } +static inline int get_held_call_index(){ + return get_call_index_with_status(CALL_HELD); +} + +static inline int get_response_held_call_index(){ + return get_call_index_with_status(CALL_RESPONSE_HOLD); +} + // static inline int get_number_none_calls(){ // return get_number_calls_with_status(CALL_NONE); // } @@ -123,8 +134,12 @@ static inline int get_number_held_calls(){ return get_number_calls_with_status(CALL_HELD); } +static inline int get_number_response_held_calls(){ + return get_number_calls_with_status(CALL_RESPONSE_HOLD); +} + hfp_call_status_t hfp_gsm_call_status(){ - if (get_number_active_calls() + get_number_held_calls()){ + if (get_number_active_calls() + get_number_held_calls() + get_number_response_held_calls()){ return HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT; } return HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS; @@ -145,6 +160,10 @@ hfp_callsetup_status_t hfp_gsm_callsetup_status(){ return callsetup_status; } +int hfp_gsm_response_held_active(){ + return get_response_held_call_index() != -1 ; +} + int hfp_gsm_call_possible(void){ int next_free_slot = get_none_call_index(); return next_free_slot != -1; @@ -154,6 +173,7 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ int next_free_slot = get_none_call_index(); int current_call_index = get_active_call_index(); int initiated_call_index = get_initiated_call_index(); + int held_call_index = get_held_call_index(); switch (event){ case HFP_AG_OUTGOING_CALL_INITIATED: @@ -190,6 +210,95 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; + + case HFP_AG_INCOMING_CALL: + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; + callsetup_status = HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS; + gsm_calls[next_free_slot].status = CALL_INITIATED; + gsm_calls[next_free_slot].clip_type = 0; + break; + + case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + + if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + gsm_calls[current_call_index].status = CALL_HELD; + } + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + break; + + case HFP_AG_HELD_CALL_JOINED_BY_AG: + if (hfp_gsm_callsetup_status() != HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) break; + if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; + gsm_calls[held_call_index].status = CALL_ACTIVE; + break; + + case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; + if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + break; + + case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: + case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; + if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break; + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + gsm_calls[initiated_call_index].status = CALL_RESPONSE_HOLD; + break; + + case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG: + case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF: + if (!hfp_gsm_response_held_active()) break; + gsm_calls[get_response_held_call_index()].status = CALL_ACTIVE; + break; + + case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG: + case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF: + if (!hfp_gsm_response_held_active()) break; + gsm_calls[get_response_held_call_index()].status = CALL_NONE; + break; + + + case HFP_AG_TERMINATE_CALL_BY_HF: + switch (hfp_gsm_call_status()){ + case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: + gsm_calls[current_call_index].status = CALL_NONE; + break; + } + break; + + case HFP_AG_TERMINATE_CALL_BY_AG: + switch (hfp_gsm_call_status()){ + case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + gsm_calls[current_call_index].status = CALL_NONE; + break; + default: + break; + } + break; + + case HFP_AG_CALL_DROPPED: + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; + if (hfp_gsm_response_held_active()) { + gsm_calls[get_response_held_call_index()].status = CALL_NONE; + } + if (current_call_index != -1){ + gsm_calls[current_call_index].status = CALL_NONE; + } + break; + default: break; } From 10b8785a443d71cc1d95e0dd5267cf42c56c87a8 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Wed, 13 Jan 2016 16:58:40 +0100 Subject: [PATCH 06/31] hfp ag: call gsm module from the ag call state machine --- src/hfp_ag.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 25498986e..939e2c9c5 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1118,6 +1118,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect switch (event){ case HFP_AG_INCOMING_CALL: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); switch (hfp_ag_call_state){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (hfp_ag_callsetup_state){ @@ -1145,6 +1146,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: // clear CLIP + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); clip_type = 0; switch (hfp_ag_call_state){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: @@ -1176,6 +1178,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_HELD_CALL_JOINED_BY_AG: + hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG); switch (hfp_ag_call_state){ case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: switch (hfp_ag_callheld_state){ @@ -1195,6 +1198,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF); // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ @@ -1217,7 +1221,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: - // clear CLIP + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG); + // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: @@ -1242,7 +1247,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: - // clear CLIP + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF); + // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: @@ -1268,6 +1274,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG: case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF: + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG); if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; hfp_ag_response_and_hold_active = 0; @@ -1278,6 +1285,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG: case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF: + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG); if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; hfp_ag_response_and_hold_active = 0; @@ -1289,6 +1297,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_TERMINATE_CALL_BY_HF: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ @@ -1319,6 +1328,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_TERMINATE_CALL_BY_AG: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_AG); // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ @@ -1343,6 +1353,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; case HFP_AG_CALL_DROPPED: + hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); // clear CLIP clip_type = 0; switch (hfp_ag_call_state){ @@ -1379,6 +1390,12 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_OUTGOING_CALL_INITIATED: + // directly reject call if number of free slots is exceeded + if (!hfp_gsm_call_possible()){ + connection->send_error = 1; + hfp_run_for_context(connection); + break; + } hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; @@ -1386,6 +1403,13 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_OUTGOING_REDIAL_INITIATED: + // directly reject call if number of free slots is exceeded + if (!hfp_gsm_call_possible()){ + connection->send_error = 1; + hfp_run_for_context(connection); + break; + } + hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; @@ -1393,25 +1417,26 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_OUTGOING_CALL_REJECTED: - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED); connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED); if (!connection){ log_info("hfp_ag_call_sm: did not find outgoing connection in initiated state"); break; } + + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED); connection->call_state = HFP_CALL_IDLE; connection->send_error = 1; hfp_run_for_context(connection); break; case HFP_AG_OUTGOING_CALL_ACCEPTED: - // hfp_gsm_handle_event(); connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED); if (!connection){ log_info("hfp_ag_call_sm: did not find outgoing connection in initiated state"); break; } - + + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ACCEPTED); connection->ok_pending = 1; connection->call_state = HFP_CALL_OUTGOING_DIALING; @@ -1439,13 +1464,14 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect log_info("hfp_ag_call_sm: did not find outgoing connection in dialing state"); break; } + + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_RINGING); connection->call_state = HFP_CALL_OUTGOING_RINGING; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE); hfp_ag_transfer_callsetup_state(); break; case HFP_AG_OUTGOING_CALL_ESTABLISHED: - // hfp_gsm_handle_event(); // get outgoing call connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_RINGING); if (!connection){ @@ -1455,6 +1481,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect log_info("hfp_ag_call_sm: did not find outgoing connection"); break; } + + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ESTABLISHED); connection->call_state = HFP_CALL_ACTIVE; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); @@ -1469,6 +1497,17 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect default: break; } + + // if ( (hfp_ag_callsetup_state != hfp_gsm_callsetup_status()) || + // (hfp_ag_callheld_state != hfp_gsm_callheld_status()) || + // (hfp_ag_call_state != hfp_gsm_call_status()) ){ + + // printf("event %d\n", event); + // printf("callsetup %d - %d \n", hfp_ag_callsetup_state, hfp_gsm_callsetup_status()); + // printf("callheld %d - %d \n", hfp_ag_callheld_state, hfp_gsm_callheld_status()); + // printf("call %d - %d \n", hfp_ag_call_state, hfp_gsm_call_status()); + // exit(1); + // } } static void hfp_run_for_context(hfp_connection_t *context){ From 3e920c463fb6ac781b85c9542a503d6a63286431 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 10:27:37 +0100 Subject: [PATCH 07/31] hfp ag: remove gsm code from ag for now --- src/hfp_ag.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 939e2c9c5..cc7ac4ed0 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1391,11 +1391,11 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_OUTGOING_CALL_INITIATED: // directly reject call if number of free slots is exceeded - if (!hfp_gsm_call_possible()){ - connection->send_error = 1; - hfp_run_for_context(connection); - break; - } + // if (!hfp_gsm_call_possible()){ + // connection->send_error = 1; + // hfp_run_for_context(connection); + // break; + // } hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; @@ -1404,11 +1404,11 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_OUTGOING_REDIAL_INITIATED: // directly reject call if number of free slots is exceeded - if (!hfp_gsm_call_possible()){ - connection->send_error = 1; - hfp_run_for_context(connection); - break; - } + // if (!hfp_gsm_call_possible()){ + // connection->send_error = 1; + // hfp_run_for_context(connection); + // break; + // } hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; From a21b02e6ce3b4dd15e1546992559cb827634b330 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 11:46:29 +0100 Subject: [PATCH 08/31] gsm model: fix drop call, add init --- src/hfp_gsm_model.c | 43 ++++++++++++++++++++++++++++--------------- src/hfp_gsm_model.h | 2 ++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index 722e65f43..120c3bd3f 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -82,6 +82,9 @@ typedef struct { // static hfp_gsm_call_t gsm_calls[HFP_GSM_MAX_NR_CALLS]; +void hfp_gsm_module_init(void){ + memset(gsm_calls, 0, sizeof(gsm_calls)); +} // static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; @@ -122,9 +125,9 @@ static inline int get_response_held_call_index(){ return get_call_index_with_status(CALL_RESPONSE_HOLD); } -// static inline int get_number_none_calls(){ -// return get_number_calls_with_status(CALL_NONE); -// } +static inline int get_number_none_calls(){ + return get_number_calls_with_status(CALL_NONE); +} static inline int get_number_active_calls(){ return get_number_calls_with_status(CALL_ACTIVE); @@ -165,8 +168,7 @@ int hfp_gsm_response_held_active(){ } int hfp_gsm_call_possible(void){ - int next_free_slot = get_none_call_index(); - return next_free_slot != -1; + return get_number_none_calls() > 0; } void hfp_gsm_handle_event(hfp_ag_call_event_t event){ @@ -212,19 +214,25 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ break; case HFP_AG_INCOMING_CALL: + printf("HFP_AG_INCOMING_CALL \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; + printf("HFP_AG_INCOMING_CALL 1: HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS -> HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS, CALL_INITIATED %d\n", next_free_slot); callsetup_status = HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS; gsm_calls[next_free_slot].status = CALL_INITIATED; gsm_calls[next_free_slot].clip_type = 0; break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; - + if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG 1: HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT, CALL_HELD %d\n", current_call_index); gsm_calls[current_call_index].status = CALL_HELD; } + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG 2: HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT, CALL_ACTIVE %d\n", initiated_call_index); + gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; @@ -235,8 +243,11 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; - if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF 1: HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS\n"); + if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break; + printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF 2\n"); callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; @@ -288,14 +299,16 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ } break; - case HFP_AG_CALL_DROPPED: - callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; - if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; - if (hfp_gsm_response_held_active()) { - gsm_calls[get_response_held_call_index()].status = CALL_NONE; - } - if (current_call_index != -1){ - gsm_calls[current_call_index].status = CALL_NONE; + case HFP_AG_CALL_DROPPED:{ + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; + + int i ; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + gsm_calls[i].status = CALL_NONE; + gsm_calls[i].clip_type = 0; + gsm_calls[i].clip_number[0] = '\0'; + } } break; diff --git a/src/hfp_gsm_model.h b/src/hfp_gsm_model.h index 75f25926e..0e5d309c3 100644 --- a/src/hfp_gsm_model.h +++ b/src/hfp_gsm_model.h @@ -65,6 +65,8 @@ hfp_callsetup_status_t hfp_gsm_callsetup_status(); int hfp_gsm_call_possible(void); +void hfp_gsm_module_init(void); + void hfp_gsm_handle_event(hfp_ag_call_event_t event); // /** From 1c6bfde03b8b275f3a08f36876db6af9666a8a9e Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 11:48:43 +0100 Subject: [PATCH 09/31] hfp ag: correct event name --- src/hfp_ag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index cc7ac4ed0..4980aa7b7 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1115,7 +1115,7 @@ static int call_setup_state_machine(hfp_connection_t * connection){ // connection is used to identify originating HF static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connection){ int indicator_index; - + //printf("hfp_ag_call_sm event %d \n", event); switch (event){ case HFP_AG_INCOMING_CALL: hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); @@ -1146,7 +1146,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: // clear CLIP - hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG); clip_type = 0; switch (hfp_ag_call_state){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: From 1335ac5955d90a9cf9152d59afb89f4e664981f3 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 11:53:06 +0100 Subject: [PATCH 10/31] hfp gsm: rename function, call gms init from ag --- src/hfp_ag.c | 2 ++ src/hfp_gsm_model.c | 2 +- src/hfp_gsm_model.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 4980aa7b7..668f8b782 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1949,6 +1949,8 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, hfp_ag_call_state = HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS; hfp_ag_callsetup_state = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; hfp_ag_callheld_state = HFP_CALLHELD_STATUS_NO_CALLS_HELD; + + hfp_gsm_init(); } void hfp_ag_establish_service_level_connection(bd_addr_t bd_addr){ diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index 120c3bd3f..6b85e3fb7 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -82,7 +82,7 @@ typedef struct { // static hfp_gsm_call_t gsm_calls[HFP_GSM_MAX_NR_CALLS]; -void hfp_gsm_module_init(void){ +void hfp_gsm_init(void){ memset(gsm_calls, 0, sizeof(gsm_calls)); } // diff --git a/src/hfp_gsm_model.h b/src/hfp_gsm_model.h index 0e5d309c3..f19ba026e 100644 --- a/src/hfp_gsm_model.h +++ b/src/hfp_gsm_model.h @@ -65,7 +65,7 @@ hfp_callsetup_status_t hfp_gsm_callsetup_status(); int hfp_gsm_call_possible(void); -void hfp_gsm_module_init(void); +void hfp_gsm_init(void); void hfp_gsm_handle_event(hfp_ag_call_event_t event); From 868fae3b10c22a6fdf89352bd5ac9d308f2dc80f Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 12:12:35 +0100 Subject: [PATCH 11/31] hfp ag/gsm: update init methods --- src/hfp_ag.c | 44 +++++++++++++++++++++++++------------------- src/hfp_gsm_model.c | 11 ++++------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 668f8b782..78bd944b1 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1391,11 +1391,11 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_OUTGOING_CALL_INITIATED: // directly reject call if number of free slots is exceeded - // if (!hfp_gsm_call_possible()){ - // connection->send_error = 1; - // hfp_run_for_context(connection); - // break; - // } + if (!hfp_gsm_call_possible()){ + connection->send_error = 1; + hfp_run_for_context(connection); + break; + } hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; @@ -1404,11 +1404,11 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_OUTGOING_REDIAL_INITIATED: // directly reject call if number of free slots is exceeded - // if (!hfp_gsm_call_possible()){ - // connection->send_error = 1; - // hfp_run_for_context(connection); - // break; - // } + if (!hfp_gsm_call_possible()){ + connection->send_error = 1; + hfp_run_for_context(connection); + break; + } hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; @@ -1498,16 +1498,16 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - // if ( (hfp_ag_callsetup_state != hfp_gsm_callsetup_status()) || - // (hfp_ag_callheld_state != hfp_gsm_callheld_status()) || - // (hfp_ag_call_state != hfp_gsm_call_status()) ){ + if ( (hfp_ag_callsetup_state != hfp_gsm_callsetup_status()) || + (hfp_ag_callheld_state != hfp_gsm_callheld_status()) || + (hfp_ag_call_state != hfp_gsm_call_status()) ){ - // printf("event %d\n", event); - // printf("callsetup %d - %d \n", hfp_ag_callsetup_state, hfp_gsm_callsetup_status()); - // printf("callheld %d - %d \n", hfp_ag_callheld_state, hfp_gsm_callheld_status()); - // printf("call %d - %d \n", hfp_ag_call_state, hfp_gsm_call_status()); - // exit(1); - // } + printf("event %d\n", event); + printf("callsetup %d - %d \n", hfp_ag_callsetup_state, hfp_gsm_callsetup_status()); + printf("callheld %d - %d \n", hfp_ag_callheld_state, hfp_gsm_callheld_status()); + printf("call %d - %d \n", hfp_ag_call_state, hfp_gsm_call_status()); + exit(1); + } } static void hfp_run_for_context(hfp_connection_t *context){ @@ -1950,6 +1950,12 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, hfp_ag_callsetup_state = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; hfp_ag_callheld_state = HFP_CALLHELD_STATUS_NO_CALLS_HELD; + hfp_ag_response_and_hold_active = 0; + clip_type = 0; // 0 == not set + memset(clip_number,0,sizeof(clip_number)); + subscriber_numbers = NULL; + subscriber_numbers_count = 0; + hfp_gsm_init(); } diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index 6b85e3fb7..a0cb8e059 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -77,17 +77,14 @@ typedef struct { uint8_t clip_type; char clip_number[25]; } hfp_gsm_call_t; - - -// + static hfp_gsm_call_t gsm_calls[HFP_GSM_MAX_NR_CALLS]; +static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; void hfp_gsm_init(void){ memset(gsm_calls, 0, sizeof(gsm_calls)); -} -// -static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; - + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; +} static int get_number_calls_with_status(hfp_gsm_call_status_t status){ int i, count = 0; From b1f3044ce38369d15d7d5bf28b36e0a2750123dd Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 12:40:04 +0100 Subject: [PATCH 12/31] hfp gsm: fix join call --- src/hfp_gsm_model.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index a0cb8e059..af9840eda 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -134,6 +134,10 @@ static inline int get_number_held_calls(){ return get_number_calls_with_status(CALL_HELD); } +static inline int get_number_initiated_calls(){ + return get_number_calls_with_status(CALL_INITIATED); +} + static inline int get_number_response_held_calls(){ return get_number_calls_with_status(CALL_RESPONSE_HOLD); } @@ -234,9 +238,20 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ break; case HFP_AG_HELD_CALL_JOINED_BY_AG: - if (hfp_gsm_callsetup_status() != HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) break; if (hfp_gsm_call_status() != HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT) break; - gsm_calls[held_call_index].status = CALL_ACTIVE; + + // TODO: mark joined calls with "multiparty flag" (if we cannot calculate it otherwise) + // TODO: is following condition correct? Can we join incoming call before it is answered? + if (callsetup_status == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + } + + if (hfp_gsm_callheld_status() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED) { + gsm_calls[held_call_index].status = CALL_ACTIVE; + break; + } break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: From 2c1d2b318b162a2573108ccdb02b13d492dfee19 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 13:42:11 +0100 Subject: [PATCH 13/31] hfp test: call setup before test run --- test/hfp/hfp_ag_client_test.c | 6 ++++++ test/hfp/hfp_hf_client_test.c | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/test/hfp/hfp_ag_client_test.c b/test/hfp/hfp_ag_client_test.c index 525339a1c..6e0a0c6cb 100644 --- a/test/hfp/hfp_ag_client_test.c +++ b/test/hfp/hfp_ag_client_test.c @@ -528,6 +528,7 @@ TEST_GROUP(HFPClient){ TEST(HFPClient, PTSRHHTests){ for (int i = 0; i < hfp_pts_ag_rhh_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_rhh_tests()[i]); teardown(); } @@ -535,6 +536,7 @@ TEST(HFPClient, PTSRHHTests){ TEST(HFPClient, PTSECCTests){ for (int i = 0; i < hfp_pts_ag_ecc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_ecc_tests()[i]); teardown(); } @@ -542,6 +544,7 @@ TEST(HFPClient, PTSECCTests){ TEST(HFPClient, PTSECSTests){ for (int i = 0; i < hfp_pts_ag_ecs_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_ecs_tests()[i]); teardown(); } @@ -549,6 +552,7 @@ TEST(HFPClient, PTSECSTests){ TEST(HFPClient, PTSTWCTests){ for (int i = 0; i < hfp_pts_ag_twc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_twc_tests()[i]); teardown(); } @@ -556,6 +560,7 @@ TEST(HFPClient, PTSTWCTests){ TEST(HFPClient, PTSATATests){ for (int i = 0; i < hfp_pts_ag_ata_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_ata_tests()[i]); teardown(); } @@ -563,6 +568,7 @@ TEST(HFPClient, PTSATATests){ TEST(HFPClient, PTSSLCTests){ for (int i = 0; i < hfp_pts_ag_slc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_ag_slc_tests()[i]); teardown(); } diff --git a/test/hfp/hfp_hf_client_test.c b/test/hfp/hfp_hf_client_test.c index 97ced1307..d541f0b01 100644 --- a/test/hfp/hfp_hf_client_test.c +++ b/test/hfp/hfp_hf_client_test.c @@ -318,7 +318,8 @@ void simulate_test_sequence(hfp_test_item_t * test_item){ int previous_step = -1; while ( i < test_item->len){ previous_step++; - if (i < previous_step) exit(0); + CHECK_EQUAL(i >= previous_step, 1); + char * expected_cmd = test_steps[i]; int expected_cmd_len = strlen(expected_cmd); printf("\nStep %d, %s \n", i, expected_cmd); @@ -495,6 +496,7 @@ TEST_GROUP(HFPClient){ TEST(HFPClient, PTSRHHTests){ for (int i = 0; i < hfp_pts_hf_rhh_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_rhh_tests()[i]); teardown(); } @@ -502,6 +504,7 @@ TEST(HFPClient, PTSRHHTests){ TEST(HFPClient, PTSECCTests){ for (int i = 0; i < hfp_pts_hf_ecc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_ecc_tests()[i]); teardown(); } @@ -509,6 +512,7 @@ TEST(HFPClient, PTSECCTests){ TEST(HFPClient, PTSECSTests){ for (int i = 0; i < hfp_pts_hf_ecs_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_ecs_tests()[i]); teardown(); } @@ -516,6 +520,7 @@ TEST(HFPClient, PTSECSTests){ TEST(HFPClient, PTSTWCTests){ for (int i = 0; i < hfp_pts_hf_twc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_twc_tests()[i]); teardown(); } @@ -523,6 +528,7 @@ TEST(HFPClient, PTSTWCTests){ TEST(HFPClient, PTSATATests){ for (int i = 0; i < hfp_pts_hf_ata_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_ata_tests()[i]); teardown(); } @@ -530,6 +536,7 @@ TEST(HFPClient, PTSATATests){ TEST(HFPClient, PTSSLCTests){ for (int i = 0; i < hfp_pts_hf_slc_tests_size(); i++){ + setup(); simulate_test_sequence(&hfp_pts_hf_slc_tests()[i]); teardown(); } From ab3782332787e9afffc07fc0e00dc543e5b47e6c Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 13:42:58 +0100 Subject: [PATCH 14/31] hfp test: fix test sequence --- test/hfp/test_sequences.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/hfp/test_sequences.c b/test/hfp/test_sequences.c index f7dca7fc3..498821f71 100644 --- a/test/hfp/test_sequences.c +++ b/test/hfp/test_sequences.c @@ -1883,7 +1883,8 @@ const char * TC_AG_ECS_BV_03_I[] = { "OK" , "AT+CMEE=1" , "OK" , - "USER:c" , // "+CIEV:3,1" , + "USER:c" , + "+CIEV:3,1" , "RING" , "+CLIP: \"1234567\",129" , "ATA" , @@ -1902,7 +1903,7 @@ const char * TC_AG_ECS_BV_03_I[] = { hfp_test_item_t pts_ag_ecs_tests[] = { TEST_SEQUENCE(TC_AG_ECS_BV_01_I), TEST_SEQUENCE(TC_AG_ECS_BV_02_I), - // TEST_SEQUENCE(TC_AG_ECS_BV_03_I) + TEST_SEQUENCE(TC_AG_ECS_BV_03_I) }; From f5a23e02c7923a319e59f5fc9df1fa1bf8f23af0 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 13:48:02 +0100 Subject: [PATCH 15/31] backport tracking of hci_write_synchronous_flow_control_enable and add hsp_hs_test example --- example/embedded/Makefile.inc | 3 + example/embedded/hsp_hs_test.c | 236 +++++++++++++++++++++++++++++++++ src/hci.c | 6 + 3 files changed, 245 insertions(+) create mode 100644 example/embedded/hsp_hs_test.c diff --git a/example/embedded/Makefile.inc b/example/embedded/Makefile.inc index 87d74a0c6..28fb766c6 100644 --- a/example/embedded/Makefile.inc +++ b/example/embedded/Makefile.inc @@ -72,6 +72,7 @@ EXAMPLES = \ spp_counter \ spp_streamer \ gap_le_advertisements \ + hsp_hs_test \ EXAMPLES_USING_LE = \ ancs_client \ @@ -167,6 +168,8 @@ ble_client: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_CLIENT_OBJ} ${SM_REAL} b gap_le_advertisements: ${CORE_OBJ} ${COMMON_OBJ} ad_parser.c gap_le_advertisements.c ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ +hsp_hs_test: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} hsp_hs.o hsp_hs_test.c + ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ clean: rm -f ${EXAMPLES} diff --git a/example/embedded/hsp_hs_test.c b/example/embedded/hsp_hs_test.c new file mode 100644 index 000000000..c9e175e3f --- /dev/null +++ b/example/embedded/hsp_hs_test.c @@ -0,0 +1,236 @@ +/* + * 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 test for HSP Headset (!! UNDER DEVELOPMENT !!) +// +// Tested working setups: +// - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud +// +// Non working setups: +// - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 921600 baud +// - select(..) blocks > 400 ms -> num completed is received to late -> gaps between audio +// - looks like bug in select->FTDI driver as it works correct on Linux +// - OS X 10.11, USB Bluetooth Dongles... +// ***************************************************************************** + +#include "btstack-config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sdp.h" +#include "hsp_hs.h" + +#include "hci.h" +#include "l2cap.h" +#include "debug.h" + +static uint32_t hsp_service_buffer[150/4]; // implicit alignment to 4-byte memory address +static const uint8_t rfcomm_channel_nr = 1; +static const char hsp_hs_service_name[] = "Headset Test"; +static uint16_t sco_handle = 0; + +static char hs_cmd_buffer[100]; + +static int phase = 0; + +// input signal: pre-computed sine wave, 160 Hz +static const uint8_t sine[] = { + 0, 15, 31, 46, 61, 74, 86, 97, 107, 114, + 120, 124, 126, 126, 124, 120, 114, 107, 97, 86, + 74, 61, 46, 31, 15, 0, 241, 225, 210, 195, + 182, 170, 159, 149, 142, 136, 132, 130, 130, 132, + 136, 142, 149, 159, 170, 182, 195, 210, 225, 241, +}; + +#if 0 +// +// re-compute sine table for input signal +// +#include +#define TABLE_SIZE 50 +static uint8_t sine[TABLE_SIZE]; +static void compute_signal(void){ + #define TABLE_SIZE (50) + // create sine wave table + int i; + printf("static const uint8_t sine[] = {"); + for( i=0; i= sizeof(sine)) phase = 0; + } + hci_send_sco_packet_buffer(3 + frames_per_packet); + static int count = 0; + count++; + if ((count & 15) == 0) printf("Sent %u\n", count); +} + +static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){ + static int count = 0; + count++; + if ((count & 15)) return; + printf("SCO packets %u\n", count); + // hexdumpf(packet, size); +} + +void packet_handler(uint8_t * event, uint16_t event_size){ + + // printf("Packet handler event 0x%02x\n", event[0]); + + try_send_sco(); + + switch (event[0]) { + case BTSTACK_EVENT_STATE: + if (event[2] != HCI_STATE_WORKING) break; + // request num completed events for SCO packets + hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1); + break; + case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: + // printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n"); + // try_send_sco(); + break; + case DAEMON_EVENT_HCI_PACKET_SENT: + // printf("DAEMON_EVENT_HCI_PACKET_SENT\n"); + // try_send_sco(); + break; + case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE: + // printf("HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE status %u, %x\n", event[2], READ_BT_16(event, 3)); + if (event[2]) break; + sco_handle = READ_BT_16(event, 3); + break; + case HCI_EVENT_HSP_META: + switch (event[2]) { + case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: + if (event[3] == 0){ + printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); + // try_send_sco(); + } else { + printf("Audio connection establishment failed with status %u\n", event[3]); + } + break; + case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: + if (event[3] == 0){ + printf("Audio connection released.\n\n"); + sco_handle = 0; + } else { + printf("Audio connection releasing failed with status %u\n", event[3]); + } + break; + case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: + printf("Received microphone gain change %d\n", event[3]); + break; + case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: + printf("Received speaker gain change %d\n", event[3]); + break; + case HSP_SUBEVENT_RING: + printf("HS: RING RING!\n"); + break; + case HSP_SUBEVENT_AG_INDICATION: + memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); + int size = event_size <= sizeof(hs_cmd_buffer)? event_size : sizeof(hs_cmd_buffer); + memcpy(hs_cmd_buffer, &event[3], size - 1); + printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer); + break; + default: + printf("event not handled %u\n", event[2]); + break; + } + break; + default: + break; + } +} + +int btstack_main(int argc, const char * argv[]){ + +#ifdef TABLE_SIZE + compute_signal(); +#endif + + hci_register_sco_packet_handler(&sco_packet_handler); + + hci_discoverable_control(1); + hci_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO); + gap_set_local_name("BTstack HSP HS"); + + hsp_hs_init(rfcomm_channel_nr); + hsp_hs_register_packet_handler(packet_handler); + + sdp_init(); + memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer)); + hsp_hs_create_service((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_hs_service_name, 0); + + sdp_register_service_internal(NULL, (uint8_t *)hsp_service_buffer); + + // turn on! + hci_power_control(HCI_POWER_ON); + + return 0; +} diff --git a/src/hci.c b/src/hci.c index 93848d67c..1d9372f21 100644 --- a/src/hci.c +++ b/src/hci.c @@ -1303,6 +1303,12 @@ static void event_handler(uint8_t *packet, int size){ (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+14] & 0X80) >> 7 | // Octet 14, bit 7 (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5; // Octet 24, bit 6 } + if (COMMAND_COMPLETE_EVENT(packet, hci_write_synchronous_flow_control_enable)){ + if (packet[5] == 0){ + // @TODO cache value from hci_write_synchronous_flow_control_enable instead of assuming == 1 + hci_stack->synchronous_flow_control_enabled = 1; + } + } break; case HCI_EVENT_COMMAND_STATUS: From 03813843b6edb6f9bf5547296cf457afbd25ca4b Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 13:52:46 +0100 Subject: [PATCH 16/31] fix compile --- example/embedded/hsp_hs_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/embedded/hsp_hs_test.c b/example/embedded/hsp_hs_test.c index c9e175e3f..7fac687dc 100644 --- a/example/embedded/hsp_hs_test.c +++ b/example/embedded/hsp_hs_test.c @@ -140,7 +140,7 @@ static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t s // hexdumpf(packet, size); } -void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t * event, uint16_t event_size){ // printf("Packet handler event 0x%02x\n", event[0]); @@ -208,6 +208,7 @@ void packet_handler(uint8_t * event, uint16_t event_size){ } } +int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ #ifdef TABLE_SIZE From 5f1e82e4ed89b436a2027daba256b93b2ee13951 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 13:53:02 +0100 Subject: [PATCH 17/31] use stricter cmopiler checkes --- platforms/posix-cc2564b/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platforms/posix-cc2564b/Makefile b/platforms/posix-cc2564b/Makefile index 9b9791495..fb57cd9a3 100644 --- a/platforms/posix-cc2564b/Makefile +++ b/platforms/posix-cc2564b/Makefile @@ -13,9 +13,10 @@ include ${BTSTACK_ROOT}/chipset-cc256x/Makefile.inc CFLAGS += -I$(BTSTACK_ROOT)/chipset-cc256x -# CC = gcc-fsf-4.9 CFLAGS += -g -Wall -# CFLAGS += -Werror + +# +CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Werror VPATH += ${BTSTACK_ROOT}/platforms/posix/src VPATH += ${BTSTACK_ROOT}/chipset-cc256x From 4a544f8319628d9084f63ad15f333c2b100d0333 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 14:15:00 +0100 Subject: [PATCH 18/31] hfp ag: refactor access to the call states --- src/hfp_ag.c | 96 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 35 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 78bd944b1..55a676c38 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -96,6 +96,21 @@ static void hfp_run_for_context(hfp_connection_t *context); static void hfp_ag_setup_audio_connection(hfp_connection_t * connection); static void hfp_ag_hf_start_ringing(hfp_connection_t * context); +static hfp_call_status_t get_hfp_ag_call_state(void){ + return hfp_ag_call_state; + //return hfp_gsm_call_status(); +} + +static hfp_callsetup_status_t get_hfp_ag_callsetup_state(void){ + return hfp_ag_callsetup_state; + //return hfp_gsm_callsetup_status(); +} + +static hfp_callheld_status_t get_hfp_ag_callheld_state(void){ + return hfp_ag_callheld_state; + // return hfp_gsm_callheld_status(); +} + hfp_generic_status_indicator_t * get_hfp_generic_status_indicators(); int get_hfp_generic_status_indicators_nr(); void set_hfp_generic_status_indicators(hfp_generic_status_indicator_t * indicators, int indicator_nr); @@ -626,14 +641,24 @@ static void hfp_ag_slc_established(hfp_connection_t * context){ hfp_init_link_settings(context); // if active call exist, set per-connection state active, too (when audio is on) - if (hfp_ag_call_state == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE; } // if AG is ringing, also start ringing on the HF - if (hfp_ag_call_state == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && - hfp_ag_callsetup_state == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ + if (get_hfp_ag_call_state() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && + get_hfp_ag_callsetup_state() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ hfp_ag_hf_start_ringing(context); } + if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || + (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || + (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ + + printf("hfp_ag_slc_established \n"); + printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); + printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); + printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); + exit(1); + } } static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * context){ @@ -1119,9 +1144,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect switch (event){ case HFP_AG_INCOMING_CALL: hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); hfp_ag_trigger_incoming_call(); @@ -1132,7 +1157,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); hfp_ag_trigger_incoming_call(); @@ -1148,9 +1173,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect // clear CLIP hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG); clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); @@ -1162,7 +1187,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: printf("AG: current call is placed on hold, incoming call gets active\n"); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); @@ -1179,9 +1204,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_HELD_CALL_JOINED_BY_AG: hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG); - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - switch (hfp_ag_callheld_state){ + switch (get_hfp_ag_callheld_state()){ case HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED: printf("AG: joining held call with active call\n"); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); @@ -1201,9 +1226,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); @@ -1224,9 +1249,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_response_and_hold_active = 1; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD; @@ -1250,9 +1275,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_response_and_hold_active = 1; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD; @@ -1300,9 +1325,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_transfer_callsetup_state(); @@ -1331,9 +1356,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_AG); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_trigger_reject_call(); @@ -1356,9 +1381,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); // clear CLIP clip_type = 0; - switch (hfp_ag_call_state){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (hfp_ag_callsetup_state){ + switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: hfp_ag_stop_ringing(); printf("Incoming call interrupted\n"); @@ -1446,7 +1471,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1); // put current call on hold if active - if (hfp_ag_call_state == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ printf("AG putting current call on hold for new outgoing call\n"); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS); indicator_index = get_ag_indicator_index_for_name("callheld"); @@ -1488,7 +1513,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); hfp_ag_transfer_call_state(); hfp_ag_transfer_callsetup_state(); - if (hfp_ag_callheld_state == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){ + if (get_hfp_ag_callheld_state() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){ hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); hfp_ag_transfer_callheld_state(); } @@ -1498,14 +1523,14 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - if ( (hfp_ag_callsetup_state != hfp_gsm_callsetup_status()) || - (hfp_ag_callheld_state != hfp_gsm_callheld_status()) || - (hfp_ag_call_state != hfp_gsm_call_status()) ){ + if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || + (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || + (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ printf("event %d\n", event); - printf("callsetup %d - %d \n", hfp_ag_callsetup_state, hfp_gsm_callsetup_status()); - printf("callheld %d - %d \n", hfp_ag_callheld_state, hfp_gsm_callheld_status()); - printf("call %d - %d \n", hfp_ag_call_state, hfp_gsm_call_status()); + printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); + printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); + printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); exit(1); } } @@ -1794,14 +1819,14 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_ // Releases all active calls (if any exist) and accepts the other (held or waiting) call. context->command = HFP_CMD_NONE; context->ok_pending = 1; - if (hfp_ag_callsetup_state != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ printf("AG: Call Dropped, Accept new call\n"); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); } else { printf("AG: Call Dropped, Resume held call\n"); } - if (hfp_ag_callheld_state != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ + if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); } @@ -1812,7 +1837,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_ context->command = HFP_CMD_NONE; context->ok_pending = 1; // only update if callsetup changed - if (hfp_ag_callsetup_state != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ printf("AG: Call on Hold, Accept new call\n"); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); @@ -1827,7 +1852,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_ // Adds a held call to the conversation. context->command = HFP_CMD_NONE; context->ok_pending = 1; - if (hfp_ag_callheld_state != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ + if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ printf("AG: Join 3-way-call\n"); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); @@ -1950,6 +1975,7 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, hfp_ag_callsetup_state = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; hfp_ag_callheld_state = HFP_CALLHELD_STATUS_NO_CALLS_HELD; + hfp_ag_response_and_hold_active = 0; clip_type = 0; // 0 == not set memset(clip_number,0,sizeof(clip_number)); From 599dcf1ca27e3ac45cd502167b304e7a5d8fa154 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 14:18:08 +0100 Subject: [PATCH 19/31] hfp ag: move gsm handle event --- src/hfp_ag.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 55a676c38..2589f21cf 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1143,7 +1143,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect //printf("hfp_ag_call_sm event %d \n", event); switch (event){ case HFP_AG_INCOMING_CALL: - hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ @@ -1171,7 +1170,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: // clear CLIP - hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG); clip_type = 0; switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: @@ -1203,7 +1201,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_HELD_CALL_JOINED_BY_AG: - hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG); switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: switch (get_hfp_ag_callheld_state()){ @@ -1223,7 +1220,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: - hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1246,7 +1242,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: - hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1272,7 +1267,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: - hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1299,7 +1293,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG: case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF: - hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG); if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; hfp_ag_response_and_hold_active = 0; @@ -1310,7 +1303,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG: case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF: - hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG); if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; hfp_ag_response_and_hold_active = 0; @@ -1322,7 +1314,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_TERMINATE_CALL_BY_HF: - hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1353,7 +1344,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_TERMINATE_CALL_BY_AG: - hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_AG); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1378,7 +1368,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; case HFP_AG_CALL_DROPPED: - hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); // clear CLIP clip_type = 0; switch (get_hfp_ag_call_state()){ @@ -1421,7 +1410,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_run_for_context(connection); break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, (const char *) &connection->line_buffer[3]); @@ -1435,7 +1423,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; hfp_emit_event(hfp_callback, HFP_SUBEVENT_REDIAL_LAST_NUMBER, 0); @@ -1448,7 +1435,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED); connection->call_state = HFP_CALL_IDLE; connection->send_error = 1; hfp_run_for_context(connection); @@ -1461,7 +1447,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ACCEPTED); connection->ok_pending = 1; connection->call_state = HFP_CALL_OUTGOING_DIALING; @@ -1483,14 +1468,12 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_OUTGOING_CALL_RINGING: - // hfp_gsm_handle_event(); - connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING); + // nection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING); if (!connection){ log_info("hfp_ag_call_sm: did not find outgoing connection in dialing state"); break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_RINGING); connection->call_state = HFP_CALL_OUTGOING_RINGING; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE); hfp_ag_transfer_callsetup_state(); @@ -1507,7 +1490,6 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ESTABLISHED); connection->call_state = HFP_CALL_ACTIVE; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); @@ -1522,7 +1504,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect default: break; } - + hfp_gsm_handle_event(event); if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ From 729ed62ea06eca1ca60af1988b78d7b1b37dafe7 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 14:19:37 +0100 Subject: [PATCH 20/31] send write sco flow control enable if #HAVE_SCO_OVER_HCI --- example/embedded/hsp_hs_test.c | 5 +++-- src/hci.c | 21 +++++++++++++++++++++ src/hci.h | 7 ++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/example/embedded/hsp_hs_test.c b/example/embedded/hsp_hs_test.c index 7fac687dc..567e4b906 100644 --- a/example/embedded/hsp_hs_test.c +++ b/example/embedded/hsp_hs_test.c @@ -39,6 +39,8 @@ // // Minimal test for HSP Headset (!! UNDER DEVELOPMENT !!) // +// Requires HAVE_SCO and HAVE_SCO_OVER_HCI to be defined +// // Tested working setups: // - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud // @@ -149,8 +151,7 @@ static void packet_handler(uint8_t * event, uint16_t event_size){ switch (event[0]) { case BTSTACK_EVENT_STATE: if (event[2] != HCI_STATE_WORKING) break; - // request num completed events for SCO packets - hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1); + printf("Working!\n"); break; case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: // printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n"); diff --git a/src/hci.c b/src/hci.c index 1d9372f21..13cd812b9 100644 --- a/src/hci.c +++ b/src/hci.c @@ -1000,6 +1000,10 @@ static void hci_initializing_run(void){ hci_send_cmd(&hci_write_scan_enable, (hci_stack->connectable << 1) | hci_stack->discoverable); // page scan hci_stack->substate = HCI_INIT_W4_WRITE_SCAN_ENABLE; break; + case HCI_INIT_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE: + hci_stack->substate = HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE; + hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1); // SCO tracking enabled + break; #ifdef HAVE_BLE // LE INIT case HCI_INIT_LE_READ_BUFFER_SIZE: @@ -1188,17 +1192,34 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){ return; } break; + case HCI_INIT_W4_WRITE_PAGE_TIMEOUT: + break; case HCI_INIT_W4_LE_READ_BUFFER_SIZE: // skip write le host if not supported (e.g. on LE only EM9301) if (hci_stack->local_supported_commands[0] & 0x02) break; hci_stack->substate = HCI_INIT_LE_SET_SCAN_PARAMETERS; return; + +#ifdef HAVE_SCO_OVER_HCI + case HCI_INIT_W4_WRITE_SCAN_ENABLE: + // just go to next state + break; + case HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE: + if (!hci_le_supported()){ + // SKIP LE init for Classic only configuration + hci_stack->substate = HCI_INIT_DONE; + return; + } + break; +#else case HCI_INIT_W4_WRITE_SCAN_ENABLE: if (!hci_le_supported()){ // SKIP LE init for Classic only configuration hci_stack->substate = HCI_INIT_DONE; return; } +#endif + break; default: break; } diff --git a/src/hci.h b/src/hci.h index 1cd24df9a..99cbf7bba 100644 --- a/src/hci.h +++ b/src/hci.h @@ -591,15 +591,16 @@ typedef enum hci_init_state{ HCI_INIT_W4_WRITE_SIMPLE_PAIRING_MODE, HCI_INIT_WRITE_PAGE_TIMEOUT, HCI_INIT_W4_WRITE_PAGE_TIMEOUT, - // HCI_INIT_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - // HCI_INIT_W4_SYNCHRONOUS_FLOW_CONTROL_ENABLE, - HCI_INIT_WRITE_CLASS_OF_DEVICE, HCI_INIT_W4_WRITE_CLASS_OF_DEVICE, HCI_INIT_WRITE_LOCAL_NAME, HCI_INIT_W4_WRITE_LOCAL_NAME, HCI_INIT_WRITE_SCAN_ENABLE, HCI_INIT_W4_WRITE_SCAN_ENABLE, + + HCI_INIT_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, + HCI_INIT_LE_READ_BUFFER_SIZE, HCI_INIT_W4_LE_READ_BUFFER_SIZE, HCI_INIT_WRITE_LE_HOST_SUPPORTED, From 6b26a6b00b8ab2d83acd9ebb874608e9de33bd9e Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 14:20:22 +0100 Subject: [PATCH 21/31] add HAVE_SCO_OVER_HCI for posix-cc2564b --- platforms/posix-cc2564b/btstack-config.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/platforms/posix-cc2564b/btstack-config.h b/platforms/posix-cc2564b/btstack-config.h index 0448f2826..6aa63e669 100644 --- a/platforms/posix-cc2564b/btstack-config.h +++ b/platforms/posix-cc2564b/btstack-config.h @@ -3,22 +3,23 @@ #ifndef __BTSTACK_CONFIG #define __BTSTACK_CONFIG -#define HAVE_TRANSPORT_USB +#define ENABLE_LOG_ERROR +#define ENABLE_LOG_INFO #define HAVE_BLE -#define USE_POSIX_RUN_LOOP -#define HAVE_SDP +#define HAVE_BZERO +#define HAVE_HCI_DUMP +#define HAVE_MALLOC #define HAVE_RFCOMM -#define REMOTE_DEVICE_DB remote_device_db_iphone +#define HAVE_SDP #define HAVE_SO_NOSIGPIPE #define HAVE_TIME -#define HAVE_MALLOC -#define HAVE_BZERO -#define SDP_DES_DUMP -#define ENABLE_LOG_INFO -#define ENABLE_LOG_ERROR -#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof benep heade, avoid memcpy +#define HAVE_SCO +#define HAVE_SCO_OVER_HCI #define HCI_ACL_PAYLOAD_SIZE (1691 + 4) -#define HAVE_HCI_DUMP +#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof BNEP header, avoid memcpy +#define REMOTE_DEVICE_DB remote_device_db_iphone #define SDP_DES_DUMP +#define SDP_DES_DUMP +#define USE_POSIX_RUN_LOOP #endif From cb335d16e8158fbd79a25fdd27778a5617f1e3bc Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 14:32:59 +0100 Subject: [PATCH 22/31] current config OS X + Linux --- platforms/posix-cc2564b/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/platforms/posix-cc2564b/main.c b/platforms/posix-cc2564b/main.c index b37a630d1..f1da871e9 100644 --- a/platforms/posix-cc2564b/main.c +++ b/platforms/posix-cc2564b/main.c @@ -93,11 +93,23 @@ int main(int argc, const char * argv[]){ btstack_memory_init(); run_loop_init(RUN_LOOP_POSIX); +#if 0 + // Ubuntu + + // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT + hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER); + + // pick serial port + hci_uart_config_cc256x.device_name = "/dev/ttyUSB0"; +#else + // OS X + // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); // pick serial port hci_uart_config_cc256x.device_name = "/dev/tty.usbserial-A900K0VK"; +#endif // init HCI hci_transport_t * transport = hci_transport_h4_instance(); From f88e4d83b955422df136078e17b1174bd6784598 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 14:33:17 +0100 Subject: [PATCH 23/31] fix HSP HS SDP record --- src/hsp_hs.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hsp_hs.c b/src/hsp_hs.c index a8f037ed2..4b413e78d 100644 --- a/src/hsp_hs.c +++ b/src/hsp_hs.c @@ -168,9 +168,10 @@ void hsp_hs_create_service(uint8_t * service, int rfcomm_channel_nr, const char de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); attribute = de_push_sequence(service); { - // "UUID for PAN Service" - de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_Headset_HS); - de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_GenericAudio); + // see Bluetooth Erratum #3507 + de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_HSP); // 0x1108 + de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_Headset_HS); // 0x1131 + de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_GenericAudio); // 0x1203 } de_pop_sequence(service, attribute); @@ -205,12 +206,12 @@ void hsp_hs_create_service(uint8_t * service, int rfcomm_channel_nr, const char de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); attribute = de_push_sequence(service); { - uint8_t *sppProfile = de_push_sequence(attribute); + uint8_t *hsp_profile = de_push_sequence(attribute); { - de_add_number(sppProfile, DE_UUID, DE_SIZE_16, SDP_HSP); - de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0102); // Verision 1.2 + de_add_number(hsp_profile, DE_UUID, DE_SIZE_16, SDP_HSP); + de_add_number(hsp_profile, DE_UINT, DE_SIZE_16, 0x0102); // Verision 1.2 } - de_pop_sequence(attribute, sppProfile); + de_pop_sequence(attribute, hsp_profile); } de_pop_sequence(service, attribute); From c0f03171d904ce7e5e20d06a27e2c579439ab4bb Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 14:33:43 +0100 Subject: [PATCH 24/31] outdated comment --- src/hci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hci.c b/src/hci.c index 13cd812b9..c485e5361 100644 --- a/src/hci.c +++ b/src/hci.c @@ -1326,7 +1326,6 @@ static void event_handler(uint8_t *packet, int size){ } if (COMMAND_COMPLETE_EVENT(packet, hci_write_synchronous_flow_control_enable)){ if (packet[5] == 0){ - // @TODO cache value from hci_write_synchronous_flow_control_enable instead of assuming == 1 hci_stack->synchronous_flow_control_enabled = 1; } } From 1d5aea23425fbb7493b25c2ad0b9d5bb5e5b2998 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 14:48:28 +0100 Subject: [PATCH 25/31] hfp ag cleanup --- src/hfp_ag.c | 94 ++++++++++++++++++---------------------------------- 1 file changed, 32 insertions(+), 62 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 2589f21cf..7ca098bba 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -98,7 +98,7 @@ static void hfp_ag_hf_start_ringing(hfp_connection_t * context); static hfp_call_status_t get_hfp_ag_call_state(void){ return hfp_ag_call_state; - //return hfp_gsm_call_status(); + // return hfp_gsm_call_status(); } static hfp_callsetup_status_t get_hfp_ag_callsetup_state(void){ @@ -649,16 +649,6 @@ static void hfp_ag_slc_established(hfp_connection_t * context){ get_hfp_ag_callsetup_state() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ hfp_ag_hf_start_ringing(context); } - if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || - (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || - (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ - - printf("hfp_ag_slc_established \n"); - printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); - printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); - printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); - exit(1); - } } static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * context){ @@ -1143,59 +1133,38 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect //printf("hfp_ag_call_sm event %d \n", event); switch (event){ case HFP_AG_INCOMING_CALL: - switch (get_hfp_ag_call_state()){ + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); + + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); + hfp_ag_trigger_incoming_call(); + + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (get_hfp_ag_callsetup_state()){ - case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); - hfp_ag_trigger_incoming_call(); - printf("AG rings\n"); - break; - default: - break; - } + printf("AG rings\n"); break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - switch (get_hfp_ag_callsetup_state()){ - case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); - hfp_ag_trigger_incoming_call(); - printf("AG call waiting\n"); - break; - default: - break; - } + printf("AG call waiting\n"); break; } break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: - // clear CLIP + if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + clip_type = 0; - switch (get_hfp_ag_call_state()){ + + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - switch (get_hfp_ag_callsetup_state()){ - case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_ag_accept_call(); - printf("AG answers call, accept call by GSM\n"); - break; - default: - break; - } + hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); + hfp_ag_ag_accept_call(); + printf("AG answers call, accept call by GSM\n"); break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - switch (get_hfp_ag_callsetup_state()){ - case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: - printf("AG: current call is placed on hold, incoming call gets active\n"); - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); - hfp_ag_transfer_callsetup_state(); - hfp_ag_transfer_callheld_state(); - break; - default: - break; - } + printf("AG: current call is placed on hold, incoming call gets active\n"); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); + hfp_ag_transfer_callsetup_state(); + hfp_ag_transfer_callheld_state(); break; } break; @@ -1504,17 +1473,18 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect default: break; } + hfp_gsm_handle_event(event); - if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || - (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || - (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ + // if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || + // (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || + // (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ - printf("event %d\n", event); - printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); - printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); - printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); - exit(1); - } + // printf("event %d\n", event); + // printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); + // printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); + // printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); + // exit(1); + // } } static void hfp_run_for_context(hfp_connection_t *context){ From e8d65f6610ed89bf7574053c98a7c9734fb3ad60 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 14:53:33 +0100 Subject: [PATCH 26/31] hfp ag cleanup --- src/hfp_ag.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 7ca098bba..90b05696b 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -96,10 +96,6 @@ static void hfp_run_for_context(hfp_connection_t *context); static void hfp_ag_setup_audio_connection(hfp_connection_t * connection); static void hfp_ag_hf_start_ringing(hfp_connection_t * context); -static hfp_call_status_t get_hfp_ag_call_state(void){ - return hfp_ag_call_state; - // return hfp_gsm_call_status(); -} static hfp_callsetup_status_t get_hfp_ag_callsetup_state(void){ return hfp_ag_callsetup_state; @@ -641,11 +637,11 @@ static void hfp_ag_slc_established(hfp_connection_t * context){ hfp_init_link_settings(context); // if active call exist, set per-connection state active, too (when audio is on) - if (get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE; } // if AG is ringing, also start ringing on the HF - if (get_hfp_ag_call_state() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && + if (hfp_gsm_call_status() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && get_hfp_ag_callsetup_state() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ hfp_ag_hf_start_ringing(context); } @@ -1170,7 +1166,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_AG_HELD_CALL_JOINED_BY_AG: - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: switch (get_hfp_ag_callheld_state()){ case HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED: @@ -1191,7 +1187,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1213,7 +1209,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1238,7 +1234,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1285,7 +1281,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_TERMINATE_CALL_BY_HF: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1315,7 +1311,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_TERMINATE_CALL_BY_AG: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1339,7 +1335,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_CALL_DROPPED: // clear CLIP clip_type = 0; - switch (get_hfp_ag_call_state()){ + switch (hfp_gsm_call_status()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1425,7 +1421,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1); // put current call on hold if active - if (get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ printf("AG putting current call on hold for new outgoing call\n"); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS); indicator_index = get_ag_indicator_index_for_name("callheld"); @@ -1474,17 +1470,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } - hfp_gsm_handle_event(event); - // if ( (get_hfp_ag_callsetup_state() != hfp_gsm_callsetup_status()) || - // (get_hfp_ag_callheld_state() != hfp_gsm_callheld_status()) || - // (get_hfp_ag_call_state() != hfp_gsm_call_status()) ){ - - // printf("event %d\n", event); - // printf("callsetup %d - %d \n", get_hfp_ag_callsetup_state(), hfp_gsm_callsetup_status()); - // printf("callheld %d - %d \n", get_hfp_ag_callheld_state(), hfp_gsm_callheld_status()); - // printf("call %d - %d \n", get_hfp_ag_call_state(), hfp_gsm_call_status()); - // exit(1); - // } + hfp_gsm_handle_event(event); } static void hfp_run_for_context(hfp_connection_t *context){ From ff67e9a4a5fe10315f90d7d89e01783c90fe4b85 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 15:47:19 +0100 Subject: [PATCH 27/31] cleanup hfp ag --- src/hfp_ag.c | 157 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 48 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 90b05696b..a2cef322f 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -96,6 +96,10 @@ static void hfp_run_for_context(hfp_connection_t *context); static void hfp_ag_setup_audio_connection(hfp_connection_t * connection); static void hfp_ag_hf_start_ringing(hfp_connection_t * context); +static hfp_call_status_t get_hfp_ag_call_state(void){ + // return hfp_ag_call_state; + return hfp_gsm_call_status(); +} static hfp_callsetup_status_t get_hfp_ag_callsetup_state(void){ return hfp_ag_callsetup_state; @@ -637,11 +641,11 @@ static void hfp_ag_slc_established(hfp_connection_t * context){ hfp_init_link_settings(context); // if active call exist, set per-connection state active, too (when audio is on) - if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE; } // if AG is ringing, also start ringing on the HF - if (hfp_gsm_call_status() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && + if (get_hfp_ag_call_state() == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS && get_hfp_ag_callsetup_state() == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){ hfp_ag_hf_start_ringing(context); } @@ -1056,7 +1060,7 @@ static void hfp_ag_set_callheld_state(hfp_callheld_status_t state){ } static void hfp_ag_set_call_state(hfp_call_status_t state){ - hfp_ag_call_state = state; + // hfp_ag_call_state = state; hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); if (!indicator){ log_error("hfp_ag_set_call_state: call indicator is missing"); @@ -1064,6 +1068,15 @@ static void hfp_ag_set_call_state(hfp_call_status_t state){ indicator->status = state; } +static void hfp_ag_set_call_indicator(){ + // hfp_ag_call_state = state; + hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); + if (!indicator){ + log_error("hfp_ag_set_call_state: call indicator is missing"); + }; + indicator->status = hfp_gsm_call_status(); +} + static void hfp_ag_stop_ringing(void){ linked_list_iterator_t it; linked_list_iterator_init(&it, hfp_get_connections()); @@ -1129,48 +1142,74 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect //printf("hfp_ag_call_sm event %d \n", event); switch (event){ case HFP_AG_INCOMING_CALL: - if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); - - hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); - hfp_ag_trigger_incoming_call(); - - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - printf("AG rings\n"); + switch (get_hfp_ag_callsetup_state()){ + case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); + hfp_ag_trigger_incoming_call(); + printf("AG rings\n"); + break; + default: + break; + } break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - printf("AG call waiting\n"); + switch (get_hfp_ag_callsetup_state()){ + case HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS); + hfp_ag_trigger_incoming_call(); + printf("AG call waiting\n"); + break; + default: + break; + } break; } break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: - if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - + // clear CLIP clip_type = 0; - - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); - hfp_ag_ag_accept_call(); - printf("AG answers call, accept call by GSM\n"); + switch (get_hfp_ag_callsetup_state()){ + case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG); + hfp_ag_set_call_indicator(); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + hfp_ag_ag_accept_call(); + printf("AG answers call, accept call by GSM\n"); + break; + default: + break; + } break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - printf("AG: current call is placed on hold, incoming call gets active\n"); - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); - hfp_ag_transfer_callsetup_state(); - hfp_ag_transfer_callheld_state(); + switch (get_hfp_ag_callsetup_state()){ + case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + printf("AG: current call is placed on hold, incoming call gets active\n"); + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); + hfp_ag_transfer_callsetup_state(); + hfp_ag_transfer_callheld_state(); + break; + default: + break; + } break; } break; case HFP_AG_HELD_CALL_JOINED_BY_AG: - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: switch (get_hfp_ag_callheld_state()){ case HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED: printf("AG: joining held call with active call\n"); + hfp_gsm_handle_event(HFP_AG_HELD_CALL_JOINED_BY_AG); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); hfp_ag_transfer_callheld_state(); hfp_emit_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL, 0); @@ -1187,12 +1226,13 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); + hfp_ag_set_call_indicator(); hfp_ag_hf_accept_call(connection); printf("HF answers call, accept call by GSM\n"); hfp_emit_event(hfp_callback, HFP_CMD_CALL_ANSWERED, 0); @@ -1209,15 +1249,16 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG); hfp_ag_response_and_hold_active = 1; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD; hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state); // as with regualr call - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); + hfp_ag_set_call_indicator(); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_ag_accept_call(); printf("AG response and hold - hold by AG\n"); @@ -1234,15 +1275,16 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF); hfp_ag_response_and_hold_active = 1; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD; hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state); // as with regualr call - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); + hfp_ag_set_call_indicator(); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_hf_accept_call(connection); printf("AG response and hold - hold by HF\n"); @@ -1260,6 +1302,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF: if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG); hfp_ag_response_and_hold_active = 0; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED; hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state); @@ -1270,21 +1313,23 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF: if (!hfp_ag_response_and_hold_active) break; if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break; + hfp_gsm_handle_event(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG); hfp_ag_response_and_hold_active = 0; hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED; hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state); // from terminate by ag - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_ag_set_call_indicator(); hfp_ag_trigger_terminate_call(); break; case HFP_AG_TERMINATE_CALL_BY_HF: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_transfer_callsetup_state(); hfp_ag_trigger_reject_call(); @@ -1292,6 +1337,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; case HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE: case HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_transfer_callsetup_state(); printf("AG terminate outgoing call process\n"); @@ -1300,7 +1346,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_HF); + hfp_ag_set_call_indicator(); hfp_ag_transfer_call_state(); connection->call_state = HFP_CALL_IDLE; printf("AG terminate call\n"); @@ -1311,10 +1358,11 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_TERMINATE_CALL_BY_AG: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_AG); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_trigger_reject_call(); printf("AG Rejected Incoming call, AG terminate call\n"); @@ -1323,8 +1371,9 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: + hfp_gsm_handle_event(HFP_AG_TERMINATE_CALL_BY_AG); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_ag_set_call_indicator(); hfp_ag_trigger_terminate_call(); printf("AG terminate call\n"); break; @@ -1335,7 +1384,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect case HFP_AG_CALL_DROPPED: // clear CLIP clip_type = 0; - switch (hfp_gsm_call_status()){ + switch (get_hfp_ag_call_state()){ case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS: switch (get_hfp_ag_callsetup_state()){ case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS: @@ -1350,16 +1399,19 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect default: break; } + hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); hfp_ag_transfer_callsetup_state(); break; case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT: if (hfp_ag_response_and_hold_active) { + hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED; hfp_ag_send_response_and_hold_state(hfp_ag_response_and_hold_state); } + hfp_gsm_handle_event(HFP_AG_CALL_DROPPED); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_ag_set_call_indicator(); hfp_ag_trigger_terminate_call(); printf("AG notify call dropped\n"); break; @@ -1375,6 +1427,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect hfp_run_for_context(connection); break; } + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; hfp_emit_string_event(hfp_callback, HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER, (const char *) &connection->line_buffer[3]); @@ -1388,6 +1441,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } + hfp_gsm_handle_event(HFP_AG_OUTGOING_REDIAL_INITIATED); connection->call_state = HFP_CALL_OUTGOING_INITIATED; hfp_emit_event(hfp_callback, HFP_SUBEVENT_REDIAL_LAST_NUMBER, 0); @@ -1400,12 +1454,13 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_REJECTED); connection->call_state = HFP_CALL_IDLE; connection->send_error = 1; hfp_run_for_context(connection); break; - case HFP_AG_OUTGOING_CALL_ACCEPTED: + case HFP_AG_OUTGOING_CALL_ACCEPTED:{ connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_INITIATED); if (!connection){ log_info("hfp_ag_call_sm: did not find outgoing connection in initiated state"); @@ -1416,12 +1471,15 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect connection->call_state = HFP_CALL_OUTGOING_DIALING; // trigger callsetup to be + int put_call_on_hold = get_hfp_ag_call_state() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT; + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ACCEPTED); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_DIALING_STATE); indicator_index = get_ag_indicator_index_for_name("callsetup"); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, indicator_index, 1); // put current call on hold if active - if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ + if (put_call_on_hold){ printf("AG putting current call on hold for new outgoing call\n"); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS); indicator_index = get_ag_indicator_index_for_name("callheld"); @@ -1431,20 +1489,22 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect // start audio if needed hfp_ag_establish_audio_connection(connection->remote_addr); break; - + } case HFP_AG_OUTGOING_CALL_RINGING: - // nection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING); + // hfp_gsm_handle_event(); + connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_DIALING); if (!connection){ log_info("hfp_ag_call_sm: did not find outgoing connection in dialing state"); break; } + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_RINGING); connection->call_state = HFP_CALL_OUTGOING_RINGING; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE); hfp_ag_transfer_callsetup_state(); break; - case HFP_AG_OUTGOING_CALL_ESTABLISHED: + case HFP_AG_OUTGOING_CALL_ESTABLISHED:{ // get outgoing call connection = hfp_ag_connection_for_call_state(HFP_CALL_OUTGOING_RINGING); if (!connection){ @@ -1455,22 +1515,23 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect break; } + int CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS = get_hfp_ag_callheld_state() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS; + hfp_gsm_handle_event(HFP_AG_OUTGOING_CALL_ESTABLISHED); connection->call_state = HFP_CALL_ACTIVE; hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT); + hfp_ag_set_call_indicator(); hfp_ag_transfer_call_state(); hfp_ag_transfer_callsetup_state(); - if (get_hfp_ag_callheld_state() == HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){ + if (CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS){ hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); hfp_ag_transfer_callheld_state(); } break; - + } default: break; } - - hfp_gsm_handle_event(event); + } static void hfp_run_for_context(hfp_connection_t *context){ From d2d9e77d814b8378e2163077e100dc6781ac8051 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 16:16:42 +0100 Subject: [PATCH 28/31] cleanup hfp ag --- src/hfp_ag.c | 143 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 59 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index a2cef322f..cf9b89c78 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -1060,7 +1060,6 @@ static void hfp_ag_set_callheld_state(hfp_callheld_status_t state){ } static void hfp_ag_set_call_state(hfp_call_status_t state){ - // hfp_ag_call_state = state; hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); if (!indicator){ log_error("hfp_ag_set_call_state: call indicator is missing"); @@ -1068,8 +1067,15 @@ static void hfp_ag_set_call_state(hfp_call_status_t state){ indicator->status = state; } +static void hfp_ag_set_callheld_indicator(){ + hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callheld"); + if (!indicator){ + log_error("hfp_ag_set_callheld_state: callheld indicator is missing"); + }; + indicator->status = hfp_gsm_callheld_status(); +} + static void hfp_ag_set_call_indicator(){ - // hfp_ag_call_state = state; hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); if (!indicator){ log_error("hfp_ag_set_call_state: call indicator is missing"); @@ -1139,6 +1145,10 @@ static int call_setup_state_machine(hfp_connection_t * connection){ // connection is used to identify originating HF static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connection){ int indicator_index; + int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup"); + int callheld_indicator_index = get_ag_indicator_index_for_name("callheld"); + int call_indicator_index = get_ag_indicator_index_for_name("call"); + //printf("hfp_ag_call_sm event %d \n", event); switch (event){ case HFP_AG_INCOMING_CALL: @@ -1528,6 +1538,70 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect } break; } + + case HFP_AG_CALL_HOLD_USER_BUSY: + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_USER_BUSY); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); + connection->call_state = HFP_CALL_ACTIVE; + printf("AG: Call Waiting, User Busy\n"); + break; + case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: + // Releases all active calls (if any exist) and accepts the other (held or waiting) call. + if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + printf("AG: Call Dropped, Accept new call\n"); + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); + } else { + printf("AG: Call Dropped, Resume held call\n"); + } + if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); + } + connection->call_state = HFP_CALL_ACTIVE; + break; + case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: + + // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call. + // only update if callsetup changed + if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + printf("AG: Call on Hold, Accept new call\n"); + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); + } else { + printf("AG: Swap calls\n"); + } + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); + connection->call_state = HFP_CALL_ACTIVE; + break; + case HFP_AG_CALL_HOLD_ADD_HELD_CALL: + // Adds a held call to the conversation. + if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ + printf("AG: Join 3-way-call\n"); + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_ADD_HELD_CALL); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); + hfp_emit_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL, 0); + } + connection->call_state = HFP_CALL_ACTIVE; + break; + case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS: + // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer) + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS); + printf("AG: Transfer call -> Connect two calls and disconnect\n"); + hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1); + connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); + connection->call_state = HFP_CALL_IDLE; + break; + default: break; } @@ -1802,73 +1876,24 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_ case HFP_CMD_CALL_HOLD: { // TODO: fully implement this log_error("HFP: unhandled call hold type %c", context->line_buffer[0]); - int callsetup_indicator_index = get_ag_indicator_index_for_name("callsetup"); - int callheld_indicator_index = get_ag_indicator_index_for_name("callheld"); - int call_indicator_index = get_ag_indicator_index_for_name("call"); + context->command = HFP_CMD_NONE; + context->ok_pending = 1; + switch (context->line_buffer[0]){ case '0': - context->command = HFP_CMD_NONE; - context->ok_pending = 1; - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); - context->call_state = HFP_CALL_ACTIVE; - printf("AG: Call Waiting, User Busy\n"); + hfp_ag_call_sm(HFP_AG_CALL_HOLD_USER_BUSY, context); break; case '1': - // Releases all active calls (if any exist) and accepts the other (held or waiting) call. - context->command = HFP_CMD_NONE; - context->ok_pending = 1; - if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ - printf("AG: Call Dropped, Accept new call\n"); - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); - } else { - printf("AG: Call Dropped, Resume held call\n"); - } - if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); - } - context->call_state = HFP_CALL_ACTIVE; + hfp_ag_call_sm(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, context); break; case '2': - // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call. - context->command = HFP_CMD_NONE; - context->ok_pending = 1; - // only update if callsetup changed - if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ - printf("AG: Call on Hold, Accept new call\n"); - hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); - } else { - printf("AG: Swap calls\n"); - } - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_CALL_ON_HOLD_OR_SWAPPED); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); - context->call_state = HFP_CALL_ACTIVE; + hfp_ag_call_sm(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, context); break; case '3': - // Adds a held call to the conversation. - context->command = HFP_CMD_NONE; - context->ok_pending = 1; - if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ - printf("AG: Join 3-way-call\n"); - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); - hfp_emit_event(hfp_callback, HFP_SUBEVENT_CONFERENCE_CALL, 0); - } - context->call_state = HFP_CALL_ACTIVE; + hfp_ag_call_sm(HFP_AG_CALL_HOLD_ADD_HELD_CALL, context); break; case '4': - // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer) - context->command = HFP_CMD_NONE; - context->ok_pending = 1; - printf("AG: Transfer call -> Connect two calls and disconnect\n"); - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); - hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, call_indicator_index, 1); - context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); - context->call_state = HFP_CALL_IDLE; + hfp_ag_call_sm(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS, context); break; default: break; From 5bac07baa2ecee131ff6440ca7cba6f1412d450e Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 16:16:54 +0100 Subject: [PATCH 29/31] cleanup hfp ag --- src/hfp.h | 8 +++++++- src/hfp_gsm_model.c | 29 ++++++++++++++--------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/hfp.h b/src/hfp.h index 07b348631..47f9d9af5 100644 --- a/src/hfp.h +++ b/src/hfp.h @@ -255,6 +255,7 @@ typedef enum { HFP_CALLHELD_STATUS_CALL_ON_HOLD_AND_NO_ACTIVE_CALLS } hfp_callheld_status_t; + typedef enum { HFP_AG_INCOMING_CALL, HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG, @@ -275,7 +276,12 @@ typedef enum { HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG, HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF, HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF, - HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF + HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF, + HFP_AG_CALL_HOLD_USER_BUSY, + HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, + HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL, + HFP_AG_CALL_HOLD_ADD_HELD_CALL, + HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS } hfp_ag_call_event_t; diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index af9840eda..a5107ef71 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -83,6 +83,10 @@ static hfp_callsetup_status_t callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SE void hfp_gsm_init(void){ memset(gsm_calls, 0, sizeof(gsm_calls)); + int i; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + gsm_calls[i].status = CALL_NONE; + } callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; } @@ -134,10 +138,6 @@ static inline int get_number_held_calls(){ return get_number_calls_with_status(CALL_HELD); } -static inline int get_number_initiated_calls(){ - return get_number_calls_with_status(CALL_INITIATED); -} - static inline int get_number_response_held_calls(){ return get_number_calls_with_status(CALL_RESPONSE_HOLD); } @@ -177,7 +177,7 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ int current_call_index = get_active_call_index(); int initiated_call_index = get_initiated_call_index(); int held_call_index = get_held_call_index(); - + printf("hfp_gsm_handle_event %d \n", event); switch (event){ case HFP_AG_OUTGOING_CALL_INITIATED: case HFP_AG_OUTGOING_REDIAL_INITIATED: @@ -215,25 +215,19 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ break; case HFP_AG_INCOMING_CALL: - printf("HFP_AG_INCOMING_CALL \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS) break; - printf("HFP_AG_INCOMING_CALL 1: HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS -> HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS, CALL_INITIATED %d\n", next_free_slot); callsetup_status = HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS; gsm_calls[next_free_slot].status = CALL_INITIATED; gsm_calls[next_free_slot].clip_type = 0; break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG: - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; if (hfp_gsm_call_status() == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){ - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG 1: HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT, CALL_HELD %d\n", current_call_index); gsm_calls[current_call_index].status = CALL_HELD; } - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_AG 2: HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT, CALL_ACTIVE %d\n", initiated_call_index); - gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; @@ -255,11 +249,8 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ break; case HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF: - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF \n"); if (hfp_gsm_callsetup_status() != HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS) break; - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF 1: HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS\n"); if (hfp_gsm_call_status() != HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS) break; - printf("HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF 2\n"); callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; gsm_calls[initiated_call_index].status = CALL_ACTIVE; break; @@ -323,7 +314,15 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ } } break; - + case HFP_AG_CALL_HOLD_USER_BUSY: + break; + case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: + break; + case HFP_AG_CALL_HOLD_ADD_HELD_CALL: + break; + case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS: + break; + default: break; } From 359d6a17fda2460ad609fa9a1853badde872cb20 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 14 Jan 2016 17:08:54 +0100 Subject: [PATCH 30/31] hfp: removed hfp_ag_call_state --- src/hfp_ag.c | 38 ++++++++++-------------- src/hfp_gsm_model.c | 71 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 28 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index cf9b89c78..eaae04444 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -76,8 +76,6 @@ static int hfp_ag_call_hold_services_nr = 0; static char *hfp_ag_call_hold_services[6]; static hfp_callback_t hfp_callback; - -static hfp_call_status_t hfp_ag_call_state; static hfp_callsetup_status_t hfp_ag_callsetup_state; static hfp_callheld_status_t hfp_ag_callheld_state; static hfp_response_and_hold_state_t hfp_ag_response_and_hold_state; @@ -97,7 +95,6 @@ static void hfp_ag_setup_audio_connection(hfp_connection_t * connection); static void hfp_ag_hf_start_ringing(hfp_connection_t * context); static hfp_call_status_t get_hfp_ag_call_state(void){ - // return hfp_ag_call_state; return hfp_gsm_call_status(); } @@ -1059,14 +1056,6 @@ static void hfp_ag_set_callheld_state(hfp_callheld_status_t state){ indicator->status = state; } -static void hfp_ag_set_call_state(hfp_call_status_t state){ - hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); - if (!indicator){ - log_error("hfp_ag_set_call_state: call indicator is missing"); - }; - indicator->status = state; -} - static void hfp_ag_set_callheld_indicator(){ hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callheld"); if (!indicator){ @@ -1546,30 +1535,35 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect connection->call_state = HFP_CALL_ACTIVE; printf("AG: Call Waiting, User Busy\n"); break; - case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: + + case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ + int call_setup_in_progress = get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + int call_held = get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD; + // Releases all active calls (if any exist) and accepts the other (held or waiting) call. - if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + if (call_setup_in_progress){ printf("AG: Call Dropped, Accept new call\n"); - hfp_gsm_handle_event(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); } else { printf("AG: Call Dropped, Resume held call\n"); } - if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ - hfp_gsm_handle_event(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + if (call_held){ hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); } + if (call_held || call_setup_in_progress){ + hfp_gsm_handle_event(HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); + } connection->call_state = HFP_CALL_ACTIVE; break; - case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: - + } + case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ + int call_setup_in_progress = get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; // Places all active calls (if any exist) on hold and accepts the other (held or waiting) call. // only update if callsetup changed - if (get_hfp_ag_callsetup_state() != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + if (call_setup_in_progress){ printf("AG: Call on Hold, Accept new call\n"); - hfp_gsm_handle_event(HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL); hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1); } else { @@ -1580,6 +1574,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); connection->call_state = HFP_CALL_ACTIVE; break; + } case HFP_AG_CALL_HOLD_ADD_HELD_CALL: // Adds a held call to the conversation. if (get_hfp_ag_callheld_state() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ @@ -1595,7 +1590,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect // Connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer) hfp_gsm_handle_event(HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS); printf("AG: Transfer call -> Connect two calls and disconnect\n"); - hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS); + hfp_ag_set_call_indicator(); hfp_ag_set_callheld_state(HFP_CALLHELD_STATUS_NO_CALLS_HELD); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1); connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callheld_indicator_index, 1); @@ -1995,7 +1990,6 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features, hfp_ag_call_hold_services_nr = call_hold_services_nr; memcpy(hfp_ag_call_hold_services, call_hold_services, call_hold_services_nr * sizeof(char *)); - hfp_ag_call_state = HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS; hfp_ag_callsetup_state = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; hfp_ag_callheld_state = HFP_CALLHELD_STATUS_NO_CALLS_HELD; diff --git a/src/hfp_gsm_model.c b/src/hfp_gsm_model.c index a5107ef71..5a49f3f0b 100644 --- a/src/hfp_gsm_model.c +++ b/src/hfp_gsm_model.c @@ -315,14 +315,73 @@ void hfp_gsm_handle_event(hfp_ag_call_event_t event){ } break; case HFP_AG_CALL_HOLD_USER_BUSY: + // Held or waiting call gets active, + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + gsm_calls[initiated_call_index].status = CALL_NONE; + gsm_calls[held_call_index].status = CALL_ACTIVE; break; - case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL: - break; - case HFP_AG_CALL_HOLD_ADD_HELD_CALL: - break; - case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS: - break; + + case HFP_AG_CALL_HOLD_RELEASE_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ + int i ; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + if (gsm_calls[i].status == CALL_ACTIVE){ + gsm_calls[i].clip_type = 0; + gsm_calls[i].clip_number[0] = '\0'; + gsm_calls[i].status = CALL_NONE; + } + } + if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + } else { + gsm_calls[held_call_index].status = CALL_ACTIVE; + } + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + } + case HFP_AG_CALL_HOLD_PARK_ACTIVE_ACCEPT_HELD_OR_WAITING_CALL:{ + int i ; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + if (gsm_calls[i].status == CALL_ACTIVE){ + gsm_calls[i].clip_type = 0; + gsm_calls[i].clip_number[0] = '\0'; + gsm_calls[i].status = CALL_HELD; + } + } + + if (callsetup_status != HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS){ + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + } else { + gsm_calls[held_call_index].status = CALL_ACTIVE; + } + callsetup_status = HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS; + break; + } + case HFP_AG_CALL_HOLD_ADD_HELD_CALL:{ + if (hfp_gsm_callheld_status() != HFP_CALLHELD_STATUS_NO_CALLS_HELD){ + int i ; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + if (gsm_calls[i].status == CALL_HELD){ + gsm_calls[i].clip_type = 0; + gsm_calls[i].clip_number[0] = '\0'; + gsm_calls[i].status = CALL_ACTIVE; + } + } + } + gsm_calls[initiated_call_index].status = CALL_ACTIVE; + + break; + } + case HFP_AG_CALL_HOLD_EXIT_AND_JOIN_CALLS:{ + int i ; + for (i = 0; i < HFP_GSM_MAX_NR_CALLS; i++){ + gsm_calls[i].clip_type = 0; + gsm_calls[i].clip_number[0] = '\0'; + gsm_calls[i].status = CALL_NONE; + } + + break; + } default: break; } From 13ced00deabcec40aaac3d9e073eebaa50e66773 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 14 Jan 2016 17:21:51 +0100 Subject: [PATCH 31/31] cc256x: route SCO over HCI if HAVE_SCO_OVER_HCI --- chipset-cc256x/bt_control_cc256x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/chipset-cc256x/bt_control_cc256x.c b/chipset-cc256x/bt_control_cc256x.c index 0bb0e7b75..1b81fc095 100644 --- a/chipset-cc256x/bt_control_cc256x.c +++ b/chipset-cc256x/bt_control_cc256x.c @@ -86,12 +86,21 @@ static uint32_t init_script_offset = 0; static int16_t init_power_in_dB = 13; // 13 dBm static int init_ehcill_enabled = 0; +static int init_send_route_sco_over_hci = 0; static int bt_control_cc256x_on(void *config){ init_script_offset = 0; +#ifdef HAVE_SCO_OVER_HCI + init_send_route_sco_over_hci = 1; +#endif return 0; } +// route SCO over HCI (connection type=1, tx buffer size = 0x00 (don't change), tx buffer max latency=0x0000(don't chnage)), accept packets - 0) +static const uint8_t hci_route_sco_over_hci[] = { + 0x10, 0xfe, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00 +}; + // UART Baud Rate control from: http://e2e.ti.com/support/low_power_rf/f/660/p/134850/484763.aspx static int cc256x_baudrate_cmd(void * config, uint32_t baudrate, uint8_t *hci_cmd_buffer){ hci_cmd_buffer[0] = 0x36; @@ -213,6 +222,12 @@ static int bt_control_cc256x_update_command(uint8_t *hci_cmd_buffer){ static int bt_control_cc256x_next_cmd(void *config, uint8_t *hci_cmd_buffer){ if (init_script_offset >= cc256x_init_script_size) { + // append send route SCO over HCI if requested + if (init_send_route_sco_over_hci){ + init_send_route_sco_over_hci = 0; + memcpy(hci_cmd_buffer, hci_route_sco_over_hci, sizeof(hci_route_sco_over_hci)); + return 1; + } return 0; }