From e3eb72c86b846c5ac1f212d7d9e73502edb2a522 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 15:17:10 +0200 Subject: [PATCH 01/24] bugfix: report last characteristic if characteristic is last handle in query --- ble/gatt_client.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 7a1cac8dc..2955e9781 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -672,17 +672,20 @@ static void report_gatt_all_characteristic_descriptors(gatt_client_t * periphera } -static void trigger_next_query(gatt_client_t * peripheral, uint16_t last_result_handle, gatt_client_state_t next_query_state){ - if (last_result_handle < peripheral->end_group_handle){ - peripheral->start_group_handle = last_result_handle + 1; - peripheral->gatt_client_state = next_query_state; - return; - } - // DONE - gatt_client_handle_transaction_complete(peripheral); - emit_gatt_complete_event(peripheral, 0); +static int is_query_done(gatt_client_t * peripheral, uint16_t last_result_handle){ + return last_result_handle >= peripheral->end_group_handle; } +static void trigger_next_query(gatt_client_t * peripheral, uint16_t last_result_handle, gatt_client_state_t next_query_state){ + if (is_query_done(peripheral, last_result_handle)){ + gatt_client_handle_transaction_complete(peripheral); + emit_gatt_complete_event(peripheral, 0); + return; + } + // next + peripheral->start_group_handle = last_result_handle + 1; + peripheral->gatt_client_state = next_query_state; +} static inline void trigger_next_included_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){ trigger_next_query(peripheral, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_QUERY); @@ -697,6 +700,10 @@ static inline void trigger_next_service_by_uuid_query(gatt_client_t * peripheral } static inline void trigger_next_characteristic_query(gatt_client_t * peripheral, uint16_t last_result_handle){ + if (is_query_done(peripheral, last_result_handle)){ + // report last characteristic + characteristic_end_found(peripheral, peripheral->end_group_handle); + } trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY); } @@ -1020,12 +1027,12 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT: report_gatt_characteristics(peripheral, packet, size); trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size)); - // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done + // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR break; case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT: report_gatt_characteristics(peripheral, packet, size); trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size)); - // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done + // GATT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR break; case P_W4_INCLUDED_SERVICE_QUERY_RESULT: { From b826f55995870b7e0c6dc60cb5cc77c71ecdf56a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 15:18:05 +0200 Subject: [PATCH 02/24] add Discover all characteristics in range --- test/pts/ble_central_test.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index f226b6e0d..69af9d0f3 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -79,6 +79,8 @@ typedef enum { CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE, CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE, CENTRAL_W4_PRIMARY_SERVICES, + CENTRAL_ENTER_START_HANDLE_4_DISCOVER_CHARACTERISTICS, + CENTRAL_ENTER_END_HANDLE_4_DISCOVER_CHARACTERISTICS, CENTRAL_W4_CHARACTERISTICS, CENTRAL_W4_READ_CHARACTERISTIC_VALUE_BY_HANDLE, CENTRAL_ENTER_HANDLE_4_READ_CHARACTERISTIC_VALUE_BY_UUID, @@ -434,7 +436,12 @@ void handle_gatt_client_event(le_event_t * event){ printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle); break; case CENTRAL_W4_CHARACTERISTICS: - printf("Characteristic found with handle 0x%04x\n", (((le_characteristic_event_t *) event)->characteristic).value_handle); + printf("Characteristic found with handle 0x%04x, uuid ", (((le_characteristic_event_t *) event)->characteristic).value_handle); + if ((((le_characteristic_event_t *) event)->characteristic).uuid16){ + printf("%04x\n", (((le_characteristic_event_t *) event)->characteristic).uuid16); + } else { + printf_hexdump((((le_characteristic_event_t *) event)->characteristic).uuid128, 16); + } break; default: break; @@ -588,6 +595,7 @@ void show_usage(void){ printf("e - Discover all Primary Services\n"); printf("f/F - Discover Primary Service by UUID16/UUID128\n"); printf("g - Discover all characteristics by UUID16\n"); + printf("h - Discover all characteristics in range\n"); printf("i - Find all included services\n"); printf("j/J - Read (Long) Characteristic Value by handle\n"); printf("k/K - Read Characteristic Value by UUID16/UUID128\n"); @@ -696,6 +704,20 @@ static int ui_process_uint16_request(char buffer){ printf("Discover Primary Services with UUID16 %04x\n", ui_uint16); gatt_client_discover_primary_services_by_uuid16(gc_id, handle, ui_uint16); return 0; + case CENTRAL_ENTER_START_HANDLE_4_DISCOVER_CHARACTERISTICS: + ui_attribute_handle = ui_uint16; + ui_request_uint16("Please enter end handle: "); + central_state = CENTRAL_ENTER_END_HANDLE_4_DISCOVER_CHARACTERISTICS; + return 0; + case CENTRAL_ENTER_END_HANDLE_4_DISCOVER_CHARACTERISTICS: { + printf("Discover Characteristics from 0x%04x to 0x%04x\n", ui_attribute_handle, ui_uint16); + central_state = CENTRAL_W4_CHARACTERISTICS; + le_service_t service; + service.start_group_handle = ui_attribute_handle; + service.end_group_handle = ui_uint16; + gatt_client_discover_characteristics_for_service(gc_id, handle, &service); + return 0; + } case CENTRAL_W4_CHARACTERISTICS: printf("Discover Characteristics with UUID16 %04x\n", ui_uint16); gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 0x0001, 0xffff, ui_uint16); @@ -1094,6 +1116,10 @@ static void ui_process_command(char buffer){ gatt_client_discover_characteristics_for_service(gc_id, handle, &service); break; } + case 'h': + central_state = CENTRAL_ENTER_START_HANDLE_4_DISCOVER_CHARACTERISTICS; + ui_request_uint16("Please enter start_handle: "); + break; case 'i': { central_state = CENTRAL_W4_CHARACTERISTICS; From 150ffeb60a30be712de86bbc6bc0d1bdc86cf203 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 15:41:32 +0200 Subject: [PATCH 03/24] report notifications and indications --- test/pts/ble_central_test.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 69af9d0f3..5a70286ce 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -535,6 +535,16 @@ void handle_gatt_client_event(le_event_t * event){ break; } break; + case GATT_NOTIFICATION: + value = (le_characteristic_value_event_t *) event; + printf("Notification handle 0x%04x, value: ", value->value_handle); + printf_hexdump(value->blob, value->blob_length); + break; + case GATT_INDICATION: + value = (le_characteristic_value_event_t *) event; + printf("Indication handle 0x%04x, value: ", value->value_handle); + printf_hexdump(value->blob, value->blob_length); + break; default: break; } @@ -911,15 +921,16 @@ static int ui_process_data_request(char buffer){ } printf("%c", buffer); - fflush(stdout); if (ui_value_pos & 1){ ui_value_data[ui_value_pos >> 1] |= hex; + printf(" "); } else { ui_value_data[ui_value_pos >> 1] = hex << 4; } ui_value_pos++; + fflush(stdout); return 0; } From 49322b26bdca62fe5fe6ef1b0f59d5a14e7a6d8d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 16:05:44 +0200 Subject: [PATCH 04/24] report gatt notifications without having a peripheral context --- ble/gatt_client.c | 50 +++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 2955e9781..ad605177c 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -489,6 +489,15 @@ static void emit_event(uint16_t gatt_client_id, le_event_t* event){ (*gatt_client_callback)(event); } +static void emit_event_to_all_subclients(le_event_t * event){ + linked_list_iterator_t it; + linked_list_iterator_init(&it, &gatt_subclients); + while (linked_list_iterator_has_next(&it)){ + gatt_subclient_t * subclient = (gatt_subclient_t*) linked_list_iterator_next(&it); + (*subclient->callback)(event); + } +} + static void emit_gatt_complete_event(gatt_client_t * peripheral, uint8_t status){ gatt_complete_event_t event; event.type = GATT_QUERY_COMPLETE; @@ -604,14 +613,18 @@ static void report_gatt_included_service(gatt_client_t * peripheral, uint8_t *uu emit_event(peripheral->subclient_id, (le_event_t*)&event); } +static void setup_characteristic_value_event(le_characteristic_value_event_t * event, uint16_t handle, uint16_t value_handle, uint8_t * value, uint16_t length, uint16_t offset, uint8_t event_type){ + event->type = event_type; + event->handle = handle; + event->value_handle = value_handle; + event->value_offset = offset; + event->blob_length = length; + event->blob = value; +} + static void send_characteristic_value_event(gatt_client_t * peripheral, uint16_t value_handle, uint8_t * value, uint16_t length, uint16_t offset, uint8_t event_type){ le_characteristic_value_event_t event; - event.type = event_type; - event.handle = peripheral->handle; - event.value_handle = value_handle; - event.value_offset = offset; - event.blob_length = length; - event.blob = value; + setup_characteristic_value_event(&event, peripheral->handle, value_handle, value, length, offset, event_type); emit_event(peripheral->subclient_id, (le_event_t*)&event); } @@ -619,8 +632,10 @@ static void report_gatt_long_characteristic_value_blob(gatt_client_t * periphera send_characteristic_value_event(peripheral, peripheral->attribute_handle, value, blob_length, value_offset, GATT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT); } -static void report_gatt_notification(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ - send_characteristic_value_event(peripheral, handle, value, length, 0, GATT_NOTIFICATION); +static void report_gatt_notification(uint16_t con_handle, uint16_t value_handle, uint8_t * value, int length){ + le_characteristic_value_event_t event; + setup_characteristic_value_event(&event, con_handle, value_handle, value, length, 0, GATT_NOTIFICATION); + emit_event_to_all_subclients((le_event_t*)&event); } static void report_gatt_indication(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ @@ -939,15 +954,6 @@ static void gatt_client_run(void){ } -static void emit_event_to_all_subclients(le_event_t * event){ - linked_list_iterator_t it; - linked_list_iterator_init(&it, &gatt_subclients); - while (linked_list_iterator_has_next(&it)){ - gatt_subclient_t * subclient = (gatt_subclient_t*) linked_list_iterator_next(&it); - (*subclient->callback)(event); - } -} - static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code) { if (is_ready(peripheral)) return; gatt_client_handle_transaction_complete(peripheral); @@ -988,6 +994,12 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, } if (packet_type != ATT_DATA_PACKET) return; + + // notification doens't need the gatt_client_t struct + if (packet[0] == ATT_HANDLE_VALUE_NOTIFICATION){ + report_gatt_notification(handle, READ_BT_16(packet,1), &packet[3], size-3); + return; + } gatt_client_t * peripheral = get_gatt_client_context_for_handle(handle); if (!peripheral) return; @@ -1013,10 +1025,6 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, break; } break; - case ATT_HANDLE_VALUE_NOTIFICATION: - report_gatt_notification(peripheral, READ_BT_16(packet,1), &packet[3], size-3); - break; - case ATT_HANDLE_VALUE_INDICATION: report_gatt_indication(peripheral, READ_BT_16(packet,1), &packet[3], size-3); peripheral->send_confirmation = 1; From 12a5e8daf67a2162366ef5c78f2db1827d54917c Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 16:17:53 +0200 Subject: [PATCH 05/24] acquire peripheral context for GATT Indications if needed --- ble/gatt_client.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/ble/gatt_client.c b/ble/gatt_client.c index ad605177c..715603101 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -638,8 +638,10 @@ static void report_gatt_notification(uint16_t con_handle, uint16_t value_handle, emit_event_to_all_subclients((le_event_t*)&event); } -static void report_gatt_indication(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ - send_characteristic_value_event(peripheral, handle, value, length, 0, GATT_INDICATION); +static void report_gatt_indication(uint16_t con_handle, uint16_t value_handle, uint8_t * value, int length){ + le_characteristic_value_event_t event; + setup_characteristic_value_event(&event, con_handle, value_handle, value, length, 0, GATT_INDICATION); + emit_event_to_all_subclients((le_event_t*)&event); } static void report_gatt_characteristic_value(gatt_client_t * peripheral, uint16_t handle, uint8_t * value, int length){ @@ -995,13 +997,20 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, if (packet_type != ATT_DATA_PACKET) return; - // notification doens't need the gatt_client_t struct - if (packet[0] == ATT_HANDLE_VALUE_NOTIFICATION){ - report_gatt_notification(handle, READ_BT_16(packet,1), &packet[3], size-3); - return; + // special cases: notifications don't need a context while indications motivate creating one + gatt_client_t * peripheral; + switch (packet[0]){ + case ATT_HANDLE_VALUE_NOTIFICATION: + report_gatt_notification(handle, READ_BT_16(packet,1), &packet[3], size-3); + return; + case ATT_HANDLE_VALUE_INDICATION: + peripheral = provide_context_for_conn_handle(handle); + break; + default: + peripheral = get_gatt_client_context_for_handle(handle); + break; } - - gatt_client_t * peripheral = get_gatt_client_context_for_handle(handle); + if (!peripheral) return; switch (packet[0]){ @@ -1026,7 +1035,7 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, } break; case ATT_HANDLE_VALUE_INDICATION: - report_gatt_indication(peripheral, READ_BT_16(packet,1), &packet[3], size-3); + report_gatt_indication(handle, READ_BT_16(packet,1), &packet[3], size-3); peripheral->send_confirmation = 1; break; From 7fa238285e9de7c87a193ca85431df4458b26a6a Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 8 Oct 2015 16:26:54 +0200 Subject: [PATCH 06/24] move custom ATT_ERROR_TIMEOUT to 0x7f --- ble/att.h | 3 ++- test/pts/ble_central_test.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ble/att.h b/ble/att.h index 5a788ff38..0d786c7a2 100644 --- a/ble/att.h +++ b/ble/att.h @@ -104,7 +104,8 @@ extern "C" { #define ATT_ERROR_INSUFFICIENT_ENCRYPTION 0x0f #define ATT_ERROR_UNSUPPORTED_GROUP_TYPE 0x10 #define ATT_ERROR_INSUFFICIENT_RESOURCES 0x11 -#define ATT_ERROR_TIMEOUT 0x12 +// custom BTstack ATT error coders +#define ATT_ERROR_TIMEOUT 0x7F // custom BTstack error codes diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 5a70286ce..0b050091d 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -200,11 +200,13 @@ static const char * att_errors[] = { static const char * att_error_reserved = "Reserved"; static const char * att_error_application = "Application Error"; static const char * att_error_common_error = "Common Profile and Service Error Codes"; +static const char * att_error_timeout = "Timeout"; const char * att_error_string_for_code(uint8_t code){ if (code >= 0xe0) return att_error_common_error; if (code >= 0xa0) return att_error_reserved; if (code >= 0x80) return att_error_application; + if (code == 0x7f) return att_error_timeout; if (code >= 0x12) return att_error_reserved; return att_errors[code]; } From c5e516fdd2bdf524931112015f2d0f3674a26df0 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Fri, 9 Oct 2015 23:53:01 +0200 Subject: [PATCH 07/24] add more GAP UUIDs --- ble/att.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ble/att.h b/ble/att.h index 0d786c7a2..1f99d51e1 100644 --- a/ble/att.h +++ b/ble/att.h @@ -144,7 +144,12 @@ extern "C" { #define GATT_SECONDARY_SERVICE_UUID 0x2801 #define GATT_INCLUDE_SERVICE_UUID 0x2802 #define GATT_CHARACTERISTICS_UUID 0x2803 +#define GATT_CHARACTERISTIC_EXTENDED_PROPERTIES 0x2900 +#define GATT_CHARACTERISTIC_USER_DESCRIPTION 0x2901 #define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION 0x2902 +#define GATT_SERVER_CHARACTERISTICS_CONFIGURATION 0x2903 +#define GATT_CHARACTERISTIC_PRESENTATION_FORMAT 0x2904 +#define GATT_CHARACTERISTIC_AGGREGATE_FORMAT 0x2905 #define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE 0 #define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION 1 From e4a65ce94f211f413981bd0b6d49dfb0620b7706 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Fri, 9 Oct 2015 23:53:30 +0200 Subject: [PATCH 08/24] all GATT GPA tests pass --- test/pts/ble_central_test.c | 235 +++++++++++++++++++++++++++++++++--- 1 file changed, 219 insertions(+), 16 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 0b050091d..e05a5eb01 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -100,6 +100,13 @@ typedef enum { CENTRAL_ENTER_HANDLE_4_WRITE_LONG_CHARACTERISTIC_DESCRIPTOR, CENTRAL_W4_WRITE_LONG_CHARACTERISTIC_DESCRIPTOR, CENTRAL_W4_SIGNED_WRITE, + CENTRAL_GPA_ENTER_UUID, + CENTRAL_GPA_ENTER_START_HANDLE, + CENTRAL_GPA_ENTER_END_HANDLE, + CENTRAL_GPA_W4_RESPONSE, + CENTRAL_GPA_W4_RESPONSE2, + CENTRAL_GPA_W4_RESPONSE3, + CENTRAL_GPA_W4_RESPONSE4, } central_state_t; typedef struct advertising_report { @@ -112,6 +119,19 @@ typedef struct advertising_report { uint8_t * data; } advertising_report_t; +static const uint8_t gpa_format_type_len[] = { + /* 0x00 */ + 1,1,1,1,1, + /* 0x05 */ + 2,2, + /* 0x07 */ + 3,4,6,8,16, + /* 0x0c */ + 1,2,2,3,4,6,8,16, + /* 0x14 */ + 4,8,2,4,4 +}; + static uint8_t test_irk[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int gap_privacy = 0; @@ -137,13 +157,18 @@ static int ui_uuid16 = 0; static int ui_uuid128_request = 0; static int ui_uuid128_pos = 0; static uint8_t ui_uuid128[16]; -static int ui_num_handles; +static int ui_handles_count; +static int ui_handles_index; static uint16_t ui_handles[10]; static uint16_t ui_attribute_handle; static int ui_attribute_offset; static int ui_value_request = 0; static uint8_t ui_value_data[50]; static int ui_value_pos = 0; +static uint16_t ui_start_handle; +static uint16_t ui_end_handle; +static uint8_t ui_presentation_format[7]; +static uint16_t ui_aggregate_handle; static uint16_t handle = 0; static uint16_t gc_id; @@ -395,6 +420,7 @@ void use_public_pts_address(void){ void handle_gatt_client_event(le_event_t * event){ le_characteristic_value_event_t * value; + le_characteristic_event_t * characteristic_event; uint8_t address_type; bd_addr_t flipped_address; le_service_t * service; @@ -420,29 +446,40 @@ void handle_gatt_client_event(le_event_t * event){ printf(", start group handle 0x%04x, end group handle 0x%04x\n", service->start_group_handle, service->end_group_handle); break; case GATT_CHARACTERISTIC_QUERY_RESULT: + characteristic_event = ((le_characteristic_event_t *) event); switch (central_state) { case CENTRAL_W4_NAME_QUERY_COMPLETE: - gap_name_characteristic = ((le_characteristic_event_t *) event)->characteristic; + gap_name_characteristic = characteristic_event->characteristic; printf("GAP Name Characteristic found, value handle: 0x04%x\n", gap_name_characteristic.value_handle); break; case CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE: - gap_reconnection_address_characteristic = ((le_characteristic_event_t *) event)->characteristic; + gap_reconnection_address_characteristic = characteristic_event->characteristic; printf("GAP Reconnection Address Characteristic found, value handle: 0x04%x\n", gap_reconnection_address_characteristic.value_handle); break; case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE: - gap_peripheral_privacy_flag_characteristic = ((le_characteristic_event_t *) event)->characteristic; + gap_peripheral_privacy_flag_characteristic = characteristic_event->characteristic; printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle); break; case CENTRAL_W4_SIGNED_WRITE_QUERY_COMPLETE: - signed_write_characteristic = ((le_characteristic_event_t *) event)->characteristic; + signed_write_characteristic = characteristic_event->characteristic; printf("Characteristic for Signed Write found, value handle: 0x%04x\n", signed_write_characteristic.value_handle); break; case CENTRAL_W4_CHARACTERISTICS: - printf("Characteristic found with handle 0x%04x, uuid ", (((le_characteristic_event_t *) event)->characteristic).value_handle); - if ((((le_characteristic_event_t *) event)->characteristic).uuid16){ - printf("%04x\n", (((le_characteristic_event_t *) event)->characteristic).uuid16); + printf("Characteristic found with handle 0x%04x, uuid ", (characteristic_event->characteristic).value_handle); + if ((characteristic_event->characteristic).uuid16){ + printf("%04x\n", (characteristic_event->characteristic).uuid16); } else { - printf_hexdump((((le_characteristic_event_t *) event)->characteristic).uuid128, 16); + printf_hexdump((characteristic_event->characteristic).uuid128, 16); + } + break; + case CENTRAL_GPA_W4_RESPONSE2: + switch (ui_uuid16){ + case GATT_CHARACTERISTIC_PRESENTATION_FORMAT: + case GATT_CHARACTERISTIC_AGGREGATE_FORMAT: + ui_attribute_handle = characteristic_event->characteristic.value_handle; + break; + default: + break; } break; default: @@ -462,7 +499,80 @@ void handle_gatt_client_event(le_event_t * event){ printf("Value: "); printf_hexdump(value->blob, value->blob_length); break; - default: + case CENTRAL_GPA_W4_RESPONSE: + switch (ui_uuid16){ + case GATT_PRIMARY_SERVICE_UUID: + printf ("Attribute handle 0x%04x, primary service 0x%04x\n", value->value_handle, READ_BT_16(value->blob,0)); + break; + case GATT_SECONDARY_SERVICE_UUID: + printf ("Attribute handle 0x%04x, secondary service 0x%04x\n", value->value_handle, READ_BT_16(value->blob,0)); + break; + case GATT_INCLUDE_SERVICE_UUID: + printf ("Attribute handle 0x%04x, included service attribute handle 0x%04x, end group handle 0x%04x, uuid %04x\n", + value->value_handle, READ_BT_16(value->blob,0), READ_BT_16(value->blob,2), READ_BT_16(value->blob,4)); + break; + case GATT_CHARACTERISTICS_UUID: + printf ("Attribute handle 0x%04x, properties 0x%02x, value handle 0x%04x, uuid ", + value->value_handle, value->blob[0], READ_BT_16(value->blob,1)); + if (value->blob_length < 19){ + printf("%04x\n", READ_BT_16(value->blob, 3)); + } else { + printUUID128(&value->blob[3]); + printf("\n"); + } + break; + case GATT_CHARACTERISTIC_EXTENDED_PROPERTIES: + printf ("Attribute handle 0x%04x, gatt characteristic properties 0x%04x\n", value->value_handle, READ_BT_16(value->blob,0)); + break; + case GATT_CHARACTERISTIC_USER_DESCRIPTION: + // go the value, but PTS 6.3 requires another request + printf("Read by type request received, store attribute handle for read request\n"); + ui_attribute_handle = value->value_handle; + break; + case GATT_CLIENT_CHARACTERISTICS_CONFIGURATION: + printf ("Attribute handle 0x%04x, gatt client characteristic configuration 0x%04x\n", value->value_handle, READ_BT_16(value->blob,0)); + break; + case GATT_CHARACTERISTIC_AGGREGATE_FORMAT: + ui_handles_count = value->blob_length >> 1; + printf ("Attribute handle 0x%04x, gatt characteristic aggregate format. Handles: ", value->value_handle); + for (ui_handles_index = 0; ui_handles_index < ui_handles_count ; ui_handles_index++){ + ui_handles[ui_handles_index] = READ_BT_16(value->blob, (ui_handles_index << 1)); + printf("0x%04x, ", ui_handles[ui_handles_index]); + } + printf("\n"); + ui_handles_index = 0; + ui_aggregate_handle = value->value_handle; + break; + case GATT_CHARACTERISTIC_PRESENTATION_FORMAT: + printf("Presentation format: "); + printf_hexdump(value->blob, value->blob_length); + memcpy(ui_presentation_format, value->blob, 7); + break; + default: + printf("Value: "); + printf_hexdump(value->blob, value->blob_length); + break; + } + break; + case CENTRAL_GPA_W4_RESPONSE3: + switch (ui_uuid16){ + case GATT_CHARACTERISTIC_PRESENTATION_FORMAT: + printf("Value: "); + printf_hexdump(value->blob, value->blob_length); + printf("Format 0x%02x, Exponent 0x%02x, Unit 0x%04x\n", + ui_presentation_format[0], ui_presentation_format[1], READ_BT_16(ui_presentation_format, 2)); + break; + case GATT_CHARACTERISTIC_AGGREGATE_FORMAT: + printf("Aggregated value: "); + printf_hexdump(value->blob, value->blob_length); + memcpy(ui_value_data, value->blob, value->blob_length); + ui_value_pos = 0; + central_state = CENTRAL_GPA_W4_RESPONSE4; + default: + break; + } + break; + default: break; } break; @@ -474,8 +584,32 @@ void handle_gatt_client_event(le_event_t * event){ break; case GATT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT: characteristic_descriptor_event = (le_characteristic_descriptor_event_t *) event; - printf("Value: "); - printf_hexdump(characteristic_descriptor_event->value, characteristic_descriptor_event->value_length); + switch (central_state){ + case CENTRAL_GPA_W4_RESPONSE2: + switch (ui_uuid16){ + case GATT_CHARACTERISTIC_USER_DESCRIPTION: + characteristic_descriptor_event->value[characteristic_descriptor_event->value_length] = 0; + printf ("Attribute handle 0x%04x, characteristic user descriptor: %s\n", + characteristic_descriptor_event->handle, characteristic_descriptor_event->value); + break; + default: + break; + } + break; + case CENTRAL_GPA_W4_RESPONSE4: + // only characteristic aggregate format + printf("Value: "); + printf_hexdump(&ui_value_data[ui_value_pos], gpa_format_type_len[characteristic_descriptor_event->value[0]]); + ui_value_pos += gpa_format_type_len[characteristic_descriptor_event->value[0]]; + printf("Format 0x%02x, Exponent 0x%02x, Unit 0x%04x\n", + characteristic_descriptor_event->value[0], characteristic_descriptor_event->value[1], + READ_BT_16(characteristic_descriptor_event->value, 2)); + break; + default: + printf("Value: "); + printf_hexdump(characteristic_descriptor_event->value, characteristic_descriptor_event->value_length); + break; + } break; case GATT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT: characteristic_descriptor_event = (le_characteristic_descriptor_event_t *) event; @@ -532,6 +666,55 @@ void handle_gatt_client_event(le_event_t * event){ printf("Primary Service Discovery complete\n"); central_state = CENTRAL_IDLE; break; + case CENTRAL_GPA_W4_RESPONSE: + switch (ui_uuid16){ + case GATT_CHARACTERISTIC_USER_DESCRIPTION: + central_state = CENTRAL_GPA_W4_RESPONSE2; + printf("Sending Read Characteristic Descriptor at 0x%04x\n", ui_attribute_handle); + gatt_client_read_characteristic_descriptor_using_descriptor_handle(gc_id, handle, ui_attribute_handle); + break; + case GATT_CHARACTERISTIC_PRESENTATION_FORMAT: + case GATT_CHARACTERISTIC_AGGREGATE_FORMAT: + { + printf("Searching Characteristic Declaration\n"); + central_state = CENTRAL_GPA_W4_RESPONSE2; + le_service_t service; + service.start_group_handle = ui_start_handle; + service.end_group_handle = ui_end_handle; + gatt_client_discover_characteristics_for_service(gc_id, handle, &service); + break; + } + break; + default: + break; + } + break; + case CENTRAL_GPA_W4_RESPONSE2: + switch(ui_uuid16){ + case GATT_CHARACTERISTIC_PRESENTATION_FORMAT: + case GATT_CHARACTERISTIC_AGGREGATE_FORMAT: + printf("Reading characteristic value at 0x%04x\n", ui_attribute_handle); + central_state = CENTRAL_GPA_W4_RESPONSE3; + gatt_client_read_value_of_characteristic_using_value_handle(gc_id, handle, ui_attribute_handle); + break; + default: + break; + } + break; + case CENTRAL_GPA_W4_RESPONSE4: + // so far, only GATT_CHARACTERISTIC_AGGREGATE_FORMAT + if (ui_handles_index < ui_handles_count) { + printf("Reading Characteristic Presentation Format at 0x%04x\n", ui_handles[ui_handles_index]); + gatt_client_read_characteristic_descriptor_using_descriptor_handle(gc_id, handle, ui_handles[ui_handles_index]); + ui_handles_index++; + break; + } + if (ui_handles_index == ui_handles_count ) { + // PTS rqequires to read the characteristic aggregate descriptor again (no idea why) + gatt_client_read_value_of_characteristic_using_value_handle(gc_id, handle, ui_aggregate_handle); + ui_handles_index++; + } + break; default: central_state = CENTRAL_IDLE; break; @@ -618,6 +801,7 @@ void show_usage(void){ printf("r - Characteristic Reliable Write\n"); printf("R - Signed Write\n"); printf("u/U - Write (Long) Characteristic Descriptor\n"); + printf("T - Read Generic Profile Attributes by Type\n"); printf("---\n"); printf("4 - IO_CAPABILITY_DISPLAY_ONLY\n"); printf("5 - IO_CAPABILITY_DISPLAY_YES_NO\n"); @@ -771,16 +955,16 @@ static int ui_process_uint16_request(char buffer){ return 0; case CENTRAL_W4_READ_MULTIPLE_CHARACTERISTIC_VALUES: if (ui_uint16){ - ui_handles[ui_num_handles++] = ui_uint16; + ui_handles[ui_handles_count++] = ui_uint16; ui_request_uint16("Please enter handle: "); } else { int i; printf("Read multiple values, handles: "); - for (i=0;i Date: Sat, 10 Oct 2015 14:48:10 +0200 Subject: [PATCH 09/24] clear gatt_client_t before use --- ble/gatt_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 715603101..14eb43038 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -184,6 +184,7 @@ static gatt_client_t * provide_context_for_conn_handle(uint16_t con_handle){ context = btstack_memory_gatt_client_get(); if (!context) return NULL; // init state + memset(context, 0, sizeof(gatt_client_t)); context->handle = con_handle; context->mtu = ATT_DEFAULT_MTU; context->mtu_state = SEND_MTU_EXCHANGE; From 8e96e3b7fd7a041aad799b62e2e1eac6946d701e Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 10 Oct 2015 14:53:02 +0200 Subject: [PATCH 10/24] add gatt_client_pts_suppress_mtu_exchange for testing sm --- ble/gatt_client.c | 10 ++++++++++ ble/gatt_client.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/ble/gatt_client.c b/ble/gatt_client.c index 14eb43038..b8acfb245 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -62,6 +62,7 @@ static linked_list_t gatt_client_connections = NULL; static linked_list_t gatt_subclients = NULL; static uint16_t gatt_client_id = 0; +static uint8_t pts_suppress_mtu_exchange; static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size); static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code); @@ -128,6 +129,7 @@ void gatt_client_unregister_packet_handler(uint16_t gatt_client_id){ void gatt_client_init(void){ gatt_client_connections = NULL; + pts_suppress_mtu_exchange = 0; att_dispatch_register_client(gatt_client_att_packet_handler); } @@ -190,6 +192,11 @@ static gatt_client_t * provide_context_for_conn_handle(uint16_t con_handle){ context->mtu_state = SEND_MTU_EXCHANGE; context->gatt_client_state = P_READY; linked_list_add(&gatt_client_connections, (linked_item_t*)context); + + // skip mtu exchange for testing sm with pts + if (pts_suppress_mtu_exchange){ + context->mtu_state = MTU_EXCHANGED; + } return context; } @@ -1749,4 +1756,7 @@ le_command_status_t gatt_client_write_long_characteristic_descriptor(uint16_t ga return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(gatt_client_id, con_handle, descriptor->handle, length, value); } +void gatt_client_pts_suppress_mtu_exchange(void){ + pts_suppress_mtu_exchange = 1; +} diff --git a/ble/gatt_client.h b/ble/gatt_client.h index 0bc985e5a..ccdf0a786 100644 --- a/ble/gatt_client.h +++ b/ble/gatt_client.h @@ -379,6 +379,9 @@ le_command_status_t gatt_client_write_long_characteristic_descriptor_using_descr le_command_status_t gatt_client_write_client_characteristic_configuration(uint16_t gatt_client_id, uint16_t con_handle, le_characteristic_t * characteristic, uint16_t configuration); /* API_END */ +// only used for testing +void gatt_client_pts_suppress_mtu_exchange(); + #if defined __cplusplus } #endif From 0300d5af9cc95db1a1715af57c58938449628c21 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 10 Oct 2015 15:05:51 +0200 Subject: [PATCH 11/24] use same handle for signed write as in gatt gaw test --- test/pts/ble_central_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index e05a5eb01..302d18e76 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -180,7 +180,7 @@ static int reconnection_address_set = 0; static bd_addr_t our_private_address; static uint16_t pts_signed_write_characteristic_uuid = 0xb00d; -static uint16_t pts_signed_write_characteristic_handle = 0x0100; +static uint16_t pts_signed_write_characteristic_handle = 0x00b1; static uint8_t signed_write_value[] = { 0x12 }; static int le_device_db_index; static sm_key_t signing_csrk; From 80c6fa00ac10e92b9cb6ffea3263bc7d50adf3f7 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 10 Oct 2015 21:36:43 +0200 Subject: [PATCH 12/24] store both local and remote csrk - remote incorrect optimization --- ble/att_server.c | 2 +- ble/gatt_client.c | 2 +- ble/le_device_db.h | 22 ++++++++++++++++++---- ble/le_device_db_dummy.c | 10 +++++++++- ble/le_device_db_memory.c | 24 +++++++++++++++++------- ble/sm.c | 12 +++--------- test/pts/ble_central_test.c | 2 +- 7 files changed, 50 insertions(+), 24 deletions(-) diff --git a/ble/att_server.c b/ble/att_server.c index 59a7a3974..d3cd8728c 100644 --- a/ble/att_server.c +++ b/ble/att_server.c @@ -267,7 +267,7 @@ static void att_run(void){ // signature is { sequence counter, secure hash } sm_key_t csrk; - le_device_db_csrk_get(att_ir_le_device_db_index, csrk); + le_device_db_remote_csrk_get(att_ir_le_device_db_index, csrk); att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION; log_info("Orig Signature: "); hexdump( &att_request_buffer[att_request_size-8], 8); diff --git a/ble/gatt_client.c b/ble/gatt_client.c index b8acfb245..898c5d55a 100644 --- a/ble/gatt_client.c +++ b/ble/gatt_client.c @@ -937,7 +937,7 @@ static void gatt_client_run(void){ case P_W4_CMAC_READY: if (sm_cmac_ready()){ sm_key_t csrk; - le_device_db_csrk_get(peripheral->le_device_index, csrk); + le_device_db_local_csrk_get(peripheral->le_device_index, csrk); uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index); peripheral->gatt_client_state = P_W4_CMAC_RESULT; sm_cmac_start(csrk, ATT_SIGNED_WRITE_COMMAND, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, att_signed_write_handle_cmac_result); diff --git a/ble/le_device_db.h b/ble/le_device_db.h index ce82e7e42..cf1c4e351 100644 --- a/ble/le_device_db.h +++ b/ble/le_device_db.h @@ -115,18 +115,32 @@ void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_k void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized); /** - * @brief set signing key for this device + * @brief set local signing key for this device * @param index * @param signing key as input */ -void le_device_db_csrk_set(int index, sm_key_t csrk); +void le_device_db_local_csrk_set(int index, sm_key_t csrk); /** - * @brief get signing key for this device + * @brief get local signing key for this device * @param index * @param signing key as output */ -void le_device_db_csrk_get(int index, sm_key_t csrk); +void le_device_db_local_csrk_get(int index, sm_key_t csrk); + +/** + * @brief set remote signing key for this device + * @param index + * @param signing key as input + */ +void le_device_db_remote_csrk_set(int index, sm_key_t csrk); + +/** + * @brief get remote signing key for this device + * @param index + * @param signing key as output + */ +void le_device_db_remote_csrk_get(int index, sm_key_t csrk); /** * @brief query last used/seen signing counter diff --git a/ble/le_device_db_dummy.c b/ble/le_device_db_dummy.c index 345513a9e..c2eaf1680 100644 --- a/ble/le_device_db_dummy.c +++ b/ble/le_device_db_dummy.c @@ -57,7 +57,15 @@ void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t csrk){} // get signature key -void le_device_db_csrk_get(int index, sm_key_t csrk){} +void le_device_db_remote_csrk_get(int index, sm_key_t csrk){} + +void le_device_db_remote_csrk_set(int index, sm_key_t csrk){} + +// get signature key +void le_device_db_local_csrk_get(int index, sm_key_t csrk){} + +void le_device_db_local_csrk_set(int index, sm_key_t csrk){} + // query last used/seen signing counter uint32_t le_device_db_remote_counter_get(int index){ diff --git a/ble/le_device_db_memory.c b/ble/le_device_db_memory.c index a57cdfcb5..81a5fb939 100644 --- a/ble/le_device_db_memory.c +++ b/ble/le_device_db_memory.c @@ -59,10 +59,11 @@ typedef struct le_device_memory_db { uint8_t authorized; // Signed Writes by remote - sm_key_t csrk; + sm_key_t remote_csrk; uint32_t remote_counter; - // Signed Writes to remote (local CSRK is fixed) + // Signed Writes by us + sm_key_t local_csrk; uint32_t local_counter; } le_device_memory_db_t; @@ -150,12 +151,20 @@ void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm } // get signature key -void le_device_db_csrk_get(int index, sm_key_t csrk){ - if (csrk) memcpy(csrk, le_devices[index].csrk, 16); +void le_device_db_remote_csrk_get(int index, sm_key_t csrk){ + if (csrk) memcpy(csrk, le_devices[index].remote_csrk, 16); } -void le_device_db_csrk_set(int index, sm_key_t csrk){ - if (csrk) memcpy(le_devices[index].csrk, csrk, 16); +void le_device_db_remote_csrk_set(int index, sm_key_t csrk){ + if (csrk) memcpy(le_devices[index].remote_csrk, csrk, 16); +} + +void le_device_db_local_csrk_get(int index, sm_key_t csrk){ + if (csrk) memcpy(csrk, le_devices[index].local_csrk, 16); +} + +void le_device_db_local_csrk_set(int index, sm_key_t csrk){ + if (csrk) memcpy(le_devices[index].local_csrk, csrk, 16); } // query last used/seen signing counter @@ -185,6 +194,7 @@ void le_device_db_dump(void){ if (le_devices[i].addr_type == INVALID_ENTRY_ADDR_TYPE) continue; log_info("%u: %u %s", i, le_devices[i].addr_type, bd_addr_to_str(le_devices[i].addr)); log_key("irk", le_devices[i].irk); - log_key("csrk", le_devices[i].csrk); + log_key("local csrk", le_devices[i].local_csrk); + log_key("remote csrk", le_devices[i].remote_csrk); } } diff --git a/ble/sm.c b/ble/sm.c index b6c89e9f2..63cd2eefe 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -1013,7 +1013,7 @@ static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){ // store CSRK if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ log_info("sm: store remote CSRK"); - le_device_db_csrk_set(le_db_index, setup->sm_peer_csrk); + le_device_db_remote_csrk_set(le_db_index, setup->sm_peer_csrk); le_device_db_remote_counter_set(le_db_index, 0); } @@ -1507,14 +1507,8 @@ static void sm_run(void){ uint8_t buffer[17]; buffer[0] = SM_CODE_SIGNING_INFORMATION; - // optimization: use CSRK of Peripheral if received, to avoid storing two CSRKs in our DB - if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ - log_info("sm: mirror CSRK"); - memcpy(setup->sm_local_csrk, setup->sm_peer_csrk, 16); - } else { - log_info("sm: store local CSRK"); - le_device_db_csrk_set(connection->sm_le_db_index, setup->sm_local_csrk); - } + log_info("sm: store local CSRK"); + le_device_db_local_csrk_set(connection->sm_le_db_index, setup->sm_local_csrk); swap128(setup->sm_local_csrk, &buffer[1]); l2cap_send_connectionless(connection->sm_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer)); sm_timeout_reset(connection); diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 302d18e76..2a88a737f 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -1275,7 +1275,7 @@ static void ui_process_command(char buffer){ break; case 'W': // fetch csrk - le_device_db_csrk_get(le_device_db_index, signing_csrk); + le_device_db_local_csrk_get(le_device_db_index, signing_csrk); // calc signature sm_cmac_start(signing_csrk, ATT_SIGNED_WRITE_COMMAND, pts_signed_write_characteristic_handle, sizeof(signed_write_value), signed_write_value, 0, att_signed_write_handle_cmac_result); break; From 09222c1170ca6b0f41d658acf46cb861a273d97d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 10 Oct 2015 22:04:39 +0200 Subject: [PATCH 13/24] allow to fix local csrk for testing --- ble/sm.c | 13 +++++++++++++ ble/sm.h | 3 +++ test/pts/ble_central_test.c | 1 + 3 files changed, 17 insertions(+) diff --git a/ble/sm.c b/ble/sm.c index 63cd2eefe..f91ee303f 100644 --- a/ble/sm.c +++ b/ble/sm.c @@ -117,6 +117,8 @@ typedef enum { // GLOBAL DATA // +static uint8_t test_use_fixed_local_csrk; + // configuration static uint8_t sm_accepted_stk_generation_methods; static uint8_t sm_max_encryption_key_size; @@ -1505,6 +1507,11 @@ static void sm_run(void){ if (setup->sm_key_distribution_send_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){ setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION; + // hack to reproduce test runs + if (test_use_fixed_local_csrk){ + memset(setup->sm_local_csrk, 0xcc, 16); + } + uint8_t buffer[17]; buffer[0] = SM_CODE_SIGNING_INFORMATION; log_info("sm: store local CSRK"); @@ -2280,6 +2287,10 @@ void sm_test_set_irk(sm_key_t irk){ sm_persistent_irk_ready = 1; } +void sm_test_use_fixed_local_csrk(void){ + test_use_fixed_local_csrk = 1; +} + void sm_init(void){ // set some (BTstack default) ER and IR int i; @@ -2311,6 +2322,8 @@ void sm_init(void){ sm_active_connection = 0; + test_use_fixed_local_csrk = 0; + // attach to lower layers l2cap_register_fixed_channel(sm_packet_handler, L2CAP_CID_SECURITY_MANAGER_PROTOCOL); } diff --git a/ble/sm.h b/ble/sm.h index 0e45c2fd5..b603be8ed 100644 --- a/ble/sm.h +++ b/ble/sm.h @@ -279,6 +279,9 @@ int sm_address_resolution_lookup(uint8_t addr_type, bd_addr_t addr); int sm_le_device_index(uint16_t handle ); /* API_END */ +// testing only +void sm_test_use_fixed_local_csrk(void); + #if defined __cplusplus } #endif diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 2a88a737f..68230b5f9 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -1494,6 +1494,7 @@ int btstack_main(int argc, const char * argv[]){ sm_set_encryption_key_size_range(sm_min_key_size, 16); sm_test_set_irk(test_irk); + sm_test_use_fixed_local_csrk(); // setup GATT Client gatt_client_init(); From a4fe4ae879430fd9580afad27ea01e0ae4671175 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sat, 10 Oct 2015 22:26:55 +0200 Subject: [PATCH 14/24] fix hci_le_advertisements_set_params and gap_advertisements_set_data to correctly disable advertisement before updating params/data --- src/hci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hci.c b/src/hci.c index 32e4be948..537ef1acb 100644 --- a/src/hci.c +++ b/src/hci.c @@ -3125,7 +3125,7 @@ void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t * adve hci_stack->le_advertisements_data = advertising_data; hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_DATA; // disable advertisements before setting data - if (hci_stack->le_advertisements_enabled){ + if (hci_stack->le_advertisements_active){ hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE; } hci_run(); @@ -3159,7 +3159,7 @@ void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t * adve hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_PARAMS; // disable advertisements before changing params - if (hci_stack->le_advertisements_enabled){ + if (hci_stack->le_advertisements_active){ hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE; } hci_run(); From b77cf00a9f971fc0974e469c08c78643cf6dfbfe Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 11 Oct 2015 23:31:11 +0200 Subject: [PATCH 15/24] add hci_dump.c to fix compile --- test/att_db/Makefile | 1 + test/des_iterator/Makefile | 1 + test/remote_device_db/Makefile | 2 ++ test/sdp_client/Makefile | 1 + 4 files changed, 5 insertions(+) diff --git a/test/att_db/Makefile b/test/att_db/Makefile index b3516652f..9f9606953 100644 --- a/test/att_db/Makefile +++ b/test/att_db/Makefile @@ -13,6 +13,7 @@ VPATH += ${BTSTACK_ROOT}/platforms/posix/src COMMON = \ utils.c \ + hci_dump.c \ att_db_util.c \ COMMON_OBJ = $(COMMON:.c=.o) diff --git a/test/des_iterator/Makefile b/test/des_iterator/Makefile index a2899f21a..8459b2f70 100644 --- a/test/des_iterator/Makefile +++ b/test/des_iterator/Makefile @@ -13,6 +13,7 @@ VPATH += ${BTSTACK_ROOT}/platforms/posix/src COMMON = \ sdp_util.c \ + hci_dump.c \ utils.c COMMON_OBJ = $(COMMON:.c=.o) diff --git a/test/remote_device_db/Makefile b/test/remote_device_db/Makefile index 5e7f30eeb..7391132da 100644 --- a/test/remote_device_db/Makefile +++ b/test/remote_device_db/Makefile @@ -14,6 +14,7 @@ VPATH += ${BTSTACK_ROOT}/platforms/posix/src FS = \ utils.c \ + hci_dump.c \ remote_device_db_fs.c @@ -21,6 +22,7 @@ MEMORY = \ utils.c \ memory_pool.c \ btstack_memory.c \ + hci_dump.c \ remote_device_db_memory.c \ linked_list.c diff --git a/test/sdp_client/Makefile b/test/sdp_client/Makefile index c65f5db72..9f388931c 100644 --- a/test/sdp_client/Makefile +++ b/test/sdp_client/Makefile @@ -16,6 +16,7 @@ VPATH += ${BTSTACK_ROOT}/platforms/posix/src COMMON = \ sdp_util.c \ sdp_parser.c \ + hci_dump.c \ utils.c \ COMMON_OBJ = $(COMMON:.c=.o) From edd8bdd843e05fdb0b9d9b48a9540c8a7dcf99f0 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Sun, 11 Oct 2015 23:31:44 +0200 Subject: [PATCH 16/24] fix compile of gatt_client mock --- test/gatt_client/mock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/gatt_client/mock.c b/test/gatt_client/mock.c index 002c5d0f3..e18476e83 100644 --- a/test/gatt_client/mock.c +++ b/test/gatt_client/mock.c @@ -116,7 +116,7 @@ int l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t l int sm_cmac_ready(void){ return 1; } -void sm_cmac_start(sm_key_t k, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8])){ +void sm_cmac_start(sm_key_t k, uint8_t opcode, uint16_t attribute_handle, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8])){ //sm_notify_client(SM_IDENTITY_RESOLVING_SUCCEEDED, sm_central_device_addr_type, sm_central_device_address, 0, sm_central_device_matched); } int sm_le_device_index(uint16_t handle ){ From bbf26c652786aaf6a8229f30666b1c34d1cebbf2 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 12 Oct 2015 10:59:06 +0200 Subject: [PATCH 17/24] make makefile in test fail on build or test error --- test/Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/Makefile b/test/Makefile index cbeaab0fc..7c64dfdf5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -12,24 +12,23 @@ SUBDIRS = \ sdp_client \ security_manager \ -# security_manager \ - -EXCLUDED = ios - subdirs: echo Building all tests + @set -e; \ for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir; \ done clean: echo Clean all test + @set -e; \ for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir clean; \ done test: echo Run all test + @set -e; \ for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir test; \ done From 97b901d7da4f600f2fa838a141980de70c43d04b Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 12 Oct 2015 18:19:58 +0200 Subject: [PATCH 18/24] fix gatt_client test --- test/gatt_client/expected_results.h | 5 +++-- test/gatt_client/gatt_client_test.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/gatt_client/expected_results.h b/test/gatt_client/expected_results.h index 4539fd499..170a87543 100644 --- a/test/gatt_client/expected_results.h +++ b/test/gatt_client/expected_results.h @@ -32,7 +32,7 @@ const uint8_t included_services_uuid128_handles[][2] = { uint8_t characteristic_handles[][2]= { {0x26, 0x2a}, {0x2b, 0x2f}, {0x30, 0x32}, {0x33, 0x35}, {0x36, 0x38}, {0x39, 0x3b}, {0x3c, 0x3e}, {0x3f, 0x41}, {0x42, 0x44}, {0x45, 0x47}, - {0x48, 0x49}, {0x4a, 0x4f}, {0x50, 0x51}, {0x52, 0x53} + {0x48, 0x49}, {0x4a, 0x4f}, {0x50, 0x51}, {0x52, 0x53}, {0x54, 0x55} }; uint8_t characteristic_uuids[][16] = { @@ -49,7 +49,8 @@ uint8_t characteristic_uuids[][16] = { {0x00, 0x00, 0xf1, 0x0a, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}, {0x00, 0x00, 0xf1, 0x0b, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}, {0x00, 0x00, 0xf1, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}, - {0x00, 0x00, 0xf1, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb} + {0x00, 0x00, 0xf1, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}, + {0x00, 0x00, 0xf1, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}, }; uint8_t indication[] = {GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION, 0x00}; diff --git a/test/gatt_client/gatt_client_test.c b/test/gatt_client/gatt_client_test.c index 547c44b9c..b369731dc 100644 --- a/test/gatt_client/gatt_client_test.c +++ b/test/gatt_client/gatt_client_test.c @@ -128,7 +128,7 @@ static void verify_included_services_uuid128(void){ } static void verify_charasteristics(void){ - CHECK_EQUAL(14, result_index); + CHECK_EQUAL(15, result_index); for (int i=0; i Date: Thu, 15 Oct 2015 21:26:27 +0200 Subject: [PATCH 19/24] fix use after free crash --- src/hci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hci.c b/src/hci.c index 537ef1acb..d8c80c713 100644 --- a/src/hci.c +++ b/src/hci.c @@ -2204,9 +2204,12 @@ void hci_run(void){ } if (entry->state & LE_WHITELIST_REMOVE_FROM_CONTROLLER){ + bd_addr_t address; + bd_addr_type_t address_type = entry->address_type; + memcpy(address, entry->address, 6); linked_list_remove(&hci_stack->le_whitelist, (linked_item_t *) entry); btstack_memory_whitelist_entry_free(entry); - hci_send_cmd(&hci_le_remove_device_from_white_list, entry->address_type, entry->address); + hci_send_cmd(&hci_le_remove_device_from_white_list, address_type, address); return; } } From 547765b0200cca8707eaa2a837850887b547a414 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 15 Oct 2015 22:33:38 +0200 Subject: [PATCH 20/24] rework gap le whitelist connections --- src/hci.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/hci.c b/src/hci.c index d8c80c713..bb6edff7e 100644 --- a/src/hci.c +++ b/src/hci.c @@ -85,6 +85,7 @@ static void hci_connection_timestamp(hci_connection_t *connection); static int hci_power_control_on(void); static void hci_power_control_off(void); static void hci_state_reset(void); +static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address); // the STACK is here #ifndef HAVE_MALLOC @@ -1573,27 +1574,35 @@ static void event_handler(uint8_t *packet, int size){ addr_type = (bd_addr_type_t)packet[7]; log_info("LE Connection_complete (status=%u) type %u, %s", packet[3], addr_type, bd_addr_to_str(addr)); conn = hci_connection_for_bd_addr_and_type(addr, addr_type); - // handle error first + // if auto-connect, remove from whitelist in both roles + if (hci_stack->le_connecting_state == LE_CONNECTING_WHITELIST){ + hci_remove_from_whitelist(addr_type, addr); + } + // handle error: error is reported only to the initiator -> outgoing connection if (packet[3]){ + // outgoing connection establishment is done + hci_stack->le_connecting_state = LE_CONNECTING_IDLE; + // remove entry if (conn){ - // outgoing connection failed, remove entry linked_list_remove(&hci_stack->connections, (linked_item_t *) conn); btstack_memory_hci_connection_free( conn ); } - // if authentication error, also delete link key - if (packet[3] == 0x05) { - hci_drop_link_key_for_bd_addr(addr); - } break; } - if (!conn){ - // advertisemts are stopped on incoming connection + // on success, both hosts receive connection complete event + if (packet[6] == 0){ + // if we're master, it was an outgoing connection and we're done with it + hci_stack->le_connecting_state = LE_CONNECTING_IDLE; + } else { + // if we're slave, it was an incoming connection, advertisements have stopped hci_stack->le_advertisements_active = 0; - // LE connections are auto-accepted, so just create a connection if there isn't one already + } + // LE connections are auto-accepted, so just create a connection if there isn't one already + if (!conn){ conn = create_connection_for_bd_addr_and_type(addr, addr_type); } + // no memory, sorry. if (!conn){ - // no memory break; } @@ -3217,13 +3226,7 @@ int gap_auto_connection_start(bd_addr_type_t address_type, bd_addr_t address){ return 0; } -/** - * @brief Auto Connection Establishment - Stop Connecting to device - * @param address_typ - * @param address - * @returns 0 if ok - */ -int gap_auto_connection_stop(bd_addr_type_t address_type, bd_addr_t address){ +static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address){ linked_list_iterator_t it; linked_list_iterator_init(&it, &hci_stack->le_whitelist); while (linked_list_iterator_has_next(&it)){ @@ -3239,6 +3242,16 @@ int gap_auto_connection_stop(bd_addr_type_t address_type, bd_addr_t address){ linked_list_iterator_remove(&it); btstack_memory_whitelist_entry_free(entry); } +} + +/** + * @brief Auto Connection Establishment - Stop Connecting to device + * @param address_typ + * @param address + * @returns 0 if ok + */ +int gap_auto_connection_stop(bd_addr_type_t address_type, bd_addr_t address){ + hci_remove_from_whitelist(address_type, address); hci_run(); return 0; } From 6ef426db84f331a42d3b068dbf17dbfba6b1bc36 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 15 Oct 2015 23:31:53 +0200 Subject: [PATCH 21/24] pretify cli --- test/pts/ble_central_test.c | 197 +++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 71 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 68230b5f9..743de8c10 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -739,83 +739,135 @@ uint16_t value_handle = 1; uint16_t attribute_size = 1; int scanning_active = 0; +int num_rows = 0; +int num_lines = 0; +const char * rows[100]; +const char * lines[100]; +const char * empty_string = ""; +const int width = 70; + +void reset_screen(void){ + // free memory + int i = 0; + for (i=0;i Date: Thu, 15 Oct 2015 23:47:47 +0200 Subject: [PATCH 22/24] fix cli redraw --- test/pts/ble_central_test.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 743de8c10..6b9d68fcf 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -754,6 +754,11 @@ void reset_screen(void){ rows[i] = NULL; } num_rows = 0; + for (i=0;i Date: Fri, 16 Oct 2015 10:52:52 +0200 Subject: [PATCH 23/24] implement backspace for cli --- test/pts/ble_central_test.c | 79 ++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 6b9d68fcf..85a620259 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -70,6 +70,7 @@ // Non standard IXIT #define PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF +#define PTS_UUID128_REPRESENTATION typedef enum { CENTRAL_IDLE, @@ -151,8 +152,9 @@ static int peer_addr_type; static bd_addr_t peer_address; static int ui_passkey = 0; static int ui_digits_for_passkey = 0; -static int ui_uint16_request = 0; static int ui_uint16 = 0; +static int ui_uint16_request = 0; +static int ui_uint16_pos = 0; static int ui_uuid16 = 0; static int ui_uuid128_request = 0; static int ui_uuid128_pos = 0; @@ -918,12 +920,14 @@ static void ui_request_uint16(const char * message){ fflush(stdout); ui_uint16_request = 1; ui_uint16 = 0; + ui_uint16_pos = 0; } static void ui_request_uud128(const char * message){ printf("%s", message); fflush(stdout); ui_uuid128_request = 1; + ui_uuid128_pos = 0; memset(ui_uuid128, 0, 16); } @@ -937,7 +941,6 @@ static void ui_request_data(const char * message){ static int ui_process_digits_for_passkey(char buffer){ if (buffer < '0' || buffer > '9') { - printf("stdinprocess: invalid input 0x%02x\n", buffer); return 0; } printf("%c", buffer); @@ -952,6 +955,15 @@ static int ui_process_digits_for_passkey(char buffer){ } static int ui_process_uint16_request(char buffer){ + if (buffer == 0x7f || buffer == 0x08) { + if (ui_uint16_pos){ + printf("\b \b"); + fflush(stdout); + ui_uint16 >>= 4; + ui_uint16_pos--; + } + return 0; + } if (buffer == '\n' || buffer == '\r'){ ui_uint16_request = 0; printf("\n"); @@ -1072,26 +1084,55 @@ static int ui_process_uint16_request(char buffer){ } int hex = hexForChar(buffer); if (hex < 0){ - printf("stdinprocess: invalid input 0x%02x\n", buffer); return 0; } printf("%c", buffer); fflush(stdout); ui_uint16 = ui_uint16 << 4 | hex; + ui_uint16_pos++; return 0; } +static int uuid128_pos_starts_with_dash(int pos){ + switch(pos){ + case 8: + case 12: + case 16: + case 20: +#ifdef PTS_UUID128_REPRESENTATION + case 4: + case 24: +#endif + return 1; + default: + return 0; + } +} + static int ui_process_uuid128_request(char buffer){ if (buffer == '-') return 0; // skip - + + if (buffer == 0x7f || buffer == 0x08) { + if (ui_uuid128_pos){ + if (uuid128_pos_starts_with_dash(ui_uuid128_pos)){ + printf("\b \b"); + fflush(stdout); + } + printf("\b \b"); + fflush(stdout); + ui_uuid128_pos--; + } + return 0; + } + int hex = hexForChar(buffer); if (hex < 0){ - printf("stdinprocess: invalid input 0x%02x\n", buffer); return 0; } printf("%c", buffer); fflush(stdout); if (ui_uuid128_pos & 1){ - ui_uuid128[ui_uuid128_pos >> 1] |= hex; + ui_uuid128[ui_uuid128_pos >> 1] = (ui_uuid128[ui_uuid128_pos >> 1] & 0xf0) | hex; } else { ui_uuid128[ui_uuid128_pos >> 1] = hex << 4; } @@ -1116,19 +1157,11 @@ static int ui_process_uuid128_request(char buffer){ return 0; } } - switch(ui_uuid128_pos){ - case 8: - case 12: - case 16: - case 20: - printf("-"); - fflush(stdout); - break; - default: - break; + if (uuid128_pos_starts_with_dash(ui_uuid128_pos)){ + printf("-"); + fflush(stdout); } return 0; - } static void ui_announce_write(const char * method){ @@ -1138,6 +1171,17 @@ static void ui_announce_write(const char * method){ } static int ui_process_data_request(char buffer){ + if (buffer == 0x7f || buffer == 0x08) { + if (ui_value_pos){ + if ((ui_value_pos & 1) == 0){ + printf("\b"); + } + printf("\b \b"); + fflush(stdout); + ui_value_pos--; + } + return 0; + } if (buffer == '\n' || buffer == '\r'){ ui_value_request = 0; printf("\n"); @@ -1177,14 +1221,13 @@ static int ui_process_data_request(char buffer){ } int hex = hexForChar(buffer); if (hex < 0){ - printf("stdinprocess: invalid input 0x%02x\n", buffer); return 0; } printf("%c", buffer); if (ui_value_pos & 1){ - ui_value_data[ui_value_pos >> 1] |= hex; + ui_value_data[ui_value_pos >> 1] = (ui_value_data[ui_value_pos >> 1] & 0xf0) | hex; printf(" "); } else { ui_value_data[ui_value_pos >> 1] = hex << 4; From 0ffd472dabd48cea63a4a110e060b4c99a5d154d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Mon, 19 Oct 2015 23:51:53 +0200 Subject: [PATCH 24/24] added platforms/posix-h4: a generic Bluetooth module connected via a serial port --- platforms/posix-h4/.gitignore | 27 +++++++ platforms/posix-h4/Makefile | 27 +++++++ platforms/posix-h4/btstack-config.h | 24 ++++++ platforms/posix-h4/main.c | 115 ++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 platforms/posix-h4/.gitignore create mode 100644 platforms/posix-h4/Makefile create mode 100644 platforms/posix-h4/btstack-config.h create mode 100644 platforms/posix-h4/main.c diff --git a/platforms/posix-h4/.gitignore b/platforms/posix-h4/.gitignore new file mode 100644 index 000000000..506c45d91 --- /dev/null +++ b/platforms/posix-h4/.gitignore @@ -0,0 +1,27 @@ +ancs_client +ancs_client.h +ble_central_test +ble_peripheral +ble_peripheral_sm_minimal +bnep_test +classic_test +gap_dedicated_bonding +gap_inquiry +gap_inquiry_and_bond +gatt_battery_query +gatt_browser +hsp_ag_test +hsp_hs_test +l2cap_test +profile.h +sdp_bnep_query +sdp_general_query +sdp_rfcomm_query +spp_and_le_counter +spp_and_le_counter.h +spp_counter +spp_streamer +led_counter +le_counter.h +ble_peripheral_test +le_counter diff --git a/platforms/posix-h4/Makefile b/platforms/posix-h4/Makefile new file mode 100644 index 000000000..3fb1d1789 --- /dev/null +++ b/platforms/posix-h4/Makefile @@ -0,0 +1,27 @@ +# Makefile for libusb based examples +BTSTACK_ROOT = ../.. +POSIX_ROOT= ${BTSTACK_ROOT}/platforms/posix + +CORE += main.c stdin_support.c + +COMMON += hci_transport_h4.c run_loop_posix.c remote_device_db_fs.c + +include ${BTSTACK_ROOT}/example/embedded/Makefile.inc + +# CC = gcc-fsf-4.9 +CFLAGS += -g -Wall +# CFLAGS += -Werror + +VPATH += ${BTSTACK_ROOT}/platforms/posix/src + +ifeq ($(OS),Windows_NT) +LDFLAGS += -lws2_32 +endif + +# Command Line examples require porting to win32, so only build on other unix-ish hosts +ifneq ($(OS),Windows_NT) +EXAMPLES += ${EXAMPLES_CLI} +CFLAGS += -I${POSIX_ROOT}/src +endif + +all: ${BTSTACK_ROOT}/include/btstack/version.h ${EXAMPLES} diff --git a/platforms/posix-h4/btstack-config.h b/platforms/posix-h4/btstack-config.h new file mode 100644 index 000000000..0448f2826 --- /dev/null +++ b/platforms/posix-h4/btstack-config.h @@ -0,0 +1,24 @@ +// config.h created by configure for BTstack Tue Jun 4 23:10:20 CEST 2013 + +#ifndef __BTSTACK_CONFIG +#define __BTSTACK_CONFIG + +#define HAVE_TRANSPORT_USB +#define HAVE_BLE +#define USE_POSIX_RUN_LOOP +#define HAVE_SDP +#define HAVE_RFCOMM +#define REMOTE_DEVICE_DB remote_device_db_iphone +#define HAVE_SO_NOSIGPIPE +#define HAVE_TIME +#define HAVE_MALLOC +#define HAVE_BZERO +#define SDP_DES_DUMP +#define ENABLE_LOG_INFO +#define ENABLE_LOG_ERROR +#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof benep heade, avoid memcpy +#define HCI_ACL_PAYLOAD_SIZE (1691 + 4) +#define HAVE_HCI_DUMP +#define SDP_DES_DUMP + +#endif diff --git a/platforms/posix-h4/main.c b/platforms/posix-h4/main.c new file mode 100644 index 000000000..6eb1da79b --- /dev/null +++ b/platforms/posix-h4/main.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2014 BlueKitchen GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. Any redistribution, use, or modification is done solely for + * personal benefit and not for any commercial purpose or for + * monetary gain. + * + * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Please inquire about commercial licensing options at + * contact@bluekitchen-gmbh.com + * + */ + +// ***************************************************************************** +// +// minimal setup for HCI code +// +// ***************************************************************************** + +#include +#include +#include +#include +#include + +#include "btstack-config.h" + +#include + +#include "debug.h" +#include "btstack_memory.h" +#include "hci.h" +#include "hci_dump.h" +#include "stdin_support.h" + +int btstack_main(int argc, const char * argv[]); + +static hci_uart_config_t hci_uart_config_generic = { + NULL, + 115200, +}; + +static void sigint_handler(int param){ + +#ifndef _WIN32 + // reset anyway + btstack_stdin_reset(); +#endif + + log_info(" <= SIGINT received, shutting down..\n"); + hci_power_control(HCI_POWER_OFF); + hci_close(); + log_info("Good bye, see you.\n"); + exit(0); +} + +static int led_state = 0; +void hal_led_toggle(void){ + led_state = 1 - led_state; + printf("LED State %u\n", led_state); +} + +int main(int argc, const char * argv[]){ + + /// GET STARTED with BTstack /// + btstack_memory_init(); + run_loop_init(RUN_LOOP_POSIX); + + // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT + hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); + + // pick serial port + hci_uart_config_generic.device_name = "/dev/tty.usbmodem1413"; + + // init HCI + hci_transport_t * transport = hci_transport_h4_instance(); + remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_fs; + + hci_init(transport, (void*) &hci_uart_config_generic, NULL, remote_db); + + // handle CTRL-c + signal(SIGINT, sigint_handler); + + // setup app + btstack_main(argc, argv); + + // go + run_loop_execute(); + + return 0; +}