From 0e7846ca8016f3ebf106dc7b24e0055876b9e33b Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 26 Mar 2016 23:00:17 +0100 Subject: [PATCH 01/29] cc256x: avoid sending random HCI at end of init script --- chipset-cc256x/convert_bts_init_scripts.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chipset-cc256x/convert_bts_init_scripts.py b/chipset-cc256x/convert_bts_init_scripts.py index d15db25f5..71a9b3c12 100755 --- a/chipset-cc256x/convert_bts_init_scripts.py +++ b/chipset-cc256x/convert_bts_init_scripts.py @@ -14,7 +14,7 @@ CC256x init script conversion tool for use with BTstack, v0.1 Copyright 2012-2014 BlueKitchen GmbH ''') -usage = '''This script perpares init scripts for TI's +usage = '''This script prepares init scripts for TI's CC256x chipsets for use with BTstack . Please download the Service Pack for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads @@ -47,7 +47,7 @@ def append_power_vector_gfsk(additions, str_list, data_indent): str_list.append("0x01, 0x82, 0xfd, 0x14, 0x00, 0x9c, 0x18, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xdc,\n"); str_list.append(data_indent) str_list.append("0xe6, 0xf0, 0xfa, 0x04, 0x0e, 0x18, 0xff, 0x00, 0x00,\n\n"); - return 25 + return 24 def append_power_vector_edr2(additions, str_list, data_indent): additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR2) template") @@ -57,7 +57,7 @@ def append_power_vector_edr2(additions, str_list, data_indent): str_list.append("0x01, 0x82, 0xfd, 0x14, 0x01, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8, \n"); str_list.append(data_indent) str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n"); - return 25 + return 24 def append_power_vector_edr3(additions, str_list, data_indent): additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR3) template") @@ -67,7 +67,7 @@ def append_power_vector_edr3(additions, str_list, data_indent): str_list.append("0x01, 0x82, 0xfd, 0x14, 0x02, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8,\n"); str_list.append(data_indent) str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n"); - return 25 + return 24 def append_class2_single_power(additions, str_list, data_indent): additions.append("- added HCI_VS_SET_CLASS2_SINGLE_POWER template") From 9d46808c46e78159a22ab85bf233d3bd0435fc24 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 27 Mar 2016 22:34:29 +0200 Subject: [PATCH 02/29] gap: pass le_connection_parameter_range_t as pointer --- ble/l2cap_le.c | 2 +- src/hci.c | 8 ++++---- src/hci.h | 4 ++-- src/l2cap.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ble/l2cap_le.c b/ble/l2cap_le.c index e04c01e06..0c4749811 100644 --- a/ble/l2cap_le.c +++ b/ble/l2cap_le.c @@ -310,7 +310,7 @@ void l2cap_acl_handler( uint8_t *packet, uint16_t size ){ if (connection){ int update_parameter = 1; le_connection_parameter_range_t existing_range; - gap_le_get_connection_parameter_range(existing_range); + gap_le_get_connection_parameter_range(&existing_range); uint16_t le_conn_interval_min = READ_BT_16(packet,12); uint16_t le_conn_interval_max = READ_BT_16(packet,14); uint16_t le_conn_latency = READ_BT_16(packet,16); diff --git a/src/hci.c b/src/hci.c index 181b01109..c609b9f3b 100644 --- a/src/hci.c +++ b/src/hci.c @@ -135,8 +135,8 @@ static hci_connection_t * create_connection_for_bd_addr_and_type(bd_addr_t addr, * * @return le connection parameter range struct */ -void gap_le_get_connection_parameter_range(le_connection_parameter_range_t range){ - range = hci_stack->le_connection_parameter_range; +void gap_le_get_connection_parameter_range(le_connection_parameter_range_t * range){ + *range = hci_stack->le_connection_parameter_range; } /** @@ -144,8 +144,8 @@ void gap_le_get_connection_parameter_range(le_connection_parameter_range_t range * */ -void gap_le_set_connection_parameter_range(le_connection_parameter_range_t range){ - hci_stack->le_connection_parameter_range = range; +void gap_le_set_connection_parameter_range(le_connection_parameter_range_t * range){ + hci_stack->le_connection_parameter_range = *range; } /** diff --git a/src/hci.h b/src/hci.h index 48b3cab05..9cf1cab60 100644 --- a/src/hci.h +++ b/src/hci.h @@ -859,8 +859,8 @@ int hci_remote_eSCO_supported(hci_con_handle_t con_handle); /* API_START */ -void gap_le_get_connection_parameter_range(le_connection_parameter_range_t range); -void gap_le_set_connection_parameter_range(le_connection_parameter_range_t range); +void gap_le_get_connection_parameter_range(le_connection_parameter_range_t * range); +void gap_le_set_connection_parameter_range(le_connection_parameter_range_t * range); /* LE Client Start */ diff --git a/src/l2cap.c b/src/l2cap.c index 574d01221..f3bae4c1c 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -1421,7 +1421,7 @@ static void l2cap_acl_handler( uint8_t *packet, uint16_t size ){ } int update_parameter = 1; le_connection_parameter_range_t existing_range; - gap_le_get_connection_parameter_range(existing_range); + gap_le_get_connection_parameter_range(&existing_range); uint16_t le_conn_interval_min = READ_BT_16(packet,12); uint16_t le_conn_interval_max = READ_BT_16(packet,14); uint16_t le_conn_latency = READ_BT_16(packet,16); From 6a3b8c39b0fd975bcaaa9269379498bfa4f6b7d3 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 28 Mar 2016 12:19:40 +0200 Subject: [PATCH 03/29] hfp_hf: remove unused var, fix compile --- src/hfp_hf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hfp_hf.c b/src/hfp_hf.c index 905bec25d..2870e0cab 100644 --- a/src/hfp_hf.c +++ b/src/hfp_hf.c @@ -850,7 +850,6 @@ static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){ hfp_connection->ok_pending = 0; - int done = 1; switch (hfp_connection->state){ case HFP_W4_EXCHANGE_SUPPORTED_FEATURES: if (has_codec_negotiation_feature(hfp_connection)){ @@ -943,12 +942,10 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){ hfp_emit_event(hfp_callback, HFP_SUBEVENT_CODECS_CONNECTION_COMPLETE, 0); break; default: - done = 0; break; } break; default: - done = 0; break; } @@ -1055,7 +1052,7 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8 hfp_run_for_context(hfp_connection); } -static void hfp_run(){ +static void hfp_run(void){ linked_list_iterator_t it; linked_list_iterator_init(&it, hfp_get_connections()); while (linked_list_iterator_has_next(&it)){ From 40fcb3ee0ad6c3df82458fbd86360513f29a30d6 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 28 Mar 2016 12:22:05 +0200 Subject: [PATCH 04/29] fix fn() prototypes --- ble/sm_minimal.c | 2 +- example/embedded/hfp_ag_demo.c | 2 +- example/embedded/hfp_hf_demo.c | 2 +- platforms/posix/src/hci_transport_h2_libusb.c | 2 +- platforms/posix/src/hci_transport_h4.c | 2 +- platforms/posix/src/hci_transport_h5.c | 2 +- src/hci.c | 2 +- src/hfp.c | 2 +- src/hfp_ag.c | 8 +-- test/gatt_client/gatt_client_test.c | 4 +- test/gatt_client/le_central.c | 6 +-- test/gatt_client/mock.c | 2 +- test/hfp/hfp_ag_client_test.c | 4 +- test/hfp/hfp_hf_client_test.c | 4 +- test/hfp/mock.c | 8 +-- test/hfp/test_sequences.c | 54 +++++++++---------- test/pts/ble_central_test.c | 2 +- test/pts/ble_peripheral_test.c | 6 +-- test/pts/bnep_test.c | 2 +- test/pts/classic_test.c | 2 +- test/pts/hfp_ag_test.c | 2 +- test/pts/hfp_hf_test.c | 2 +- test/pts/hsp_hs_test.c | 2 +- test/pts/l2cap_test.c | 2 +- .../remote_device_db_fs_test.c | 2 +- test/sdp_client/sdp_rfcomm_query.c | 2 +- 26 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ble/sm_minimal.c b/ble/sm_minimal.c index 499d8ee12..a8c7f81dd 100644 --- a/ble/sm_minimal.c +++ b/ble/sm_minimal.c @@ -49,7 +49,7 @@ // SM internal types and globals // -static void sm_run(); +static void sm_run(void); // used to notify applicationss that user interaction is neccessary, see sm_notify_t below static btstack_packet_handler_t sm_client_packet_handler = NULL; diff --git a/example/embedded/hfp_ag_demo.c b/example/embedded/hfp_ag_demo.c index 842e08ad8..d5788d74f 100644 --- a/example/embedded/hfp_ag_demo.c +++ b/example/embedded/hfp_ag_demo.c @@ -108,7 +108,7 @@ static hfp_generic_status_indicator_t hf_indicators[] = { char cmd; // prototypes -static void show_usage(); +static void show_usage(void); // GAP INQUIRY diff --git a/example/embedded/hfp_hf_demo.c b/example/embedded/hfp_hf_demo.c index 838a7b4e2..cdf8e008d 100644 --- a/example/embedded/hfp_hf_demo.c +++ b/example/embedded/hfp_hf_demo.c @@ -89,7 +89,7 @@ static uint16_t indicators[1] = {0x01}; char cmd; // prototypes -static void show_usage(); +static void show_usage(void); // Testig User Interface static void show_usage(void){ diff --git a/platforms/posix/src/hci_transport_h2_libusb.c b/platforms/posix/src/hci_transport_h2_libusb.c index bf3c079af..d97c25b15 100644 --- a/platforms/posix/src/hci_transport_h2_libusb.c +++ b/platforms/posix/src/hci_transport_h2_libusb.c @@ -1025,7 +1025,7 @@ static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ } // get usb singleton -hci_transport_t * hci_transport_usb_instance() { +hci_transport_t * hci_transport_usb_instance(void) { if (!hci_transport_usb) { hci_transport_usb = (hci_transport_t*) malloc( sizeof(hci_transport_t)); hci_transport_usb->open = usb_open; diff --git a/platforms/posix/src/hci_transport_h4.c b/platforms/posix/src/hci_transport_h4.c index 18b7a529c..55b0e1a11 100644 --- a/platforms/posix/src/hci_transport_h4.c +++ b/platforms/posix/src/hci_transport_h4.c @@ -332,7 +332,7 @@ static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ } // get h4 singleton -hci_transport_t * hci_transport_h4_instance() { +hci_transport_t * hci_transport_h4_instance(void) { if (hci_transport_h4 == NULL) { hci_transport_h4 = (hci_transport_h4_t*)malloc( sizeof(hci_transport_h4_t)); hci_transport_h4->ds = NULL; diff --git a/platforms/posix/src/hci_transport_h5.c b/platforms/posix/src/hci_transport_h5.c index 983555a65..597a985e9 100644 --- a/platforms/posix/src/hci_transport_h5.c +++ b/platforms/posix/src/hci_transport_h5.c @@ -297,7 +297,7 @@ static void dummy_handler(uint8_t *packet, int size){ } // get h5 singleton -hci_transport_t * hci_transport_h5_instance() { +hci_transport_t * hci_transport_h5_instance(void) { if (hci_transport_h5 == NULL) { hci_transport_h5 = malloc( sizeof(hci_transport_h5_t)); hci_transport_h5->ds = NULL; diff --git a/src/hci.c b/src/hci.c index c609b9f3b..d4cccec33 100644 --- a/src/hci.c +++ b/src/hci.c @@ -3461,7 +3461,7 @@ void hci_set_sco_voice_setting(uint16_t voice_setting){ * @brief Get SCO Voice Setting * @return current voice setting */ -uint16_t hci_get_sco_voice_setting(){ +uint16_t hci_get_sco_voice_setting(void){ return hci_stack->sco_voice_setting; } diff --git a/src/hfp.c b/src/hfp.c index 04ae5716b..b39e01fc5 100644 --- a/src/hfp.c +++ b/src/hfp.c @@ -218,7 +218,7 @@ static void hfp_emit_audio_connection_established_event(hfp_callback_t callback, (*callback)(event, sizeof(event)); } -linked_list_t * hfp_get_connections(){ +linked_list_t * hfp_get_connections(void){ return (linked_list_t *) &hfp_connections; } diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 0b96bac43..81f87a1fd 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -139,7 +139,7 @@ void hfp_ag_register_packet_handler(hfp_callback_t callback){ hfp_callback = callback; } -static int use_in_band_tone(){ +static int use_in_band_tone(void){ return get_bit(hfp_supported_features, HFP_AGSF_IN_BAND_RING_TONE); } @@ -1005,7 +1005,7 @@ static void hfp_ag_trigger_terminate_call(void){ hfp_emit_simple_event(hfp_callback, HFP_SUBEVENT_CALL_TERMINATED); } -static void hfp_ag_set_callsetup_indicator(){ +static void hfp_ag_set_callsetup_indicator(void){ hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callsetup"); if (!indicator){ log_error("hfp_ag_set_callsetup_indicator: callsetup indicator is missing"); @@ -1013,7 +1013,7 @@ static void hfp_ag_set_callsetup_indicator(){ indicator->status = hfp_gsm_callsetup_status(); } -static void hfp_ag_set_callheld_indicator(){ +static void hfp_ag_set_callheld_indicator(void){ hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("callheld"); if (!indicator){ log_error("hfp_ag_set_callheld_state: callheld indicator is missing"); @@ -1021,7 +1021,7 @@ static void hfp_ag_set_callheld_indicator(){ indicator->status = hfp_gsm_callheld_status(); } -static void hfp_ag_set_call_indicator(){ +static void hfp_ag_set_call_indicator(void){ hfp_ag_indicator_t * indicator = get_ag_indicator_for_name("call"); if (!indicator){ log_error("hfp_ag_set_call_state: call indicator is missing"); diff --git a/test/gatt_client/gatt_client_test.c b/test/gatt_client/gatt_client_test.c index b369731dc..d5ecaebef 100644 --- a/test/gatt_client/gatt_client_test.c +++ b/test/gatt_client/gatt_client_test.c @@ -72,8 +72,8 @@ static le_service_t included_services[50]; static le_characteristic_t characteristics[50]; static le_characteristic_descriptor_t descriptors[50]; -void mock_simulate_discover_primary_services_response(); -void mock_simulate_att_exchange_mtu_response(); +void mock_simulate_discover_primary_services_response(void); +void mock_simulate_att_exchange_mtu_response(void); void CHECK_EQUAL_ARRAY(const uint8_t * expected, uint8_t * actual, int size){ for (int i=0; i Date: Mon, 28 Mar 2016 15:19:31 +0200 Subject: [PATCH 05/29] att_server: directly process ATT Write Commands --- ble/att_server.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ble/att_server.c b/ble/att_server.c index 968fe436d..7b0f87347 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -340,11 +340,24 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa return; } + // directly process commands + // note: signed write cannot be handled directly as authentication needs to be verified + if (packet[0] == ATT_WRITE_COMMAND){ + att_handle_request(&att_connection, packet, size, 0); + return; + } + // check size - if (size > sizeof(att_request_buffer)) return; + if (size > sizeof(att_request_buffer)) { + log_info("att_packet_handler: dropping att pdu 0x%02x as size %u > att_request_buffer %u", packet[0], size, (int) sizeof(att_request_buffer)); + return; + } // last request still in processing? - if (att_server_state != ATT_SERVER_IDLE) return; + if (att_server_state != ATT_SERVER_IDLE){ + log_info("att_packet_handler: skipping att pdu 0x%02x as server not idle (state %u)", packet[0], att_server_state); + return; + } // store request att_server_state = ATT_SERVER_REQUEST_RECEIVED; From 1532fd1ef9f98cdc072ff7dd7b988a0794d86789 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 30 Mar 2016 10:21:23 +0200 Subject: [PATCH 06/29] hfp_ag: fix sending outgoing cmds in chunks --- src/hfp_ag.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hfp_ag.c b/src/hfp_ag.c index 81f87a1fd..112966dd5 100644 --- a/src/hfp_ag.c +++ b/src/hfp_ag.c @@ -370,6 +370,7 @@ static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * hfp_connect // assumes: can send now == true // assumes: num segments > 0 + // assumes: individual segments are smaller than MTU rfcomm_reserve_packet_buffer(); int mtu = rfcomm_get_max_frame_size(cid); uint8_t * data = rfcomm_get_outgoing_buffer(); @@ -377,11 +378,11 @@ static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * hfp_connect int segment = start_segment; while (segment < num_segments){ int segment_len = get_segment_len(hfp_connection, segment); - if (offset + segment_len <= mtu){ - store_segment(hfp_connection, segment, data+offset); - offset += segment_len; - segment++; - } + if (offset + segment_len > mtu) break; + // append segement + store_segment(hfp_connection, segment, data+offset); + offset += segment_len; + segment++; } rfcomm_send_prepared(cid, offset); return segment; From 962127fa8633084d38bf92322dd6cb9a7776004a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 11 Apr 2016 11:19:41 +0200 Subject: [PATCH 07/29] link to v0.9 builders + docs --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 205f6c293..0b5b72e74 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ It has been qualified with the the Bluetooth SIG for GAP, IOP, HFP, HSP, SPP, PA GATT, SM of the Bluetooth 4.2 LE Central and Peripheral roles (QD ID 25340). ## Documentation -- [HTML](http://bluekitchen-gmbh.com/btstack/) -- [PDF](http://bluekitchen-gmbh.com/btstack.pdf) +- [HTML](http://bluekitchen-gmbh.com/btstack/v0.9) +- [PDF](http://bluekitchen-gmbh.com/btstack_v0.9.pdf) ## Supported Protocols * L2CAP @@ -52,22 +52,22 @@ Coming next: HID, HOGP, A2DP, and more. #### Embedded Platforms: Status | Platform -------------- | ------ -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-ez430-rf2560-master) | [EZ430-RF256x Bluetooth Evaluation Tool for MSP430](http://www.ti.com/tool/ez430-rf256x) -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-msp-exp430f5438-cc2564b-master) | [MSP430F5438 Experimenter Board for MSP430](http://www.ti.com/tool/msp-exp430f5438) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-msp430f5229lp-cc2564b-master) | [MSP-EXP430F5529LP LaunchPad](http://www.ti.com/ww/en/launchpad/launchpads-msp430-msp-exp430f5529lp.html#tabs) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-stm32-f103rb-nucleo-master) | [STM32 Nucleo development board NUCLEO-F103RB](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-pic32-harmony-master) | [Microchip's PIC32 Bluetooth Audio Development Kit](http://www.microchip.com/Developmenttools/ProductDetails.aspx?PartNO=DV320032) +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-ez430-rf2560-v0.9) | [EZ430-RF256x Bluetooth Evaluation Tool for MSP430](http://www.ti.com/tool/ez430-rf256x) +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-msp-exp430f5438-cc2564b-v0.9) | [MSP430F5438 Experimenter Board for MSP430](http://www.ti.com/tool/msp-exp430f5438) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-msp430f5229lp-cc2564b-v0.9) | [MSP-EXP430F5529LP LaunchPad](http://www.ti.com/ww/en/launchpad/launchpads-msp430-msp-exp430f5529lp.html#tabs) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-stm32-f103rb-nucleo-v0.9) | [STM32 Nucleo development board NUCLEO-F103RB](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF259875) with [Bluetooth CC2564 Module Evaluation Board](http://www.ti.com/tool/cc2564modnem) and [EM Adapter BoosterPack](http://www.ti.com/tool/boost-ccemadapter) with additional 32768Hz quartz oscillator +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-pic32-harmony-v0.9) | [Microchip's PIC32 Bluetooth Audio Development Kit](http://www.microchip.com/Developmenttools/ProductDetails.aspx?PartNO=DV320032) #### Other Platforms: Status | Platform -------------- | ------ -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-posix-stlc2500d-master)| posix: Unix-based system talking to Bluetooth module via serial port -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-libusb-master)| libusb: Unix-based system talking via USB Bluetooth dongle -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-daemon-master)| daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=java-master)| java: Java wrapper for daemon -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-ios-master)| iOS: daemon for iOS jailbreak devices, C client-server API -![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-mtk-master)| mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-posix-stlc2500d-v0.9)| posix: Unix-based system talking to Bluetooth module via serial port +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-libusb-v0.9)| libusb: Unix-fbased system talking via USB Bluetooth dongle +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-daemon-v0.9)| daemon: TCP and Unix domain named socket client-server architecture supporting multiple clients +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=java-v0.9)| java: Java wrapper for daemon +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-ios-v0.9)| iOS: daemon for iOS jailbreak devices, C client-server API +![buildstatus](http://buildbot.bluekitchen-gmbh.com/btstack/badge.png?builder=platform-mtk-v0.9)| mtk: daemon for rooted Android devices, based on Mediatek MT65xx processor, Java and C client-server API ## Supported Chipsets From 9cd88577a133787b5cd6253052b0c38714d300a5 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 11 Apr 2016 22:26:41 +0200 Subject: [PATCH 08/29] add link to migration notes --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c1be1c67..23657fee1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -**_Note: Major API Changes. For older projects, you may use the [v0.9 branch](https://github.com/bluekitchen/btstack/tree/v0.9)_** +**_Note: Major API Changes. For older projects, you may use the [v0.9 branch](https://github.com/bluekitchen/btstack/tree/v0.9). +Please see [Migration notes]([Migration notes]) _** # Welcome to BTstack From db00faf25be88e84360484b9ba5af4c578223359 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 18 Apr 2016 14:49:05 +0200 Subject: [PATCH 09/29] fix warnings --- platform/embedded/hci_transport_h4_embedded.c | 4 ++-- src/classic/hsp_ag.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/embedded/hci_transport_h4_embedded.c b/platform/embedded/hci_transport_h4_embedded.c index 103ac0c58..24f6750b6 100644 --- a/platform/embedded/hci_transport_h4_embedded.c +++ b/platform/embedded/hci_transport_h4_embedded.c @@ -254,13 +254,13 @@ static void h4_process(btstack_data_source_t *ds, btstack_data_source_callback_t packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); } - if (h4_state != H4_PACKET_RECEIVED) return 0; + if (h4_state != H4_PACKET_RECEIVED) return; packet_handler(hci_packet[0], &hci_packet[1], read_pos-1); h4_init_sm(); - return 0; + return; } static int h4_send_packet(uint8_t packet_type, uint8_t *packet, int size){ diff --git a/src/classic/hsp_ag.c b/src/classic/hsp_ag.c index 357c04299..3e953d452 100644 --- a/src/classic/hsp_ag.c +++ b/src/classic/hsp_ag.c @@ -227,7 +227,7 @@ void hsp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, } } -static int hsp_ag_send_str_over_rfcomm(uint16_t cid, char * command){ +static int hsp_ag_send_str_over_rfcomm(const uint16_t cid, char * command){ int err = rfcomm_send(cid, (uint8_t*) command, strlen(command)); if (err){ log_error("rfcomm_send_internal -> error 0X%02x", err); From 6a7f493ac537c641f693aed1969287d0f0d58269 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 18 Apr 2016 16:15:39 +0200 Subject: [PATCH 10/29] example/hsp: fix docu to refer to ENABLE_SCO_OVER_HCI --- example/hsp_ag_demo.c | 2 +- example/hsp_hs_demo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/hsp_ag_demo.c b/example/hsp_ag_demo.c index 2cc055903..79df9d4b1 100644 --- a/example/hsp_ag_demo.c +++ b/example/hsp_ag_demo.c @@ -88,7 +88,7 @@ static const uint8_t sine[] = { /* @section Audio Transfer Setup * * @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz. - * To send and receive an audio signal, HAVE_SCO_OVER_HCI has to be defined. + * To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined. * * Tested working setups: * - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud diff --git a/example/hsp_hs_demo.c b/example/hsp_hs_demo.c index b1dfa0a39..f1240b943 100644 --- a/example/hsp_hs_demo.c +++ b/example/hsp_hs_demo.c @@ -89,7 +89,7 @@ static const uint8_t sine[] = { /* @section Audio Transfer Setup * * @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz. - * To send and receive an audio signal, HAVE_SCO_OVER_HCI has to be defined. + * To send and receive an audio signal, ENABLE_SCO_OVER_HCI has to be defined. * * Tested working setups: * - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud From a3f81b3616fc4809498d6370de8837262c53ee13 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 20 Apr 2016 16:51:36 +0200 Subject: [PATCH 11/29] sm: use uint8_t[7] instead of struct for sm_pairing_packet_t to avoid to depend on packed structs --- src/ble/sm.c | 43 +++++++++++++++++++++++-------------------- src/ble/sm.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/hci.h | 10 +--------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/ble/sm.c b/src/ble/sm.c index 10341ef70..8ed3b74c6 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -531,7 +531,8 @@ static void sm_setup_tk(void){ // If both devices have out of band authentication data, then the Authentication // Requirements Flags shall be ignored when selecting the pairing method and the // Out of Band pairing method shall be used. - if (setup->sm_m_preq.oob_data_flag && setup->sm_s_pres.oob_data_flag){ + if (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) + && sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres)){ log_info("SM: have OOB data"); log_info_key("OOB", setup->sm_tk); setup->sm_stk_generation_method = OOB; @@ -544,20 +545,21 @@ static void sm_setup_tk(void){ // If both devices have not set the MITM option in the Authentication Requirements // Flags, then the IO capabilities shall be ignored and the Just Works association // model shall be used. - if ( ((setup->sm_m_preq.auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0x00) && ((setup->sm_s_pres.auth_req & SM_AUTHREQ_MITM_PROTECTION) == 0)){ + if (((sm_pairing_packet_get_auth_req(setup->sm_m_preq) & SM_AUTHREQ_MITM_PROTECTION) == 0) + && ((sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_MITM_PROTECTION) == 0)){ return; } // Also use just works if unknown io capabilites - if ((setup->sm_m_preq.io_capability > IO_CAPABILITY_KEYBOARD_DISPLAY) || (setup->sm_m_preq.io_capability > IO_CAPABILITY_KEYBOARD_DISPLAY)){ + if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY)){ return; } // Otherwise the IO capabilities of the devices shall be used to determine the // pairing method as defined in Table 2.4. - setup->sm_stk_generation_method = stk_generation_method[setup->sm_s_pres.io_capability][setup->sm_m_preq.io_capability]; + setup->sm_stk_generation_method = stk_generation_method[sm_pairing_packet_get_io_capability(setup->sm_s_pres)][sm_pairing_packet_get_io_capability(setup->sm_m_preq)]; log_info("sm_setup_tk: master io cap: %u, slave io cap: %u -> method %u", - setup->sm_m_preq.io_capability, setup->sm_s_pres.io_capability, setup->sm_stk_generation_method); + sm_pairing_packet_get_io_capability(setup->sm_m_preq), sm_pairing_packet_get_io_capability(setup->sm_s_pres), setup->sm_stk_generation_method); } static int sm_key_distribution_flags_for_set(uint8_t key_set){ @@ -834,10 +836,10 @@ static int sm_key_distribution_all_received(sm_connection_t * sm_conn){ int recv_flags; if (sm_conn->sm_role){ // slave / responser - recv_flags = sm_key_distribution_flags_for_set(setup->sm_s_pres.initiator_key_distribution); + recv_flags = sm_key_distribution_flags_for_set(sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres)); } else { // master / initiator - recv_flags = sm_key_distribution_flags_for_set(setup->sm_s_pres.responder_key_distribution); + recv_flags = sm_key_distribution_flags_for_set(sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres)); } log_debug("sm_key_distribution_all_received: received 0x%02x, expecting 0x%02x", setup->sm_key_distribution_received_set, recv_flags); return recv_flags == setup->sm_key_distribution_received_set; @@ -888,14 +890,14 @@ static void sm_init_setup(sm_connection_t * sm_conn){ memcpy(setup->sm_s_address, sm_conn->sm_peer_address, 6); int key_distribution_flags = sm_key_distribution_flags_for_auth_req(); - setup->sm_m_preq.initiator_key_distribution = key_distribution_flags; - setup->sm_m_preq.responder_key_distribution = key_distribution_flags; + sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags); + sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags); } - local_packet->io_capability = sm_io_capabilities; - local_packet->oob_data_flag = have_oob_data; - local_packet->auth_req = sm_auth_req; - local_packet->max_encryption_key_size = sm_max_encryption_key_size; + sm_pairing_packet_set_io_capability(*local_packet, sm_io_capabilities); + sm_pairing_packet_set_oob_data_flag(*local_packet, have_oob_data); + sm_pairing_packet_set_auth_req(*local_packet, sm_auth_req); + sm_pairing_packet_set_max_encryption_key_size(*local_packet, sm_max_encryption_key_size); } static int sm_stk_generation_init(sm_connection_t * sm_conn){ @@ -905,15 +907,15 @@ static int sm_stk_generation_init(sm_connection_t * sm_conn){ if (sm_conn->sm_role){ // slave / responser remote_packet = &setup->sm_m_preq; - remote_key_request = setup->sm_m_preq.responder_key_distribution; + remote_key_request = sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq); } else { // master / initiator remote_packet = &setup->sm_s_pres; - remote_key_request = setup->sm_s_pres.initiator_key_distribution; + remote_key_request = sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres); } // check key size - sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(remote_packet->max_encryption_key_size); + sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(*remote_packet)); if (sm_conn->sm_actual_encryption_key_size == 0) return SM_REASON_ENCRYPTION_KEY_SIZE; // setup key distribution @@ -1343,7 +1345,7 @@ static void sm_run(void){ } case SM_INITIATOR_PH1_SEND_PAIRING_REQUEST: - setup->sm_m_preq.code = SM_CODE_PAIRING_REQUEST; + sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST); connection->sm_engine_state = SM_INITIATOR_PH1_W4_PAIRING_RESPONSE; l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t)); sm_timeout_reset(connection); @@ -1357,10 +1359,11 @@ static void sm_run(void){ case SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE: // echo initiator for now - setup->sm_s_pres.code = SM_CODE_PAIRING_RESPONSE; + sm_pairing_packet_set_code(setup->sm_s_pres,SM_CODE_PAIRING_RESPONSE); key_distribution_flags = sm_key_distribution_flags_for_auth_req(); - setup->sm_s_pres.initiator_key_distribution = setup->sm_m_preq.initiator_key_distribution & key_distribution_flags; - setup->sm_s_pres.responder_key_distribution = setup->sm_m_preq.responder_key_distribution & key_distribution_flags; + sm_pairing_packet_set_initiator_key_distribution(setup->sm_s_pres, sm_pairing_packet_get_initiator_key_distribution(setup->sm_m_preq) & key_distribution_flags); + sm_pairing_packet_set_responder_key_distribution(setup->sm_s_pres, sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq) & key_distribution_flags); + connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_CONFIRM; l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) &setup->sm_s_pres, sizeof(sm_pairing_packet_t)); sm_timeout_reset(connection); diff --git a/src/ble/sm.h b/src/ble/sm.h index 87fd05823..5ded4ac26 100644 --- a/src/ble/sm.h +++ b/src/ble/sm.h @@ -53,6 +53,50 @@ typedef struct { bd_addr_type_t address_type; } sm_lookup_entry_t; +static inline uint8_t sm_pairing_packet_get_code(sm_pairing_packet_t packet){ + return packet[0]; +} +static inline uint8_t sm_pairing_packet_get_io_capability(sm_pairing_packet_t packet){ + return packet[1]; +} +static inline uint8_t sm_pairing_packet_get_oob_data_flag(sm_pairing_packet_t packet){ + return packet[2]; +} +static inline uint8_t sm_pairing_packet_get_auth_req(sm_pairing_packet_t packet){ + return packet[3]; +} +static inline uint8_t sm_pairing_packet_get_max_encryption_key_size(sm_pairing_packet_t packet){ + return packet[4]; +} +static inline uint8_t sm_pairing_packet_get_initiator_key_distribution(sm_pairing_packet_t packet){ + return packet[5]; +} +static inline uint8_t sm_pairing_packet_get_responder_key_distribution(sm_pairing_packet_t packet){ + return packet[6]; +} + +static inline void sm_pairing_packet_set_code(sm_pairing_packet_t packet, uint8_t code){ + packet[0] = code; +} +static inline void sm_pairing_packet_set_io_capability(sm_pairing_packet_t packet, uint8_t io_capability){ + packet[1] = io_capability; +} +static inline void sm_pairing_packet_set_oob_data_flag(sm_pairing_packet_t packet, uint8_t oob_data_flag){ + packet[2] = oob_data_flag; +} +static inline void sm_pairing_packet_set_auth_req(sm_pairing_packet_t packet, uint8_t auth_req){ + packet[3] = auth_req; +} +static inline void sm_pairing_packet_set_max_encryption_key_size(sm_pairing_packet_t packet, uint8_t max_encryption_key_size){ + packet[4] = max_encryption_key_size; +} +static inline void sm_pairing_packet_set_initiator_key_distribution(sm_pairing_packet_t packet, uint8_t initiator_key_distribution){ + packet[5] = initiator_key_distribution; +} +static inline void sm_pairing_packet_set_responder_key_distribution(sm_pairing_packet_t packet, uint8_t responder_key_distribution){ + packet[6] = responder_key_distribution; +} + /* API_START */ /** diff --git a/src/hci.h b/src/hci.h index b0e1a33c3..b5febacad 100644 --- a/src/hci.h +++ b/src/hci.h @@ -320,15 +320,7 @@ typedef enum { AUTHORIZATION_GRANTED } authorization_state_t; -typedef struct sm_pairing_packet { - uint8_t code; - uint8_t io_capability; - uint8_t oob_data_flag; - uint8_t auth_req; - uint8_t max_encryption_key_size; - uint8_t initiator_key_distribution; - uint8_t responder_key_distribution; -} sm_pairing_packet_t; +typedef uint8_t sm_pairing_packet_t[7]; // connection info available as long as connection exists typedef struct sm_connection { From 7f727f81e57a27995d56a495af217b3aff62c8c8 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 20 Apr 2016 16:52:49 +0200 Subject: [PATCH 12/29] sm: use just works if master or slave have unknown IO capabilities --- src/ble/sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ble/sm.c b/src/ble/sm.c index 8ed3b74c6..5be638c38 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -551,7 +551,7 @@ static void sm_setup_tk(void){ } // Also use just works if unknown io capabilites - if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY)){ + if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_s_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY)){ return; } From b04800026f9e932c77bcab726d4342c46f3ae59f Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 20 Apr 2016 16:57:41 +0200 Subject: [PATCH 13/29] sm: fix compile --- src/ble/sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ble/sm.c b/src/ble/sm.c index 5be638c38..9d97c9e26 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -551,7 +551,7 @@ static void sm_setup_tk(void){ } // Also use just works if unknown io capabilites - if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_s_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY)){ + if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_s_pres) > IO_CAPABILITY_KEYBOARD_DISPLAY)){ return; } From bb6944afd9b3ec354819e79194855d0a5d9b6e85 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 11:47:33 +0200 Subject: [PATCH 14/29] hfp: request rfcomm send event after connection created --- src/classic/hfp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 3e72da8b7..a60991183 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -490,6 +490,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet default: break; } + rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); } break; From 473ac565d5bec808a27038120ea3e66bd9fae3dd Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 11:50:46 +0200 Subject: [PATCH 15/29] hfp_ag: fix sending of chunked AG Indicators --- src/classic/hfp_ag.c | 57 ++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 7b1dbaed3..f33b812d8 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -557,7 +557,6 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){ switch (hfp_connection->command){ case HFP_CMD_AVAILABLE_CODECS: - //printf("HFP_CODECS_RECEIVED_LIST \n"); if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){ hfp_connection->codecs_state = HFP_CODECS_RECEIVED_LIST; hfp_ag_ok(hfp_connection->rfcomm_cid); @@ -576,20 +575,17 @@ static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){ return 1; case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP: - //printf(" HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP \n"); hfp_connection->codecs_state = HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE; hfp_ag_ok(hfp_connection->rfcomm_cid); return 1; case HFP_CMD_AG_SEND_COMMON_CODEC: - //printf(" HFP_CMD_AG_SEND_COMMON_CODEC \n"); hfp_connection->codecs_state = HFP_CODECS_AG_SENT_COMMON_CODEC; hfp_connection->suggested_codec = hfp_ag_suggest_codec(hfp_connection); hfp_ag_cmd_suggest_codec(hfp_connection->rfcomm_cid, hfp_connection->suggested_codec); return 1; case HFP_CMD_HF_CONFIRMED_CODEC: - //printf("HFP_CMD_HF_CONFIRMED_CODEC \n"); if (hfp_connection->codec_confirmed != hfp_connection->suggested_codec){ hfp_connection->codecs_state = HFP_CODECS_ERROR; hfp_ag_error(hfp_connection->rfcomm_cid); @@ -636,9 +632,9 @@ static void hfp_ag_slc_established(hfp_connection_t * hfp_connection){ } static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * hfp_connection){ + log_info("hfp_ag_run_for_context_service_level_connection state %u, command %u", hfp_connection->state, hfp_connection->command); if (hfp_connection->state >= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0; int done = 0; - // printf(" -> State machine: SLC\n"); switch(hfp_connection->command){ case HFP_CMD_SUPPORTED_FEATURES: switch(hfp_connection->state){ @@ -665,18 +661,9 @@ static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * hf case HFP_CMD_RETRIEVE_AG_INDICATORS: if (hfp_connection->state == HFP_W4_RETRIEVE_INDICATORS) { - hfp_connection->command = HFP_CMD_NONE; // prevent reentrance - int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(hfp_connection->rfcomm_cid, hfp_connection, hfp_connection->send_ag_indicators_segment); - if (next_segment < hfp_ag_indicators_cmd_generator_num_segments(hfp_connection)){ - // prepare sending of next segment - hfp_connection->send_ag_indicators_segment = next_segment; - hfp_connection->command = HFP_CMD_RETRIEVE_AG_INDICATORS; - } else { - // done, go to next state - hfp_connection->send_ag_indicators_segment = 0; - hfp_connection->state = HFP_W4_RETRIEVE_INDICATORS_STATUS; - } - return 1; + // HF requested AG Indicators and we did expect it + hfp_connection->state = HFP_RETRIEVE_INDICATORS; + // continue below in state switch } break; @@ -729,16 +716,35 @@ static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * hf default: break; } + + switch (hfp_connection->state){ + case HFP_RETRIEVE_INDICATORS: { + int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(hfp_connection->rfcomm_cid, hfp_connection, hfp_connection->send_ag_indicators_segment); + int num_segments = hfp_ag_indicators_cmd_generator_num_segments(hfp_connection); + log_info("HFP_CMD_RETRIEVE_AG_INDICATORS next segment %u, num_segments %u", next_segment, num_segments); + if (next_segment < num_segments){ + // prepare sending of next segment + hfp_connection->send_ag_indicators_segment = next_segment; + log_info("HFP_CMD_RETRIEVE_AG_INDICATORS more. command %u, next seg %u", hfp_connection->command, next_segment); + } else { + // done, go to next state + hfp_connection->send_ag_indicators_segment = 0; + hfp_connection->state = HFP_W4_RETRIEVE_INDICATORS_STATUS; + } + return 1; + } + default: + break; + } + return done; } static int hfp_ag_run_for_context_service_level_connection_queries(hfp_connection_t * hfp_connection){ - // if (hfp_connection->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0; - + int done = codecs_exchange_state_machine(hfp_connection); if (done) return done; - // printf(" -> State machine: SLC Queries\n"); switch(hfp_connection->command){ case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION: hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION, hfp_connection->ag_activate_voice_recognition); @@ -801,7 +807,6 @@ static int hfp_ag_run_for_audio_connection(hfp_connection_t * hfp_connection){ // run codecs exchange int done = codecs_exchange_state_machine(hfp_connection); if (done) return done; - // printf(" -> State machine: Audio hfp_connection\n"); if (hfp_connection->codecs_state != HFP_CODECS_EXCHANGED) return done; if (hfp_connection->establish_audio_connection){ @@ -1610,9 +1615,15 @@ static void hfp_ag_send_call_status(hfp_connection_t * hfp_connection, int call_ } static void hfp_run_for_context(hfp_connection_t *hfp_connection){ + + log_info("hfp_run_for_context %p", hfp_connection); + if (!hfp_connection) return; + if (!hfp_connection->rfcomm_cid) return; + if (!rfcomm_can_send_packet_now(hfp_connection->rfcomm_cid)) { + log_info("hfp_run_for_context: request can send for 0x%02x", hfp_connection->rfcomm_cid); rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); return; } @@ -1763,6 +1774,10 @@ static void hfp_run_for_context(hfp_connection_t *hfp_connection){ if (done){ hfp_connection->command = HFP_CMD_NONE; } + // + if (done) { + rfcomm_request_can_send_now_event(hfp_connection->rfcomm_cid); + } } static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){ From eddcd3084af8a144b56e09ed9af6b20590981c8a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 12:40:21 +0200 Subject: [PATCH 16/29] hfp: handle command status error when opening sco connection --- src/classic/hfp.c | 78 ++++++++++++++++++++++++++++---------------- src/classic/hfp.h | 2 +- src/classic/hfp_ag.c | 2 +- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/classic/hfp.c b/src/classic/hfp.c index a60991183..b0154bd53 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -99,6 +99,8 @@ static void parse_sequence(hfp_connection_t * context); static hfp_callback_t hfp_callback; static btstack_packet_handler_t rfcomm_packet_handler; +static hfp_connection_t * sco_establishment_active; + void hfp_set_callback(hfp_callback_t callback){ hfp_callback = callback; } @@ -438,13 +440,48 @@ static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uin } } +static void hfp_handle_failed_sco_connection(uint8_t status){ + + if (!sco_establishment_active){ + log_error("(e)SCO Connection failed but not started by us"); + return; + } + log_error("(e)SCO Connection failed status %u", status); + + // invalid params / unspecified error + if (status != 0x11 && status != 0x1f) return; + + switch (sco_establishment_active->link_setting){ + case HFP_LINK_SETTINGS_D0: + return; // no other option left + case HFP_LINK_SETTINGS_D1: + sco_establishment_active->link_setting = HFP_LINK_SETTINGS_D0; + break; + case HFP_LINK_SETTINGS_S1: + sco_establishment_active->link_setting = HFP_LINK_SETTINGS_D1; + break; + case HFP_LINK_SETTINGS_S2: + case HFP_LINK_SETTINGS_S3: + case HFP_LINK_SETTINGS_S4: + sco_establishment_active->link_setting = HFP_LINK_SETTINGS_S1; + break; + case HFP_LINK_SETTINGS_T1: + case HFP_LINK_SETTINGS_T2: + sco_establishment_active->link_setting = HFP_LINK_SETTINGS_S3; + break; + } + sco_establishment_active->establish_audio_connection = 1; + sco_establishment_active = 0; +} + + void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint16_t rfcomm_cid, handle; hfp_connection_t * hfp_connection = NULL; uint8_t status; - // printf("AG packet_handler type %u, event type %x, size %u\n", packet_type, hci_event_packet_get_type(packet), size); + log_info("AG packet_handler type %u, event type %x, size %u", packet_type, hci_event_packet_get_type(packet), size); switch (hci_event_packet_get_type(packet)) { @@ -494,6 +531,12 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet } break; + case HCI_EVENT_COMMAND_STATUS: + if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) { + hfp_handle_failed_sco_connection(hci_event_command_status_get_status(packet)); + } + break; + case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ reverse_bd_addr(&packet[5], event_addr); @@ -501,32 +544,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet status = packet[index++]; if (status != 0){ - log_error("(e)SCO Connection failed status %u", status); - // if outgoing && link_setting != d0 && appropriate error - if (status != 0x11 && status != 0x1f) break; // invalid params / unspecified error - hfp_connection = get_hfp_connection_context_for_bd_addr(event_addr); - if (!hfp_connection) break; - switch (hfp_connection->link_setting){ - case HFP_LINK_SETTINGS_D0: - return; // no other option left - case HFP_LINK_SETTINGS_D1: - // hfp_connection->link_setting = HFP_LINK_SETTINGS_D0; - // break; - case HFP_LINK_SETTINGS_S1: - // hfp_connection->link_setting = HFP_LINK_SETTINGS_D1; - // break; - case HFP_LINK_SETTINGS_S2: - case HFP_LINK_SETTINGS_S3: - case HFP_LINK_SETTINGS_S4: - // hfp_connection->link_setting = HFP_LINK_SETTINGS_S1; - // break; - case HFP_LINK_SETTINGS_T1: - case HFP_LINK_SETTINGS_T2: - // hfp_connection->link_setting = HFP_LINK_SETTINGS_S3; - hfp_connection->link_setting = HFP_LINK_SETTINGS_D0; - break; - } - hfp_connection->establish_audio_connection = 1; + hfp_handle_failed_sco_connection(status); break; } @@ -1332,10 +1350,12 @@ static const struct link_settings { { 0x000d, 0x02, 0x0380 } // HFP_LINK_SETTINGS_T2, 2-EV3 }; -void hfp_setup_synchronous_connection(hci_con_handle_t handle, hfp_link_setttings_t setting){ +void hfp_setup_synchronous_connection(hfp_connection_t * hfp_connection){ // all packet types, fixed bandwidth + int setting = hfp_connection->link_setting; log_info("hfp_setup_synchronous_connection using setting nr %u", setting); - hci_send_cmd(&hci_setup_synchronous_connection, handle, 8000, 8000, hfp_link_settings[setting].max_latency, + sco_establishment_active = hfp_connection; + hci_send_cmd(&hci_setup_synchronous_connection, hfp_connection->acl_handle, 8000, 8000, hfp_link_settings[setting].max_latency, hci_get_sco_voice_setting(), hfp_link_settings[setting].retransmission_effort, hfp_link_settings[setting].packet_types); // all types 0x003f, only 2-ev3 0x380 } diff --git a/src/classic/hfp.h b/src/classic/hfp.h index 22dc8a640..68c9e80a0 100644 --- a/src/classic/hfp.h +++ b/src/classic/hfp.h @@ -645,7 +645,7 @@ void hfp_reset_context_flags(hfp_connection_t * connection); void hfp_release_audio_connection(hfp_connection_t * connection); -void hfp_setup_synchronous_connection(hci_con_handle_t handle, hfp_link_setttings_t link_settings); +void hfp_setup_synchronous_connection(hfp_connection_t * connection); const char * hfp_hf_feature(int index); const char * hfp_ag_feature(int index); diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index f33b812d8..023107ce0 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -812,7 +812,7 @@ static int hfp_ag_run_for_audio_connection(hfp_connection_t * hfp_connection){ if (hfp_connection->establish_audio_connection){ hfp_connection->state = HFP_W4_SCO_CONNECTED; hfp_connection->establish_audio_connection = 0; - hfp_setup_synchronous_connection(hfp_connection->acl_handle, hfp_connection->link_setting); + hfp_setup_synchronous_connection(hfp_connection); return 1; } return 0; From 6c5b2002a2ca49992a963d1762becd217afd94de Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 14:48:17 +0200 Subject: [PATCH 17/29] hfp: don't report command status ok for synchronous setup --- src/classic/hfp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/classic/hfp.c b/src/classic/hfp.c index b0154bd53..9fb02881c 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -446,7 +446,7 @@ static void hfp_handle_failed_sco_connection(uint8_t status){ log_error("(e)SCO Connection failed but not started by us"); return; } - log_error("(e)SCO Connection failed status %u", status); + log_error("(e)SCO Connection failed status 0x%02x", status); // invalid params / unspecified error if (status != 0x11 && status != 0x1f) return; @@ -533,7 +533,10 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet case HCI_EVENT_COMMAND_STATUS: if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) { - hfp_handle_failed_sco_connection(hci_event_command_status_get_status(packet)); + uint8_t status = hci_event_command_status_get_status(packet); + if (status) { + hfp_handle_failed_sco_connection(hci_event_command_status_get_status(packet)); + } } break; From e64e0086b6e940726b732214f11d6320c5a5b42c Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 14:50:02 +0200 Subject: [PATCH 18/29] example/hfp_ag: tidy up --- example/hfp_ag_demo.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index 153ab611f..79e175f15 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -65,7 +65,10 @@ uint8_t hfp_service_buffer[150]; const uint8_t rfcomm_channel_nr = 1; const char hfp_ag_service_name[] = "BTstack HFP AG Test"; -static bd_addr_t device_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46}; +// PTS +// static bd_addr_t device_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46}; +// BT-201 +static bd_addr_t device_addr = {0x00, 0x07, 0xB0, 0x83, 0x02, 0x5E}; static uint8_t codecs[1] = {HFP_CODEC_CVSD}; static uint16_t handle = -1; @@ -189,7 +192,7 @@ static void inquiry_packet_handler (uint8_t packet_type, uint8_t *packet, uint16 numResponses = hci_event_inquiry_result_get_num_responses(packet); int offset = 3; for (i=0; i= 0) continue; // already in our list @@ -234,7 +237,7 @@ static void inquiry_packet_handler (uint8_t packet_type, uint8_t *packet, uint16 break; case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: - reverse_bd_addr(addr, &packet[3]); + reverse_bd_addr(&packet[3], addr); index = getDeviceIndexForAddress(addr); if (index >= 0) { if (packet[2] == 0) { @@ -259,7 +262,10 @@ static void show_usage(void); // Testig User Interface static void show_usage(void){ - printf("\n--- Bluetooth HFP Audiogateway (AG) unit Test Console ---\n"); + bd_addr_t iut_address; + gap_local_bd_addr(iut_address); + + printf("\n--- Bluetooth HFP Audiogateway (AG) unit Test Console %s ---\n", bd_addr_to_str(iut_address)); printf("---\n"); printf("a - establish HFP connection to PTS module\n"); @@ -514,7 +520,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac break; case 't': log_info("USER:\'%c\'", cmd); - printf("Terminate HCI connection.\n"); + printf("Terminate HCI connection. 0x%2x\n", handle); gap_disconnect(handle); break; case 'u': @@ -560,7 +566,6 @@ static void packet_handler(uint8_t * event, uint16_t event_size){ break; } - if (event[0] != HCI_EVENT_HFP_META) return; if (event[3] @@ -639,22 +644,25 @@ static hfp_phone_number_t subscriber_number = { int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ - // HFP HS address is hardcoded, please change it - // init L2CAP - l2cap_init(); - rfcomm_init(); - sdp_init(); + gap_discoverable_control(1); + + // L2CAP + l2cap_init(); + + // HFP + rfcomm_init(); hfp_ag_init(rfcomm_channel_nr); hfp_ag_init_supported_features(0x3ef | (1< Date: Thu, 21 Apr 2016 15:05:23 +0200 Subject: [PATCH 19/29] hfp_hf: fix compile --- src/classic/hfp.c | 2 +- src/classic/hfp_hf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 9fb02881c..0a51433c2 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -533,7 +533,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet case HCI_EVENT_COMMAND_STATUS: if (hci_event_command_status_get_command_opcode(packet) == hci_setup_synchronous_connection.opcode) { - uint8_t status = hci_event_command_status_get_status(packet); + status = hci_event_command_status_get_status(packet); if (status) { hfp_handle_failed_sco_connection(hci_event_command_status_get_status(packet)); } diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index 7586bffca..2aca9eb4b 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -566,7 +566,7 @@ static int hfp_hf_run_for_audio_connection(hfp_connection_t * hfp_connection){ if (hfp_connection->establish_audio_connection){ hfp_connection->state = HFP_W4_SCO_CONNECTED; hfp_connection->establish_audio_connection = 0; - hfp_setup_synchronous_connection(hfp_connection->acl_handle, hfp_connection->link_setting); + hfp_setup_synchronous_connection(hfp_connection); return 1; } From 6ff51cfd6b7d7e31b57ee80cd4a1a52e6877718d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 15:29:46 +0200 Subject: [PATCH 20/29] Add handle to HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED getters --- src/btstack_defines.h | 3 ++- src/btstack_event.h | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/btstack_defines.h b/src/btstack_defines.h index 803bb4196..6057c61c0 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -904,9 +904,10 @@ typedef uint8_t sm_key_t[16]; #define HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED 0x02 /** - * @format 11 + * @format 11H * @param subevent_code * @param status 0 == OK + * @param handle */ #define HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED 0x03 diff --git a/src/btstack_event.h b/src/btstack_event.h index c498133ba..04001c73a 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -2660,6 +2660,15 @@ static inline hci_con_handle_t hfp_subevent_service_level_connection_established static inline uint8_t hfp_subevent_audio_connection_established_get_status(const uint8_t * event){ return event[3]; } +/** + * @brief Get field handle from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @return handle + * @note: btstack_type H + */ +static inline hci_con_handle_t hfp_subevent_audio_connection_established_get_handle(const uint8_t * event){ + return little_endian_read_16(event, 4); +} /** From 3cef842b65a7bc80381f44c5312aee052981b0f0 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 15:58:44 +0200 Subject: [PATCH 21/29] example/hfp_ag: send sinus wave to HF --- example/hfp_ag_demo.c | 68 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index 79e175f15..f628f5eb7 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -61,6 +61,17 @@ #endif +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, +}; + uint8_t hfp_service_buffer[150]; const uint8_t rfcomm_channel_nr = 1; const char hfp_ag_service_name[] = "BTstack HFP AG Test"; @@ -72,6 +83,7 @@ static bd_addr_t device_addr = {0x00, 0x07, 0xB0, 0x83, 0x02, 0x5E}; static uint8_t codecs[1] = {HFP_CODEC_CVSD}; static uint16_t handle = -1; +static hci_con_handle_t sco_handle; static int memory_1_enabled = 1; static int ag_indicators_nr = 7; @@ -553,6 +565,48 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } #endif +#define SCO_REPORT_PERIOD 100 +static void send_sco_data(void){ + if (!sco_handle) return; + + const int sco_packet_length = hci_get_sco_packet_length(); + const int sco_payload_length = sco_packet_length - 3; + const int frames_per_packet = sco_payload_length; // for 8-bit data. for 16-bit data it's /2 + + hci_reserve_packet_buffer(); + uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); + // set handle + flags + little_endian_store_16(sco_packet, 0, sco_handle); + // set len + sco_packet[2] = sco_payload_length; + int i; + for (i=0;i= sizeof(sine)) phase = 0; + } + hci_send_sco_packet_buffer(sco_packet_length); + + // request another send event + hci_request_sco_can_send_now_event(); + + static int count = 0; + count++; + if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); +} + +static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){ + switch (packet_type){ + case HCI_EVENT_PACKET: + if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ + send_sco_data(); + } + break; + default: + break; + } +} + static void packet_handler(uint8_t * event, uint16_t event_size){ switch (event[0]){ case HCI_EVENT_INQUIRY_RESULT: @@ -583,12 +637,21 @@ static void packet_handler(uint8_t * event, uint16_t event_size){ break; case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED: printf("Service level connection released.\n"); + sco_handle = 0; break; case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED: - printf("\n** Audio connection established **\n"); + if (hfp_subevent_audio_connection_established_get_status(event)){ + printf("Audio connection establishment failed with status %u\n", hfp_subevent_audio_connection_established_get_status(event)); + sco_handle = 0; + } else { + sco_handle = hfp_subevent_audio_connection_established_get_handle(event); + printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); + hci_request_sco_can_send_now_event(); + } break; case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: printf("\n** Audio connection released **\n"); + sco_handle = 0; break; case HFP_SUBEVENT_START_RINGINIG: printf("\n** Start Ringing **\n"); @@ -659,7 +722,8 @@ int btstack_main(int argc, const char * argv[]){ hfp_ag_init_hf_indicators(hf_indicators_nr, hf_indicators); hfp_ag_init_call_hold_services(call_hold_services_nr, call_hold_services); hfp_ag_set_subcriber_number_information(&subscriber_number, 1); - hfp_ag_register_packet_handler(packet_handler); + hfp_ag_register_packet_handler(&packet_handler); + hci_register_sco_packet_handler(&sco_packet_handler); // SDP Server sdp_init(); From 827ced601492012208b772af46bb699edb4418e1 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 16:17:03 +0200 Subject: [PATCH 22/29] hfp/hsp: don't call l2cap_init --- src/classic/hfp_ag.c | 2 -- src/classic/hfp_hf.c | 2 -- src/classic/hsp_hs.c | 3 --- 3 files changed, 7 deletions(-) diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 023107ce0..6cc14e70e 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -2052,8 +2052,6 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr){ hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); - l2cap_init(); - rfcomm_register_service(&packet_handler, rfcomm_channel_nr, 0xffff); hfp_ag_response_and_hold_active = 0; diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index 2aca9eb4b..878a3292b 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -1083,8 +1083,6 @@ void hfp_hf_init(uint16_t rfcomm_channel_nr){ hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); - l2cap_init(); - rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff); hfp_set_packet_handler_for_rfcomm_connections(&packet_handler); diff --git a/src/classic/hsp_hs.c b/src/classic/hsp_hs.c index 4ee77e2b8..ab1f2813e 100644 --- a/src/classic/hsp_hs.c +++ b/src/classic/hsp_hs.c @@ -276,9 +276,6 @@ void hsp_hs_init(uint8_t rfcomm_channel_nr){ hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); - // init L2CAP - l2cap_init(); - rfcomm_init(); rfcomm_register_service(packet_handler, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap From 3d50b4ba508ee9a63dad46affe576c15b254cc01 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 20:47:37 +0200 Subject: [PATCH 23/29] hci: use btstack_packet_handler_t for acl and sco callbacks --- example/hfp_ag_demo.c | 2 +- example/hsp_ag_demo.c | 27 +++++++++++++++++---------- example/hsp_hs_demo.c | 22 +++++++++++++++------- src/hci.c | 10 +++++----- src/hci.h | 8 ++++---- src/l2cap.c | 10 +++++----- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index f628f5eb7..1707e7edd 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -595,7 +595,7 @@ static void send_sco_data(void){ if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){ +static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ switch (packet_type){ case HCI_EVENT_PACKET: if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ diff --git a/example/hsp_ag_demo.c b/example/hsp_ag_demo.c index 79df9d4b1..32782dc95 100644 --- a/example/hsp_ag_demo.c +++ b/example/hsp_ag_demo.c @@ -215,16 +215,26 @@ static void send_sco_data(void){ hci_request_sco_can_send_now_event(); static int count = 0; - count++; - if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); + if ((count & SCO_REPORT_PERIOD)) return; + printf("SCO packets sent: %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){ - return; +static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ static int count = 0; - count++; - if ((count & SCO_REPORT_PERIOD)) return; - printf("SCO packets %u\n", count); + switch (packet_type){ + case HCI_EVENT_PACKET: + if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ + send_sco_data(); + } + break; + case HCI_SCO_DATA_PACKET: + count++; + if ((count & SCO_REPORT_PERIOD)) return; + printf("SCO packets received: %u\n", count); + break; + default: + break; + } } static void packet_handler(uint8_t * event, uint16_t event_size){ @@ -233,9 +243,6 @@ static void packet_handler(uint8_t * event, uint16_t event_size){ if (event[2] != HCI_STATE_WORKING) break; show_usage(); break; - case HCI_EVENT_SCO_CAN_SEND_NOW: - send_sco_data(); - break; case HCI_EVENT_HSP_META: switch (event[2]) { case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: diff --git a/example/hsp_hs_demo.c b/example/hsp_hs_demo.c index f1240b943..ffa509db0 100644 --- a/example/hsp_hs_demo.c +++ b/example/hsp_hs_demo.c @@ -215,16 +215,24 @@ static void send_sco_data(void){ hci_request_sco_can_send_now_event(); static int count = 0; - count++; - if ((count & 15) == 0) printf("Sent %u\n", count); + if ((count & SCO_REPORT_PERIOD)) return; + printf("SCO packets sent: %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){ +static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ static int count = 0; - // hexdumpf(packet, size); - count++; - if ((count & SCO_REPORT_PERIOD)) return; - printf("SCO packets %u\n", count); + switch (packet_type){ + case HCI_EVENT_PACKET: + if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ + send_sco_data(); + } + break; + default: + count++; + if ((count & SCO_REPORT_PERIOD)) return; + printf("SCO packets received: %u\n", count); + break; + } } static void packet_handler(uint8_t * event, uint16_t event_size){ diff --git a/src/hci.c b/src/hci.c index 99e886c4c..a59b7b576 100644 --- a/src/hci.c +++ b/src/hci.c @@ -1816,7 +1816,7 @@ static void event_handler(uint8_t *packet, int size){ static void sco_handler(uint8_t * packet, uint16_t size){ if (!hci_stack->sco_packet_handler) return; - hci_stack->sco_packet_handler(HCI_SCO_DATA_PACKET, packet, size); + hci_stack->sco_packet_handler(HCI_SCO_DATA_PACKET, 0, packet, size); } static void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ @@ -1844,14 +1844,14 @@ void hci_add_event_handler(btstack_packet_callback_registration_t * callback_han /** Register HCI packet handlers */ -void hci_register_acl_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ +void hci_register_acl_packet_handler(btstack_packet_handler_t handler){ hci_stack->acl_packet_handler = handler; } /** * @brief Registers a packet handler for SCO data. Used for HSP and HFP profiles. */ -void hci_register_sco_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ +void hci_register_sco_packet_handler(btstack_packet_handler_t handler){ hci_stack->sco_packet_handler = handler; } @@ -2930,7 +2930,7 @@ static void hci_emit_event(uint8_t * event, uint16_t size, int dump){ static void hci_emit_acl_packet(uint8_t * packet, uint16_t size){ if (!hci_stack->acl_packet_handler) return; - hci_stack->acl_packet_handler(HCI_ACL_DATA_PACKET, packet, size); + hci_stack->acl_packet_handler(HCI_ACL_DATA_PACKET, 0, packet, size); } static void hci_notify_if_sco_can_send_now(void){ @@ -2940,7 +2940,7 @@ static void hci_notify_if_sco_can_send_now(void){ hci_stack->sco_waiting_for_can_send_now = 0; uint8_t event[2] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0 }; hci_dump_packet(HCI_EVENT_PACKET, 1, event, sizeof(event)); - hci_stack->sco_packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_stack->sco_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); } } diff --git a/src/hci.h b/src/hci.h index b5febacad..df5c2fb8b 100644 --- a/src/hci.h +++ b/src/hci.h @@ -519,10 +519,10 @@ typedef struct { btstack_linked_list_t connections; /* callback to L2CAP layer */ - void (*acl_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); + btstack_packet_handler_t acl_packet_handler; /* callback for SCO data */ - void (*sco_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); + btstack_packet_handler_t sco_packet_handler; /* callbacks for events */ btstack_linked_list_t event_handlers; @@ -720,12 +720,12 @@ void hci_add_event_handler(btstack_packet_callback_registration_t * callback_han /** * @brief Registers a packet handler for ACL data. Used by L2CAP */ -void hci_register_acl_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)); +void hci_register_acl_packet_handler(btstack_packet_handler_t handler); /** * @brief Registers a packet handler for SCO data. Used for HSP and HFP profiles. */ -void hci_register_sco_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)); +void hci_register_sco_packet_handler(btstack_packet_handler_t handler); // Sending HCI Commands diff --git a/src/l2cap.c b/src/l2cap.c index ddc4f9121..0efef419c 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -82,7 +82,7 @@ static void l2cap_emit_channel_closed(l2cap_channel_t *channel); static void l2cap_emit_connection_request(l2cap_channel_t *channel); static int l2cap_channel_ready_for_open(l2cap_channel_t *channel); static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -static void l2cap_acl_handler(uint8_t packet_type, uint8_t *packet, uint16_t size ); +static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ); static void l2cap_notify_channel_can_send(void); typedef struct l2cap_fixed_channel { @@ -1381,7 +1381,7 @@ static void l2cap_signaling_handler_dispatch( hci_con_handle_t handle, uint8_t * } } -static void l2cap_acl_handler(uint8_t packet_type, uint8_t *packet, uint16_t size ){ +static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ){ // Get Channel ID uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet); @@ -1487,9 +1487,9 @@ static void l2cap_acl_handler(uint8_t packet_type, uint8_t *packet, uint16_t siz default: { // Find channel for this channel_id and connection handle - l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(channel_id); + l2cap_channel_t * l2cap_channel = l2cap_get_channel_for_local_cid(channel_id); if (channel) { - l2cap_dispatch_to_channel(channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); + l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); } break; } @@ -1499,7 +1499,7 @@ static void l2cap_acl_handler(uint8_t packet_type, uint8_t *packet, uint16_t siz } // finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE -void l2cap_finialize_channel_close(l2cap_channel_t *channel){ +void l2cap_finialize_channel_close(l2cap_channel_t * channel){ channel->state = L2CAP_STATE_CLOSED; l2cap_emit_channel_closed(channel); // discard channel From d1fd2a8811aee54fa4cfbcb170349a56f8fd50a5 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 21:23:31 +0200 Subject: [PATCH 24/29] l2cap: fix event forwarding failure by previous commit --- src/l2cap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/l2cap.c b/src/l2cap.c index 0efef419c..51ce5320a 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -1488,7 +1488,7 @@ static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa default: { // Find channel for this channel_id and connection handle l2cap_channel_t * l2cap_channel = l2cap_get_channel_for_local_cid(channel_id); - if (channel) { + if (l2cap_channel) { l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER); } break; From 13839019fac3531c95d6d5428516acfddf89b2dc Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 21:29:03 +0200 Subject: [PATCH 25/29] HFP + HSP: use uniform btstack_packet_handler_t --- example/hfp_ag_demo.c | 163 ++++++++++++++++------------------ example/hfp_hf_demo.c | 2 +- example/hsp_ag_demo.c | 130 +++++++++++++-------------- example/hsp_hs_demo.c | 156 +++++++++++++++----------------- src/classic/hfp.c | 20 ++--- src/classic/hfp.h | 12 ++- src/classic/hfp_ag.c | 4 +- src/classic/hfp_ag.h | 2 +- src/classic/hfp_hf.c | 24 ++--- src/classic/hfp_hf.h | 2 +- src/classic/hsp_ag.c | 12 +-- src/classic/hsp_ag.h | 29 +++--- src/classic/hsp_hs.c | 16 ++-- src/classic/hsp_hs.h | 31 +++---- test/hfp/hfp_ag_client_test.c | 3 +- test/hfp/hfp_hf_client_test.c | 2 +- test/pts/hfp_ag_test.c | 2 +- test/pts/hfp_hf_test.c | 2 +- test/pts/hsp_ag_test.c | 2 +- test/pts/hsp_hs_test.c | 2 +- 20 files changed, 294 insertions(+), 322 deletions(-) diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index 1707e7edd..2f6b05b72 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -595,97 +595,92 @@ static void send_sco_data(void){ if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ switch (packet_type){ case HCI_EVENT_PACKET: - if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ - send_sco_data(); + switch (event[0]){ + case HCI_EVENT_INQUIRY_RESULT: + case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI: + case HCI_EVENT_INQUIRY_COMPLETE: + case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: + inquiry_packet_handler(HCI_EVENT_PACKET, event, event_size); + break; + case HCI_EVENT_SCO_CAN_SEND_NOW: + send_sco_data(); + break; + default: + break; } - break; - default: - break; - } -} -static void packet_handler(uint8_t * event, uint16_t event_size){ - switch (event[0]){ - case HCI_EVENT_INQUIRY_RESULT: - case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI: - case HCI_EVENT_INQUIRY_COMPLETE: - case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: - inquiry_packet_handler(HCI_EVENT_PACKET, event, event_size); - break; + if (event[0] != HCI_EVENT_HFP_META) return; - default: - break; - } - - if (event[0] != HCI_EVENT_HFP_META) return; - - if (event[3] - && event[2] != HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER - && event[2] != HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG - && event[2] != HFP_SUBEVENT_TRANSMIT_DTMF_CODES){ - printf("ERROR, status: %u\n", event[3]); - return; - } - - switch (event[2]) { - case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED: - handle = hfp_subevent_service_level_connection_established_get_con_handle(event); - printf("Service level connection established.\n"); - break; - case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED: - printf("Service level connection released.\n"); - sco_handle = 0; - break; - case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED: - if (hfp_subevent_audio_connection_established_get_status(event)){ - printf("Audio connection establishment failed with status %u\n", hfp_subevent_audio_connection_established_get_status(event)); - sco_handle = 0; - } else { - sco_handle = hfp_subevent_audio_connection_established_get_handle(event); - printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); - hci_request_sco_can_send_now_event(); + if (event[3] + && event[2] != HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER + && event[2] != HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG + && event[2] != HFP_SUBEVENT_TRANSMIT_DTMF_CODES){ + printf("ERROR, status: %u\n", event[3]); + return; } - break; - case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: - printf("\n** Audio connection released **\n"); - sco_handle = 0; - break; - case HFP_SUBEVENT_START_RINGINIG: - printf("\n** Start Ringing **\n"); - break; - case HFP_SUBEVENT_STOP_RINGINIG: - printf("\n** Stop Ringing **\n"); - break; - case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER: - printf("\n** Outgoing call '%s' **\n", hfp_subevent_place_call_with_number_get_number(event)); - // validate number - if ( strcmp("1234567", hfp_subevent_place_call_with_number_get_number(event)) == 0 - || strcmp("7654321", hfp_subevent_place_call_with_number_get_number(event)) == 0 - || (memory_1_enabled && strcmp(">1", hfp_subevent_place_call_with_number_get_number(event)) == 0)){ - printf("Dialstring valid: accept call\n"); - hfp_ag_outgoing_call_accepted(); - } else { - printf("Dialstring invalid: reject call\n"); - hfp_ag_outgoing_call_rejected(); + + switch (event[2]) { + case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED: + handle = hfp_subevent_service_level_connection_established_get_con_handle(event); + printf("Service level connection established.\n"); + break; + case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED: + printf("Service level connection released.\n"); + sco_handle = 0; + break; + case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED: + if (hfp_subevent_audio_connection_established_get_status(event)){ + printf("Audio connection establishment failed with status %u\n", hfp_subevent_audio_connection_established_get_status(event)); + sco_handle = 0; + } else { + sco_handle = hfp_subevent_audio_connection_established_get_handle(event); + printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); + hci_request_sco_can_send_now_event(); + } + break; + case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: + printf("\n** Audio connection released **\n"); + sco_handle = 0; + break; + case HFP_SUBEVENT_START_RINGINIG: + printf("\n** Start Ringing **\n"); + break; + case HFP_SUBEVENT_STOP_RINGINIG: + printf("\n** Stop Ringing **\n"); + break; + case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER: + printf("\n** Outgoing call '%s' **\n", hfp_subevent_place_call_with_number_get_number(event)); + // validate number + if ( strcmp("1234567", hfp_subevent_place_call_with_number_get_number(event)) == 0 + || strcmp("7654321", hfp_subevent_place_call_with_number_get_number(event)) == 0 + || (memory_1_enabled && strcmp(">1", hfp_subevent_place_call_with_number_get_number(event)) == 0)){ + printf("Dialstring valid: accept call\n"); + hfp_ag_outgoing_call_accepted(); + } else { + printf("Dialstring invalid: reject call\n"); + hfp_ag_outgoing_call_rejected(); + } + break; + + case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG: + printf("\n** Attach number to voice tag. Sending '1234567\n"); + hfp_ag_send_phone_number_for_voice_tag(device_addr, "1234567"); + break; + case HFP_SUBEVENT_TRANSMIT_DTMF_CODES: + printf("\n** Send DTMF Codes: '%s'\n", hfp_subevent_transmit_dtmf_codes_get_dtmf(event)); + hfp_ag_send_dtmf_code_done(device_addr); + break; + case HFP_SUBEVENT_CALL_ANSWERED: + printf("Call answered by HF\n"); + break; + default: + printf("Event not handled %u\n", event[2]); + break; } - break; - - case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG: - printf("\n** Attach number to voice tag. Sending '1234567\n"); - hfp_ag_send_phone_number_for_voice_tag(device_addr, "1234567"); - break; - case HFP_SUBEVENT_TRANSMIT_DTMF_CODES: - printf("\n** Send DTMF Codes: '%s'\n", hfp_subevent_transmit_dtmf_codes_get_dtmf(event)); - hfp_ag_send_dtmf_code_done(device_addr); - break; - case HFP_SUBEVENT_CALL_ANSWERED: - printf("Call answered by HF\n"); - break; default: - printf("Event not handled %u\n", event[2]); break; } } @@ -723,7 +718,7 @@ int btstack_main(int argc, const char * argv[]){ hfp_ag_init_call_hold_services(call_hold_services_nr, call_hold_services); hfp_ag_set_subcriber_number_information(&subscriber_number, 1); hfp_ag_register_packet_handler(&packet_handler); - hci_register_sco_packet_handler(&sco_packet_handler); + hci_register_sco_packet_handler(&packet_handler); // SDP Server sdp_init(); diff --git a/example/hfp_hf_demo.c b/example/hfp_hf_demo.c index 76d86077b..008cccc20 100644 --- a/example/hfp_hf_demo.c +++ b/example/hfp_hf_demo.c @@ -444,7 +444,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } #endif -static void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ if (event[0] != HCI_EVENT_HFP_META) return; switch (event[2]) { diff --git a/example/hsp_ag_demo.c b/example/hsp_ag_demo.c index 32782dc95..6966245a3 100644 --- a/example/hsp_ag_demo.c +++ b/example/hsp_ag_demo.c @@ -219,80 +219,81 @@ static void send_sco_data(void){ printf("SCO packets sent: %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ + static int count = 0; + switch (packet_type){ - case HCI_EVENT_PACKET: - if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ - send_sco_data(); - } - break; + case HCI_SCO_DATA_PACKET: count++; if ((count & SCO_REPORT_PERIOD)) return; printf("SCO packets received: %u\n", count); break; - default: - break; - } -} -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; - show_usage(); - break; - case HCI_EVENT_HSP_META: - switch (event[2]) { - case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: - if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ - printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); - } else { - printf("RFCOMM connection established.\n"); - } + case HCI_EVENT_PACKET: + switch (event[0]) { + case BTSTACK_EVENT_STATE: + if (event[2] != HCI_STATE_WORKING) break; + show_usage(); break; - case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: - if (hsp_subevent_rfcomm_disconnection_complete_get_status(event)){ - printf("RFCOMM disconnection failed with status %u.\n", hsp_subevent_rfcomm_disconnection_complete_get_status(event)); - } else { - printf("RFCOMM disconnected.\n"); + case HCI_EVENT_SCO_CAN_SEND_NOW: + send_sco_data(); + break; + case HCI_EVENT_HSP_META: + switch (event[2]) { + case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: + if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ + printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); + } else { + printf("RFCOMM connection established.\n"); + } + break; + case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: + if (hsp_subevent_rfcomm_disconnection_complete_get_status(event)){ + printf("RFCOMM disconnection failed with status %u.\n", hsp_subevent_rfcomm_disconnection_complete_get_status(event)); + } else { + printf("RFCOMM disconnected.\n"); + } + break; + case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: + if (hsp_subevent_audio_connection_complete_get_status(event)){ + printf("Audio connection establishment failed with status %u\n", hsp_subevent_audio_connection_complete_get_status(event)); + sco_handle = 0; + } else { + sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); + printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); + hci_request_sco_can_send_now_event(); + } + break; + case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: + if (hsp_subevent_audio_disconnection_complete_get_status(event)){ + printf("Audio connection releasing failed with status %u\n", hsp_subevent_audio_disconnection_complete_get_status(event)); + } else { + printf("Audio connection released.\n\n"); + sco_handle = 0; + } + break; + case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: + printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); + break; + case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: + printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); + break; + case HSP_SUBEVENT_HS_COMMAND:{ + memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); + int cmd_length = hsp_subevent_hs_command_get_value_length(event); + int size = cmd_length <= sizeof(hs_cmd_buffer)? cmd_length : sizeof(hs_cmd_buffer); + memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1); + printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer); + break; + } + default: + printf("event not handled %u\n", event[2]); + break; } break; - case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: - if (hsp_subevent_audio_connection_complete_get_status(event)){ - printf("Audio connection establishment failed with status %u\n", hsp_subevent_audio_connection_complete_get_status(event)); - sco_handle = 0; - } else { - sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); - printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); - hci_request_sco_can_send_now_event(); - } - break; - case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: - if (hsp_subevent_audio_disconnection_complete_get_status(event)){ - printf("Audio connection releasing failed with status %u\n", hsp_subevent_audio_disconnection_complete_get_status(event)); - } else { - printf("Audio connection released.\n\n"); - sco_handle = 0; - } - break; - case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: - printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); - break; - case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: - printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); - break; - case HSP_SUBEVENT_HS_COMMAND:{ - memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); - int cmd_length = hsp_subevent_hs_command_get_value_length(event); - int size = cmd_length <= sizeof(hs_cmd_buffer)? cmd_length : sizeof(hs_cmd_buffer); - memcpy(hs_cmd_buffer, hsp_subevent_hs_command_get_value(event), size - 1); - printf("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n", hs_cmd_buffer); - break; - } default: - printf("event not handled %u\n", event[2]); break; } break; @@ -319,8 +320,6 @@ static 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[]){ - hci_register_sco_packet_handler(&sco_packet_handler); - l2cap_init(); sdp_init(); @@ -333,7 +332,8 @@ int btstack_main(int argc, const char * argv[]){ rfcomm_init(); hsp_ag_init(rfcomm_channel_nr); - hsp_ag_register_packet_handler(packet_handler); + hsp_ag_register_packet_handler(&packet_handler); + hci_register_sco_packet_handler(&packet_handler); #ifdef HAVE_POSIX_STDIN btstack_stdin_setup(stdin_process); diff --git a/example/hsp_hs_demo.c b/example/hsp_hs_demo.c index ffa509db0..ec2d1bbd3 100644 --- a/example/hsp_hs_demo.c +++ b/example/hsp_hs_demo.c @@ -215,103 +215,95 @@ static void send_sco_data(void){ hci_request_sco_can_send_now_event(); static int count = 0; + count++; if ((count & SCO_REPORT_PERIOD)) return; printf("SCO packets sent: %u\n", count); } -static void sco_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ - static int count = 0; +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ + static int sco_rev_count = 0; switch (packet_type){ + case HCI_SCO_DATA_PACKET: + sco_rev_count++; + if ((sco_rev_count & SCO_REPORT_PERIOD)) break; + printf("SCO packets received: %u\n", sco_rev_count); + break; case HCI_EVENT_PACKET: - if (packet[0] == HCI_EVENT_SCO_CAN_SEND_NOW){ - send_sco_data(); - } - break; - default: - count++; - if ((count & SCO_REPORT_PERIOD)) return; - printf("SCO packets received: %u\n", count); - break; - } -} + switch (event[0]) { + case BTSTACK_EVENT_STATE: + if (btstack_event_state_get_state(event) != HCI_STATE_WORKING) break; + show_usage(); + break; + case HCI_EVENT_SCO_CAN_SEND_NOW: + send_sco_data(); + break; + case HCI_EVENT_HSP_META: + switch (event[2]) { + case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: + if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ + printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); + } else { + printf("RFCOMM connection established.\n"); + } + break; + case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: + if (hsp_subevent_rfcomm_disconnection_complete_get_status(event)){ + printf("RFCOMM disconnection failed with status %u.\n", hsp_subevent_rfcomm_disconnection_complete_get_status(event)); + } else { + printf("RFCOMM disconnected.\n"); + } + break; + case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: + if (hsp_subevent_audio_connection_complete_get_status(event)){ + printf("Audio connection establishment failed with status %u\n", hsp_subevent_audio_connection_complete_get_status(event)); + sco_handle = 0; + } else { + sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); + printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); + hci_request_sco_can_send_now_event(); + } + break; + case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: + if (hsp_subevent_audio_disconnection_complete_get_status(event)){ + printf("Audio connection releasing failed with status %u\n", hsp_subevent_audio_disconnection_complete_get_status(event)); + } else { + printf("Audio connection released.\n\n"); + sco_handle = 0; + } + break; + case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: + printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); + break; + case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: + printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); + break; + case HSP_SUBEVENT_RING: + printf("HS: RING RING!\n"); + break; + case HSP_SUBEVENT_AG_INDICATION: { + memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); + int size = hsp_subevent_ag_indication_get_value_length(event); + if (size >= sizeof(hs_cmd_buffer)-1){ + size = sizeof(hs_cmd_buffer)-1; + } + memcpy(hs_cmd_buffer, hsp_subevent_ag_indication_get_value(event), size); + printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer); -static void packet_handler(uint8_t * event, uint16_t event_size){ - switch (event[0]) { - case BTSTACK_EVENT_STATE: - if (btstack_event_state_get_state(event) != HCI_STATE_WORKING) break; - show_usage(); - break; - case HCI_EVENT_SCO_CAN_SEND_NOW: - send_sco_data(); - break; - case HCI_EVENT_HSP_META: - switch (event[2]) { - case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: - if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ - printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); - } else { - printf("RFCOMM connection established.\n"); - } - break; - case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: - if (hsp_subevent_rfcomm_disconnection_complete_get_status(event)){ - printf("RFCOMM disconnection failed with status %u.\n", hsp_subevent_rfcomm_disconnection_complete_get_status(event)); - } else { - printf("RFCOMM disconnected.\n"); + } + break; + default: + printf("event not handled %u\n", event[2]); + break; } break; - case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: - if (hsp_subevent_audio_connection_complete_get_status(event)){ - printf("Audio connection establishment failed with status %u\n", hsp_subevent_audio_connection_complete_get_status(event)); - sco_handle = 0; - } else { - sco_handle = hsp_subevent_audio_connection_complete_get_handle(event); - printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle); - hci_request_sco_can_send_now_event(); - } - break; - case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: - if (hsp_subevent_audio_disconnection_complete_get_status(event)){ - printf("Audio connection releasing failed with status %u\n", hsp_subevent_audio_disconnection_complete_get_status(event)); - } else { - printf("Audio connection released.\n\n"); - sco_handle = 0; - } - break; - case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: - printf("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event)); - break; - case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: - printf("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event)); - break; - case HSP_SUBEVENT_RING: - printf("HS: RING RING!\n"); - break; - case HSP_SUBEVENT_AG_INDICATION: { - memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer)); - int size = hsp_subevent_ag_indication_get_value_length(event); - if (size >= sizeof(hs_cmd_buffer)-1){ - size = sizeof(hs_cmd_buffer)-1; - } - memcpy(hs_cmd_buffer, hsp_subevent_ag_indication_get_value(event), size); - printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer); - - } - break; default: - printf("event not handled %u\n", event[2]); break; } - break; default: break; } } -static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ - packet_handler(packet, size); -} - /* @section Main Application Setup * * @text Listing MainConfiguration shows main application code. @@ -331,9 +323,9 @@ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ // register for HCI events - hci_event_callback_registration.callback = &handle_hci_event; + hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); - hci_register_sco_packet_handler(&sco_packet_handler); + hci_register_sco_packet_handler(&packet_handler); l2cap_init(); diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 0a51433c2..a47178ad6 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -96,12 +96,12 @@ static const char * hfp_ag_features[] = { static btstack_linked_list_t hfp_connections = NULL; static void parse_sequence(hfp_connection_t * context); -static hfp_callback_t hfp_callback; +static btstack_packet_handler_t hfp_callback; static btstack_packet_handler_t rfcomm_packet_handler; static hfp_connection_t * sco_establishment_active; -void hfp_set_callback(hfp_callback_t callback){ +void hfp_set_callback(btstack_packet_handler_t callback){ hfp_callback = callback; } @@ -186,26 +186,26 @@ int join_bitmap(char * buffer, int buffer_size, uint32_t values, int values_nr){ return offset; } -void hfp_emit_simple_event(hfp_callback_t callback, uint8_t event_subtype){ +void hfp_emit_simple_event(btstack_packet_handler_t callback, uint8_t event_subtype){ if (!callback) return; uint8_t event[3]; event[0] = HCI_EVENT_HFP_META; event[1] = sizeof(event) - 2; event[2] = event_subtype; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value){ +void hfp_emit_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t value){ if (!callback) return; uint8_t event[4]; event[0] = HCI_EVENT_HFP_META; event[1] = sizeof(event) - 2; event[2] = event_subtype; event[3] = value; // status 0 == OK - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void hfp_emit_connection_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle){ +void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle){ if (!callback) return; uint8_t event[6]; event[0] = HCI_EVENT_HFP_META; @@ -213,10 +213,10 @@ void hfp_emit_connection_event(hfp_callback_t callback, uint8_t event_subtype, u event[2] = event_subtype; event[3] = status; // status 0 == OK little_endian_store_16(event, 4, con_handle); - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void hfp_emit_string_event(hfp_callback_t callback, uint8_t event_subtype, const char * value){ +void hfp_emit_string_event(btstack_packet_handler_t callback, uint8_t event_subtype, const char * value){ if (!callback) return; uint8_t event[40]; event[0] = HCI_EVENT_HFP_META; @@ -225,7 +225,7 @@ void hfp_emit_string_event(hfp_callback_t callback, uint8_t event_subtype, const int size = (strlen(value) < sizeof(event) - 4) ? strlen(value) : sizeof(event) - 4; strncpy((char*)&event[3], value, size); event[3 + size] = 0; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } btstack_linked_list_t * hfp_get_connections(void){ diff --git a/src/classic/hfp.h b/src/classic/hfp.h index 68c9e80a0..e1c067342 100644 --- a/src/classic/hfp.h +++ b/src/classic/hfp.h @@ -432,8 +432,6 @@ typedef enum{ HFP_CALL_SM } hfp_state_machine_t; -typedef void (*hfp_callback_t)(uint8_t * event, uint16_t event_size); - typedef struct{ uint16_t uuid; uint8_t state; // enabled @@ -621,16 +619,16 @@ int get_bit(uint16_t bitmap, int position); int store_bit(uint32_t bitmap, int position, uint8_t value); // UTILS_END -void hfp_set_callback(hfp_callback_t callback); +void hfp_set_callback(btstack_packet_handler_t callback); void hfp_set_packet_handler_for_rfcomm_connections(btstack_packet_handler_t handler); void hfp_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t service_uuid, int rfcomm_channel_nr, const char * name); void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -void hfp_emit_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t value); -void hfp_emit_simple_event(hfp_callback_t callback, uint8_t event_subtype); -void hfp_emit_string_event(hfp_callback_t callback, uint8_t event_subtype, const char * value); -void hfp_emit_connection_event(hfp_callback_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle); +void hfp_emit_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t value); +void hfp_emit_simple_event(btstack_packet_handler_t callback, uint8_t event_subtype); +void hfp_emit_string_event(btstack_packet_handler_t callback, uint8_t event_subtype, const char * value); +void hfp_emit_connection_event(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, hci_con_handle_t con_handle); hfp_connection_t * get_hfp_connection_context_for_rfcomm_cid(uint16_t cid); hfp_connection_t * get_hfp_connection_context_for_bd_addr(bd_addr_t bd_addr); diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 6cc14e70e..f8fe311d2 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -95,7 +95,7 @@ static hfp_generic_status_indicator_t hfp_generic_status_indicators[HFP_MAX_NUM_ static int hfp_ag_call_hold_services_nr = 0; static char *hfp_ag_call_hold_services[6]; -static hfp_callback_t hfp_callback; +static btstack_packet_handler_t hfp_callback; static hfp_response_and_hold_state_t hfp_ag_response_and_hold_state; static int hfp_ag_response_and_hold_active = 0; @@ -149,7 +149,7 @@ static int get_ag_indicator_index_for_name(const char * name){ } -void hfp_ag_register_packet_handler(hfp_callback_t callback){ +void hfp_ag_register_packet_handler(btstack_packet_handler_t callback){ if (callback == NULL){ log_error("hfp_ag_register_packet_handler called with NULL callback"); return; diff --git a/src/classic/hfp_ag.h b/src/classic/hfp_ag.h index 9881d08f2..272792ae9 100644 --- a/src/classic/hfp_ag.h +++ b/src/classic/hfp_ag.h @@ -115,7 +115,7 @@ void hfp_ag_init_call_hold_services(int call_hold_services_nr, const char * call * @brief Register callback for the HFP Audio Gateway (AG) client. * @param callback */ -void hfp_ag_register_packet_handler(hfp_callback_t callback); +void hfp_ag_register_packet_handler(btstack_packet_handler_t callback); /** * @brief Enable in-band ring tone. diff --git a/src/classic/hfp_hf.c b/src/classic/hfp_hf.c index 878a3292b..1506ea854 100644 --- a/src/classic/hfp_hf.c +++ b/src/classic/hfp_hf.c @@ -74,7 +74,7 @@ static uint32_t hfp_indicators_value[HFP_MAX_NUM_HF_INDICATORS]; static uint8_t hfp_hf_speaker_gain = 9; static uint8_t hfp_hf_microphone_gain = 9; -static hfp_callback_t hfp_callback; +static btstack_packet_handler_t hfp_callback; static hfp_call_status_t hfp_call_status; static hfp_callsetup_status_t hfp_callsetup_status; @@ -84,7 +84,7 @@ static char phone_number[25]; static btstack_packet_callback_registration_t hci_event_callback_registration; -void hfp_hf_register_packet_handler(hfp_callback_t callback){ +void hfp_hf_register_packet_handler(btstack_packet_handler_t callback){ hfp_callback = callback; if (callback == NULL){ log_error("hfp_hf_register_packet_handler called with NULL callback"); @@ -94,7 +94,7 @@ void hfp_hf_register_packet_handler(hfp_callback_t callback){ hfp_set_callback(callback); } -static void hfp_hf_emit_subscriber_information(hfp_callback_t callback, uint8_t event_subtype, uint8_t status, uint8_t bnip_type, const char * bnip_number){ +static void hfp_hf_emit_subscriber_information(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t status, uint8_t bnip_type, const char * bnip_number){ if (!callback) return; uint8_t event[31]; event[0] = HCI_EVENT_HFP_META; @@ -105,10 +105,10 @@ static void hfp_hf_emit_subscriber_information(hfp_callback_t callback, uint8_t int size = (strlen(bnip_number) < sizeof(event) - 6) ? strlen(bnip_number) : sizeof(event) - 6; strncpy((char*)&event[5], bnip_number, size); event[5 + size] = 0; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -static void hfp_hf_emit_type_and_number(hfp_callback_t callback, uint8_t event_subtype, uint8_t bnip_type, const char * bnip_number){ +static void hfp_hf_emit_type_and_number(btstack_packet_handler_t callback, uint8_t event_subtype, uint8_t bnip_type, const char * bnip_number){ if (!callback) return; uint8_t event[30]; event[0] = HCI_EVENT_HFP_META; @@ -118,10 +118,10 @@ static void hfp_hf_emit_type_and_number(hfp_callback_t callback, uint8_t event_s int size = (strlen(bnip_number) < sizeof(event) - 5) ? strlen(bnip_number) : sizeof(event) - 5; strncpy((char*)&event[4], bnip_number, size); event[4 + size] = 0; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -static void hfp_hf_emit_enhanced_call_status(hfp_callback_t callback, uint8_t clcc_idx, uint8_t clcc_dir, +static void hfp_hf_emit_enhanced_call_status(btstack_packet_handler_t callback, uint8_t clcc_idx, uint8_t clcc_dir, uint8_t clcc_status, uint8_t clcc_mpty, uint8_t bnip_type, const char * bnip_number){ if (!callback) return; uint8_t event[35]; @@ -136,7 +136,7 @@ static void hfp_hf_emit_enhanced_call_status(hfp_callback_t callback, uint8_t cl int size = (strlen(bnip_number) < sizeof(event) - 10) ? strlen(bnip_number) : sizeof(event) - 10; strncpy((char*)&event[9], bnip_number, size); event[9 + size] = 0; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static int hfp_hf_supports_codec(uint8_t codec){ @@ -373,7 +373,7 @@ static int hfp_hf_send_clcc(uint16_t cid){ return send_str_over_rfcomm(cid, buffer); } -static void hfp_emit_ag_indicator_event(hfp_callback_t callback, hfp_ag_indicator_t indicator){ +static void hfp_emit_ag_indicator_event(btstack_packet_handler_t callback, hfp_ag_indicator_t indicator){ if (!callback) return; uint8_t event[5+HFP_MAX_INDICATOR_DESC_SIZE+1]; event[0] = HCI_EVENT_HFP_META; @@ -383,10 +383,10 @@ static void hfp_emit_ag_indicator_event(hfp_callback_t callback, hfp_ag_indicato event[4] = indicator.status; strncpy((char*)&event[5], indicator.name, HFP_MAX_INDICATOR_DESC_SIZE); event[5+HFP_MAX_INDICATOR_DESC_SIZE] = 0; - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -static void hfp_emit_network_operator_event(hfp_callback_t callback, hfp_network_opearator_t network_operator){ +static void hfp_emit_network_operator_event(btstack_packet_handler_t callback, hfp_network_opearator_t network_operator){ if (!callback) return; uint8_t event[24]; event[0] = HCI_EVENT_HFP_META; @@ -395,7 +395,7 @@ static void hfp_emit_network_operator_event(hfp_callback_t callback, hfp_network event[3] = network_operator.mode; event[4] = network_operator.format; strcpy((char*)&event[5], network_operator.name); - (*callback)(event, sizeof(event)); + (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static int hfp_hf_run_for_context_service_level_connection(hfp_connection_t * hfp_connection){ diff --git a/src/classic/hfp_hf.h b/src/classic/hfp_hf.h index a3832bc1e..8e88bad9b 100644 --- a/src/classic/hfp_hf.h +++ b/src/classic/hfp_hf.h @@ -95,7 +95,7 @@ void hfp_hf_init_hf_indicators(int indicators_nr, uint16_t * indicators); * @brief Register callback for the HFP Hands-Free (HF) client. * @param callback */ -void hfp_hf_register_packet_handler(hfp_callback_t callback); +void hfp_hf_register_packet_handler(btstack_packet_handler_t callback); /** * @brief Establish RFCOMM connection with the AG with given Bluetooth address, diff --git a/src/classic/hsp_ag.c b/src/classic/hsp_ag.c index 3e953d452..c4bf0d1ab 100644 --- a/src/classic/hsp_ag.c +++ b/src/classic/hsp_ag.c @@ -124,15 +124,15 @@ typedef enum { static hsp_state_t hsp_state = HSP_IDLE; -static hsp_ag_callback_t hsp_ag_callback; +static btstack_packet_handler_t hsp_ag_callback; static void hsp_run(void); static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -static void dummy_notify(uint8_t * event, uint16_t size){} +static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){} -void hsp_ag_register_packet_handler(hsp_ag_callback_t callback){ +void hsp_ag_register_packet_handler(btstack_packet_handler_t callback){ if (callback == NULL){ callback = &dummy_notify; } @@ -146,7 +146,7 @@ static void emit_event(uint8_t event_subtype, uint8_t value){ event[1] = sizeof(event) - 2; event[2] = event_subtype; event[3] = value; // status 0 == OK - (*hsp_ag_callback)(event, sizeof(event)); + (*hsp_ag_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static void emit_event_audio_connected(uint8_t status, uint16_t handle){ @@ -157,7 +157,7 @@ static void emit_event_audio_connected(uint8_t status, uint16_t handle){ event[2] = HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE; event[3] = status; little_endian_store_16(event, 4, handle); - (*hsp_ag_callback)(event, sizeof(event)); + (*hsp_ag_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } void hsp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, int rfcomm_channel_nr, const char * name){ @@ -554,7 +554,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack event[1] = size + 2; event[2] = HSP_SUBEVENT_HS_COMMAND; event[3] = size; - (*hsp_ag_callback)(event, size+4); + (*hsp_ag_callback)(HCI_EVENT_PACKET, 0, event, size+4); } hsp_run(); diff --git a/src/classic/hsp_ag.h b/src/classic/hsp_ag.h index 085ee700b..9f6692a83 100644 --- a/src/classic/hsp_ag.h +++ b/src/classic/hsp_ag.h @@ -54,23 +54,6 @@ extern "C" { /* API_START */ -/** - * @brief Packet handler for HSP Audio Gateway (AG) events. - * - * The HSP AG event has type HCI_EVENT_HSP_META with following subtypes: - * - HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE - * - HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE - * - HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE - * - HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE - * - HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED - * - HSP_SUBEVENT_SPEAKER_GAIN_CHANGED - * - HSP_SUBEVENT_HS_COMMAND - * - * @param event See include/btstack/hci_cmds.h - * @param event_size - */ -typedef void (*hsp_ag_callback_t)(uint8_t * event, uint16_t event_size); - /** * @brief Set up HSP AG. * @param rfcomm_channel_nr @@ -88,9 +71,19 @@ void hsp_ag_create_sdp_record(uint8_t * service, uint32_t service_record_handle, /** * @brief Register packet handler to receive HSP AG events. + + * The HSP AG event has type HCI_EVENT_HSP_META with following subtypes: + * - HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE + * - HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE + * - HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE + * - HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE + * - HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED + * - HSP_SUBEVENT_SPEAKER_GAIN_CHANGED + * - HSP_SUBEVENT_HS_COMMAND + * * @param callback */ -void hsp_ag_register_packet_handler(hsp_ag_callback_t callback); +void hsp_ag_register_packet_handler(btstack_packet_handler_t callback); /** * @brief Connect to HSP Headset. diff --git a/src/classic/hsp_hs.c b/src/classic/hsp_hs.c index ab1f2813e..8b8995166 100644 --- a/src/classic/hsp_hs.c +++ b/src/classic/hsp_hs.c @@ -123,10 +123,10 @@ static void hsp_run(void); static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -static hsp_hs_callback_t hsp_hs_callback; -static void dummy_notify(uint8_t * event, uint16_t size){} +static btstack_packet_handler_t hsp_hs_callback; +static void dummy_notify(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t size){} -void hsp_hs_register_packet_handler(hsp_hs_callback_t callback){ +void hsp_hs_register_packet_handler(btstack_packet_handler_t callback){ if (callback == NULL){ callback = &dummy_notify; } @@ -140,7 +140,7 @@ static void emit_event(uint8_t event_subtype, uint8_t value){ event[1] = sizeof(event) - 2; event[2] = event_subtype; event[3] = value; // status 0 == OK - (*hsp_hs_callback)(event, sizeof(event)); + (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static void emit_ring_event(void){ @@ -149,7 +149,7 @@ static void emit_ring_event(void){ event[0] = HCI_EVENT_HSP_META; event[1] = sizeof(event) - 2; event[2] = HSP_SUBEVENT_RING; - (*hsp_hs_callback)(event, sizeof(event)); + (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } static void emit_event_audio_connected(uint8_t status, uint16_t handle){ @@ -160,7 +160,7 @@ static void emit_event_audio_connected(uint8_t status, uint16_t handle){ event[2] = HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE; event[3] = status; little_endian_store_16(event, 4, handle); - (*hsp_hs_callback)(event, sizeof(event)); + (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } // remote audio volume control @@ -474,7 +474,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack event[1] = size + 2; event[2] = HSP_SUBEVENT_AG_INDICATION; event[3] = size; - (*hsp_hs_callback)(event, size+4); + (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, size+4); } hsp_run(); return; @@ -587,7 +587,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack case RFCOMM_EVENT_CHANNEL_CLOSED: hsp_hs_reset_state(); - hsp_hs_callback(packet, size); + hsp_hs_callback(HCI_EVENT_PACKET, 0, packet, size); break; default: diff --git a/src/classic/hsp_hs.h b/src/classic/hsp_hs.h index d1838367b..ab29d3ad8 100644 --- a/src/classic/hsp_hs.h +++ b/src/classic/hsp_hs.h @@ -54,24 +54,6 @@ extern "C" { /* API_START */ -/** - * @brief Packet handler for HSP Headset (HS) events. - * - * The HSP HS event has type HCI_EVENT_HSP_META with following subtypes: - * - HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE - * - HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE - * - HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE - * - HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE - * - HSP_SUBEVENT_RING - * - HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED - * - HSP_SUBEVENT_SPEAKER_GAIN_CHANGED - * - HSP_SUBEVENT_AG_INDICATION - * - * @param event See include/btstack/hci_cmds.h - * @param event_size - */ -typedef void (*hsp_hs_callback_t)(uint8_t * event, uint16_t event_size); - /** * @brief Set up HSP HS. * @param rfcomm_channel_nr @@ -89,9 +71,20 @@ void hsp_hs_create_sdp_record(uint8_t * service, uint32_t service_record_handle, /** * @brief Register packet handler to receive HSP HS events. + * + * The HSP HS event has type HCI_EVENT_HSP_META with following subtypes: + * - HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE + * - HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE + * - HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE + * - HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE + * - HSP_SUBEVENT_RING + * - HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED + * - HSP_SUBEVENT_SPEAKER_GAIN_CHANGED + * - HSP_SUBEVENT_AG_INDICATION + * * @param callback */ -void hsp_hs_register_packet_handler(hsp_hs_callback_t callback); +void hsp_hs_register_packet_handler(btstack_packet_handler_t callback); /** * @brief Connect to HSP Audio Gateway. diff --git a/test/hfp/hfp_ag_client_test.c b/test/hfp/hfp_ag_client_test.c index a976ae135..176718419 100644 --- a/test/hfp/hfp_ag_client_test.c +++ b/test/hfp/hfp_ag_client_test.c @@ -346,7 +346,8 @@ static void simulate_test_sequence(hfp_test_item_t * test_item){ } } -void packet_handler(uint8_t * event, uint16_t event_size){ +void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ + if (event[0] != HCI_EVENT_HFP_META) return; if (event[3] diff --git a/test/hfp/hfp_hf_client_test.c b/test/hfp/hfp_hf_client_test.c index b8d8e8cde..6d4068d36 100644 --- a/test/hfp/hfp_hf_client_test.c +++ b/test/hfp/hfp_hf_client_test.c @@ -391,7 +391,7 @@ void simulate_test_sequence(hfp_test_item_t * test_item){ } } -void packet_handler(uint8_t * event, uint16_t event_size){ +void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ if (event[0] != HCI_EVENT_HFP_META) return; switch (event[2]) { diff --git a/test/pts/hfp_ag_test.c b/test/pts/hfp_ag_test.c index 4d89527ba..e27e0a0b2 100644 --- a/test/pts/hfp_ag_test.c +++ b/test/pts/hfp_ag_test.c @@ -570,7 +570,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } -static void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ switch (event[0]){ case HCI_EVENT_INQUIRY_RESULT: case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI: diff --git a/test/pts/hfp_hf_test.c b/test/pts/hfp_hf_test.c index b55c5a9fb..76d1df4bd 100644 --- a/test/pts/hfp_hf_test.c +++ b/test/pts/hfp_hf_test.c @@ -462,7 +462,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } -static void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ if (event[0] != HCI_EVENT_HFP_META) return; switch (event[2]) { diff --git a/test/pts/hsp_ag_test.c b/test/pts/hsp_ag_test.c index a79e0fe25..b1b63008a 100644 --- a/test/pts/hsp_ag_test.c +++ b/test/pts/hsp_ag_test.c @@ -154,7 +154,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } // Audio Gateway routines -static void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ switch (event[2]) { case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: if (event[3] == 0){ diff --git a/test/pts/hsp_hs_test.c b/test/pts/hsp_hs_test.c index 7d131d883..c0a9e3e07 100644 --- a/test/pts/hsp_hs_test.c +++ b/test/pts/hsp_hs_test.c @@ -159,7 +159,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac } } -static void packet_handler(uint8_t * event, uint16_t event_size){ +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ // printf("Packet handler event 0x%02x\n", event[0]); switch (event[0]) { case BTSTACK_EVENT_STATE: From bdb44bd96ae543c7a3d46ba439628bc6db6be702 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 21 Apr 2016 21:48:56 +0200 Subject: [PATCH 26/29] example/hsp+hfp: prettify SCO packet count, show remote addr in menu --- example/hfp_ag_demo.c | 4 ++-- example/hfp_hf_demo.c | 2 +- example/hsp_ag_demo.c | 3 +-- example/hsp_hs_demo.c | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index 2f6b05b72..4a9234bb4 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -280,7 +280,7 @@ static void show_usage(void){ printf("\n--- Bluetooth HFP Audiogateway (AG) unit Test Console %s ---\n", bd_addr_to_str(iut_address)); printf("---\n"); - printf("a - establish HFP connection to PTS module\n"); + printf("a - establish HFP connection to PTS module %s\n", bd_addr_to_str(device_addr)); // printf("A - release HFP connection to PTS module\n"); printf("b - establish AUDIO connection\n"); @@ -592,7 +592,7 @@ static void send_sco_data(void){ static int count = 0; count++; - if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); + if ((count % SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); } static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ diff --git a/example/hfp_hf_demo.c b/example/hfp_hf_demo.c index 008cccc20..693d07e10 100644 --- a/example/hfp_hf_demo.c +++ b/example/hfp_hf_demo.c @@ -85,7 +85,7 @@ static void show_usage(void){ printf("\n--- Bluetooth HFP Hands-Free (HF) unit Test Console ---\n"); printf("---\n"); - printf("a - establish SLC connection to device\n"); + printf("a - establish SLC connection to device %s\n", bd_addr_to_str(device_addr)); printf("A - release SLC connection to device\n"); printf("b - establish Audio connection\n"); diff --git a/example/hsp_ag_demo.c b/example/hsp_ag_demo.c index 6966245a3..bdc6598d3 100644 --- a/example/hsp_ag_demo.c +++ b/example/hsp_ag_demo.c @@ -215,8 +215,7 @@ static void send_sco_data(void){ hci_request_sco_can_send_now_event(); static int count = 0; - if ((count & SCO_REPORT_PERIOD)) return; - printf("SCO packets sent: %u\n", count); + if ((count % SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); } static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ diff --git a/example/hsp_hs_demo.c b/example/hsp_hs_demo.c index ec2d1bbd3..d2874f9db 100644 --- a/example/hsp_hs_demo.c +++ b/example/hsp_hs_demo.c @@ -216,8 +216,7 @@ static void send_sco_data(void){ static int count = 0; count++; - if ((count & SCO_REPORT_PERIOD)) return; - printf("SCO packets sent: %u\n", count); + if ((count % SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count); } static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size){ From d9ec3f99b2ef5d1f0bc418afb7caf6ce897ad715 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Fri, 22 Apr 2016 10:09:40 +0200 Subject: [PATCH 27/29] example/hsp_X_demo: fix error report for HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE --- example/hsp_ag_demo.c | 2 +- example/hsp_hs_demo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/hsp_ag_demo.c b/example/hsp_ag_demo.c index bdc6598d3..e6fe0ac31 100644 --- a/example/hsp_ag_demo.c +++ b/example/hsp_ag_demo.c @@ -243,7 +243,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even switch (event[2]) { case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ - printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); + printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_rfcomm_connection_complete_get_status(event)); } else { printf("RFCOMM connection established.\n"); } diff --git a/example/hsp_hs_demo.c b/example/hsp_hs_demo.c index d2874f9db..81aae70fe 100644 --- a/example/hsp_hs_demo.c +++ b/example/hsp_hs_demo.c @@ -240,7 +240,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even switch (event[2]) { case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: if (hsp_subevent_rfcomm_connection_complete_get_status(event)){ - printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_audio_connection_complete_get_handle(event)); + printf("RFCOMM connection establishement failed with status %u\n", hsp_subevent_rfcomm_connection_complete_get_status(event)); } else { printf("RFCOMM connection established.\n"); } From 664e8b55a1e48293e61484224468b13b65e59636 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 26 Apr 2016 11:44:42 +0200 Subject: [PATCH 28/29] hci_transport_h4_embedded: handle SCO packets --- platform/embedded/hci_transport_h4_embedded.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/platform/embedded/hci_transport_h4_embedded.c b/platform/embedded/hci_transport_h4_embedded.c index 24f6750b6..accc1362f 100644 --- a/platform/embedded/hci_transport_h4_embedded.c +++ b/platform/embedded/hci_transport_h4_embedded.c @@ -67,6 +67,7 @@ typedef enum { H4_W4_PACKET_TYPE = 1, H4_W4_EVENT_HEADER, H4_W4_ACL_HEADER, + H4_W4_SCO_HEADER, H4_W4_PAYLOAD, H4_PACKET_RECEIVED } H4_STATE; @@ -171,13 +172,17 @@ static void h4_block_received(void){ switch (h4_state) { case H4_W4_PACKET_TYPE: switch (hci_packet[0]) { + case HCI_EVENT_PACKET: + h4_state = H4_W4_EVENT_HEADER; + bytes_to_read = HCI_EVENT_HEADER_SIZE; + break; case HCI_ACL_DATA_PACKET: h4_state = H4_W4_ACL_HEADER; bytes_to_read = HCI_ACL_HEADER_SIZE; break; - case HCI_EVENT_PACKET: - h4_state = H4_W4_EVENT_HEADER; - bytes_to_read = HCI_EVENT_HEADER_SIZE; + case HCI_SCO_DATA_PACKET: + h4_state = H4_W4_SCO_HEADER; + bytes_to_read = HCI_SCO_HEADER_SIZE; break; default: log_error("h4_process: invalid packet type 0x%02x", hci_packet[0]); @@ -209,7 +214,16 @@ static void h4_block_received(void){ } h4_state = H4_W4_PAYLOAD; break; - + + case H4_W4_SCO_HEADER: + bytes_to_read = hci_packet[2]; + if (bytes_to_read == 0) { + h4_state = H4_PACKET_RECEIVED; + break; + } + h4_state = H4_W4_PAYLOAD; + break; + case H4_W4_PAYLOAD: h4_state = H4_PACKET_RECEIVED; bytes_to_read = 0; From 287b4054fbd741e620a8ec618dc6cbb62bf425eb Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 27 Apr 2016 10:40:55 +0200 Subject: [PATCH 29/29] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 23657fee1..676b67992 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ **_Note: Major API Changes. For older projects, you may use the [v0.9 branch](https://github.com/bluekitchen/btstack/tree/v0.9). -Please see [Migration notes]([Migration notes]) _** +Please see [Migration notes](https://github.com/bluekitchen/btstack/blob/master/doc/manual/docs/appendix/migration.md)_** # Welcome to BTstack @@ -27,8 +27,8 @@ It has been qualified with the the Bluetooth SIG for GAP, IOP, HFP, HSP, SPP, PA GATT, SM of the Bluetooth 4.2 LE Central and Peripheral roles (QD ID 25340). ## Documentation -- [HTML](http://bluekitchen-gmbh.com/btstack/v1.0) -- [PDF](http://bluekitchen-gmbh.com/btstack_v1.0.pdf) +- [HTML](http://bluekitchen-gmbh.com/btstack) +- [PDF](http://bluekitchen-gmbh.com/btstack.pdf) ## Supported Protocols * L2CAP