From a2a6b20caeacc678e197f5ef3fb9f3dfe740e402 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 30 Jul 2015 11:56:29 +0200 Subject: [PATCH 1/5] add GAP Characteristic UUIDs --- ble/att.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ble/att.h b/ble/att.h index 9eb58f891..5a788ff38 100644 --- a/ble/att.h +++ b/ble/att.h @@ -149,8 +149,12 @@ extern "C" { #define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION 1 #define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION 2 +// GAP Service and Characteristics #define GAP_SERVICE_UUID 0x1800 #define GAP_DEVICE_NAME_UUID 0x2a00 +#define GAP_APPEARANCE_UUID 0x2a01 +#define GAP_PERIPHERAL_PRIVACY_FLAG 0x2a02 +#define GAP_RECONNECTION_ADDRESS_UUID 0x2a03 typedef struct att_connection { From 2c1ed46591c22746ca30915ab2f41c5de7fef10d Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 30 Jul 2015 15:24:32 +0200 Subject: [PATCH 2/5] handle gap-conn-acp-bv-2 --- test/pts/ble_central_test.c | 54 ++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index cbf028414..974b53062 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -67,10 +67,14 @@ // test profile #include "profile.h" +// IXIT +#define PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF + typedef enum { CENTRAL_IDLE, CENTRAL_W4_NAME_QUERY_COMPLETE, CENTRAL_W4_NAME_VALUE, + CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE, } central_state_t; typedef struct advertising_report { @@ -104,10 +108,14 @@ static int ui_digits_for_passkey = 0; static uint16_t handle = 0; static bd_addr_t tester_address = {0x00, 0x1B, 0xDC, 0x07, 0x32, 0xef}; static int tester_address_type = 0; -uint16_t gc_id; +static int reconnection_address_set = 0; +static bd_addr_t non_resolvabe_address = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33}; +static bd_addr_t private_address; +static uint16_t gc_id; static central_state_t central_state = CENTRAL_IDLE; static le_characteristic_t gap_name_characteristic; +static le_characteristic_t gap_reconnection_address_characteristic; static void show_usage(); static void fill_advertising_report_from_packet(advertising_report_t * report, uint8_t *packet); @@ -296,6 +304,8 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, void handle_gatt_client_event(le_event_t * event){ le_service_t service; le_characteristic_value_event_t * value; + uint8_t address_type; + bd_addr_t flipped_address; switch(event->type){ case GATT_SERVICE_QUERY_RESULT: // service = ((le_service_event_t *) event)->service; @@ -321,6 +331,13 @@ void handle_gatt_client_event(le_event_t * event){ central_state = CENTRAL_W4_NAME_VALUE; gatt_client_read_value_of_characteristic(gc_id, handle, &gap_name_characteristic); break; + case CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE: + central_state = CENTRAL_IDLE; + hci_le_advertisement_address(&address_type, private_address); + printf("Private address: %s\n", bd_addr_to_str(private_address)); + bt_flip_addr(flipped_address, private_address); + gatt_client_write_value_of_characteristic(gc_id, handle, gap_reconnection_address_characteristic.value_handle, 6, flipped_address); + reconnection_address_set = 1; default: break; } @@ -329,6 +346,11 @@ void handle_gatt_client_event(le_event_t * event){ switch (central_state) { case CENTRAL_W4_NAME_QUERY_COMPLETE: gap_name_characteristic = ((le_characteristic_event_t *) 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; + printf("GAP Reconnection Address Characteristic found, value handle: 0x04%x\n", gap_reconnection_address_characteristic.value_handle); break; default: break; @@ -356,9 +378,11 @@ void show_usage(void){ printf("---\n"); printf("c/C - connectable off\n"); printf("---\n"); + printf("1 - enable privacy using random non-resolvable private address\n"); printf("s/S - passive/active scanning\n"); printf("a - enable Advertisements\n"); - printf("n - query GATT Device Name\n"); + printf("n - query GAP Device Name\n"); + printf("o - set GAP Reconnection Address\n"); printf("t - terminate connection, stop connecting\n"); printf("p - auto connect to PTS\n"); printf("P - direct connect to PTS\n"); @@ -388,6 +412,12 @@ int stdin_process(struct data_source *ds){ } switch (buffer){ + case '1': + printf("Enabling non-resolvable private address\n"); + gap_random_address_set_mode(GAP_RANDOM_ADDRESS_NON_RESOLVABLE); + update_advertisment_params(); + gap_privacy = 1; + break; case 'a': hci_send_cmd(&hci_le_set_advertise_enable, 1); break; @@ -401,13 +431,31 @@ int stdin_process(struct data_source *ds){ break; case 'n': central_state = CENTRAL_W4_NAME_QUERY_COMPLETE; - gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, 0x2a00); + gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_DEVICE_NAME_UUID); + break; + case 'o': + central_state = CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE; + gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_RECONNECTION_ADDRESS_UUID); break; case 'p': +#ifdef PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF + if (reconnection_address_set){ + res = gap_auto_connection_start(1, private_address); + printf("Auto Connection Establishment to type %u, addr %s -> %x\n", 1, bd_addr_to_str(private_address), res); + break; + } +#endif res = gap_auto_connection_start(tester_address_type, tester_address); printf("Auto Connection Establishment to type %u, addr %s -> %x\n", tester_address_type, bd_addr_to_str(tester_address), res); break; case 'P': +#ifdef PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF + if (reconnection_address_set){ + printf("Direct Connection Establishment to type %u, addr %s\n", 1, bd_addr_to_str(non_resolvabe_address)); + le_central_connect(non_resolvabe_address, 1); + + } +#endif printf("Direct Connection Establishment to type %u, addr %s\n", tester_address_type, bd_addr_to_str(tester_address)); le_central_connect(tester_address, tester_address_type); break; From b1640c53997b7c5a78be604f9f576c7396ef64ab Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 30 Jul 2015 16:00:52 +0200 Subject: [PATCH 3/5] handle gap-conn-gcep-bv-4 --- test/pts/ble_central_test.c | 112 +++++++++++++++++------------------- 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 974b53062..125fd7527 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -59,6 +59,7 @@ #include "sm.h" #include "att.h" +#include "att_server.h" #include "gap_le.h" #include "le_device_db.h" #include "stdin_support.h" @@ -67,7 +68,7 @@ // test profile #include "profile.h" -// IXIT +// Non standard IXIT #define PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF typedef enum { @@ -75,6 +76,7 @@ typedef enum { CENTRAL_W4_NAME_QUERY_COMPLETE, CENTRAL_W4_NAME_VALUE, CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE, + CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE, } central_state_t; typedef struct advertising_report { @@ -90,7 +92,7 @@ typedef struct advertising_report { 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; -static int gap_bondable = 0; +/* static */ int gap_bondable = 0; static char gap_device_name[20]; static int gap_connectable = 0; @@ -106,21 +108,21 @@ static int ui_passkey = 0; static int ui_digits_for_passkey = 0; static uint16_t handle = 0; -static bd_addr_t tester_address = {0x00, 0x1B, 0xDC, 0x07, 0x32, 0xef}; -static int tester_address_type = 0; -static int reconnection_address_set = 0; -static bd_addr_t non_resolvabe_address = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33}; -static bd_addr_t private_address; static uint16_t gc_id; +static bd_addr_t public_pts_address = {0x00, 0x1B, 0xDC, 0x07, 0x32, 0xef}; +static int public_pts_address_type = 0; +static bd_addr_t current_pts_address; +static int current_pts_address_type; +static int reconnection_address_set = 0; +static bd_addr_t our_private_address; + static central_state_t central_state = CENTRAL_IDLE; static le_characteristic_t gap_name_characteristic; static le_characteristic_t gap_reconnection_address_characteristic; +static le_characteristic_t gap_peripheral_privacy_flag_characteristic; static void show_usage(); -static void fill_advertising_report_from_packet(advertising_report_t * report, uint8_t *packet); -static void dump_advertising_report(advertising_report_t * e); - /// static void printUUID(uint8_t * uuid128, uint16_t uuid16){ @@ -131,31 +133,19 @@ static void printUUID(uint8_t * uuid128, uint16_t uuid16){ } } -static void dump_characteristic(le_characteristic_t * characteristic){ +void dump_characteristic(le_characteristic_t * characteristic){ printf(" * characteristic: [0x%04x-0x%04x-0x%04x], properties 0x%02x, uuid ", characteristic->start_handle, characteristic->value_handle, characteristic->end_handle, characteristic->properties); printUUID(characteristic->uuid128, characteristic->uuid16); printf("\n"); } -static void dump_service(le_service_t * service){ +void dump_service(le_service_t * service){ printf(" * service: [0x%04x-0x%04x], uuid ", service->start_group_handle, service->end_group_handle); printUUID(service->uuid128, service->uuid16); printf("\n"); } -static void fill_advertising_report_from_packet(advertising_report_t * report, uint8_t *packet){ - int pos = 2; - report->event_type = packet[pos++]; // 2 - report->address_type = packet[pos++]; // 3 - bt_flip_addr(report->address, &packet[pos]); // 4 - pos += 6; - report->rssi = packet[pos++]; // 10 - report->length = packet[pos++]; // 11 - report->data = &packet[pos]; // 12 - pos += report->length; -} - const char * ad_event_types[] = { "Connectable undirected advertising", "Connectable directed advertising", @@ -168,7 +158,7 @@ static void handle_advertising_event(uint8_t * packet, int size){ // filter PTS bd_addr_t addr; bt_flip_addr(addr, &packet[4]); - if (memcmp(addr, tester_address, 6)) return; + if (memcmp(addr, public_pts_address, 6)) return; printf("Advertisement: %s, ", ad_event_types[packet[2]]); int adv_size = packet[11]; uint8_t * adv_data = &packet[12]; @@ -177,7 +167,7 @@ static void handle_advertising_event(uint8_t * packet, int size){ ad_context_t context; for (ad_iterator_init(&context, adv_size, adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){ uint8_t data_type = ad_iterator_get_data_type(&context); - uint8_t size = ad_iterator_get_data_len(&context); + // uint8_t size = ad_iterator_get_data_len(&context); uint8_t * data = ad_iterator_get_data(&context); switch (data_type){ case 1: // AD_FLAGS @@ -212,11 +202,11 @@ static void update_advertisment_params(void){ case 0: case 2: case 3: - gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, &null_addr, 0x07, 0x00); + gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); break; case 1: case 4: - gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, tester_address_type, &tester_address, 0x07, 0x00); + gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, public_pts_address_type, public_pts_address, 0x07, 0x00); break; } } @@ -226,8 +216,6 @@ static void gap_run(void){ } void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ - advertising_report_t report; - switch (packet_type) { case HCI_EVENT_PACKET: @@ -289,8 +277,6 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, case GAP_LE_ADVERTISING_REPORT: handle_advertising_event(packet, size); - // fill_advertising_report_from_packet(&report, packet); - // dump_advertising_report(&report); break; default: break; @@ -299,12 +285,15 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, gap_run(); } - +void use_public_pts_address(void){ + memcpy(current_pts_address, public_pts_address, 6); + current_pts_address_type = public_pts_address_type; +} void handle_gatt_client_event(le_event_t * event){ - le_service_t service; le_characteristic_value_event_t * value; uint8_t address_type; + uint8_t privacy_flag = 0; bd_addr_t flipped_address; switch(event->type){ case GATT_SERVICE_QUERY_RESULT: @@ -333,11 +322,22 @@ void handle_gatt_client_event(le_event_t * event){ break; case CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE: central_state = CENTRAL_IDLE; - hci_le_advertisement_address(&address_type, private_address); - printf("Private address: %s\n", bd_addr_to_str(private_address)); - bt_flip_addr(flipped_address, private_address); + hci_le_advertisement_address(&address_type, our_private_address); + printf("Our private address: %s\n", bd_addr_to_str(our_private_address)); + bt_flip_addr(flipped_address, our_private_address); gatt_client_write_value_of_characteristic(gc_id, handle, gap_reconnection_address_characteristic.value_handle, 6, flipped_address); reconnection_address_set = 1; +#ifdef PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF + memcpy(current_pts_address, our_private_address, 6); + current_pts_address_type = 1; +#endif + break; + case CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE: + central_state = CENTRAL_IDLE; + gatt_client_write_value_of_characteristic(gc_id, handle, gap_peripheral_privacy_flag_characteristic.value_handle, 1, &privacy_flag); + use_public_pts_address(); + printf("Peripheral Privacy Flag set to FALSE, connecting to public PTS address again\n"); + break; default: break; } @@ -352,6 +352,9 @@ void handle_gatt_client_event(le_event_t * event){ gap_reconnection_address_characteristic = ((le_characteristic_event_t *) 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; + printf("GAP Peripheral Privacy Flag Characteristic found, value handle: 0x04%x\n", gap_peripheral_privacy_flag_characteristic.value_handle); default: break; } @@ -371,6 +374,7 @@ void show_usage(void){ printf("GAP: connectable %u\n", gap_connectable); printf("SM: %s, MITM protection %u, OOB data %u, key range [%u..16]\n", sm_io_capabilities, sm_mitm_protection, sm_have_oob_data, sm_min_key_size); + printf("PTS: addr type %u, addr %s\n", current_pts_address_type, current_pts_address); printf("Privacy %u\n", gap_privacy); printf("Device name: %s\n", gap_device_name); printf("Value Handle: %x\n", value_handle); @@ -379,6 +383,7 @@ void show_usage(void){ printf("c/C - connectable off\n"); printf("---\n"); printf("1 - enable privacy using random non-resolvable private address\n"); + printf("2 - clear Peripheral Privacy Flag on PTS\n"); printf("s/S - passive/active scanning\n"); printf("a - enable Advertisements\n"); printf("n - query GAP Device Name\n"); @@ -433,31 +438,21 @@ int stdin_process(struct data_source *ds){ central_state = CENTRAL_W4_NAME_QUERY_COMPLETE; gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_DEVICE_NAME_UUID); break; + case '2': + central_state = CENTRAL_W4_PERIPHERAL_PRIVACY_FLAG_QUERY_COMPLETE; + gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_PERIPHERAL_PRIVACY_FLAG); + break; case 'o': central_state = CENTRAL_W4_RECONNECTION_ADDRESS_QUERY_COMPLETE; gatt_client_discover_characteristics_for_handle_range_by_uuid16(gc_id, handle, 1, 0xffff, GAP_RECONNECTION_ADDRESS_UUID); break; case 'p': -#ifdef PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF - if (reconnection_address_set){ - res = gap_auto_connection_start(1, private_address); - printf("Auto Connection Establishment to type %u, addr %s -> %x\n", 1, bd_addr_to_str(private_address), res); - break; - } -#endif - res = gap_auto_connection_start(tester_address_type, tester_address); - printf("Auto Connection Establishment to type %u, addr %s -> %x\n", tester_address_type, bd_addr_to_str(tester_address), res); + res = gap_auto_connection_start(current_pts_address_type, current_pts_address); + printf("Auto Connection Establishment to type %u, addr %s -> %x\n", current_pts_address_type, bd_addr_to_str(current_pts_address), res); break; case 'P': -#ifdef PTS_USES_RECONNECTION_ADDRESS_FOR_ITSELF - if (reconnection_address_set){ - printf("Direct Connection Establishment to type %u, addr %s\n", 1, bd_addr_to_str(non_resolvabe_address)); - le_central_connect(non_resolvabe_address, 1); - - } -#endif - printf("Direct Connection Establishment to type %u, addr %s\n", tester_address_type, bd_addr_to_str(tester_address)); - le_central_connect(tester_address, tester_address_type); + le_central_connect(current_pts_address, current_pts_address_type); + printf("Direct Connection Establishment to type %u, addr %s\n", current_pts_address_type, bd_addr_to_str(current_pts_address)); break; case 's': if (scanning_active){ @@ -566,13 +561,12 @@ int btstack_main(int argc, const char * argv[]){ // Setup LE Device DB le_device_db_init(); - // - // gap_random_address_set_update_period(300000); - // gap_random_address_set_mode(GAP_RANDOM_ADDRESS_RESOLVABLE); - // set adv params update_advertisment_params(); + memcpy(current_pts_address, public_pts_address, 6); + current_pts_address_type = public_pts_address_type; + // allow foor terminal input btstack_stdin_setup(stdin_process); From 08f532b144e85693f8580024477245c0d3adf723 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 30 Jul 2015 16:43:38 +0200 Subject: [PATCH 4/5] add comment at sm state 50 --- src/hci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hci.h b/src/hci.h index 8eab15d41..457c9baaf 100644 --- a/src/hci.h +++ b/src/hci.h @@ -418,6 +418,7 @@ typedef enum { SM_RESPONDER_PH2_SEND_LTK_REPLY, // INITITIATOR ROLE + // state = 50 SM_INITIATOR_CONNECTED, SM_INITIATOR_PH0_HAS_LTK, SM_INITIATOR_PH0_SEND_START_ENCRYPTION, From f6b4c96ab9c72d5e3102e95e251d5cade55a08d8 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 30 Jul 2015 16:43:53 +0200 Subject: [PATCH 5/5] start bonding in central mode --- test/pts/ble_central_test.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 125fd7527..a8803045a 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -268,10 +268,20 @@ void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, printf("\nGAP Bonding %s (%u): Display cancel\n", bd_addr_to_str(peer_address), peer_addr_type); break; - case SM_AUTHORIZATION_REQUEST: { + case SM_JUST_WORKS_REQUEST: + { // auto-authorize connection if requested sm_event_t * event = (sm_event_t *) packet; - sm_authorization_grant(event->addr_type, event->address); + sm_just_works_confirm(current_pts_address_type, current_pts_address); + printf("Just Works request confirmed\n"); + break; + } + break; + case SM_AUTHORIZATION_REQUEST: + { + // auto-authorize connection if requested + sm_event_t * event = (sm_event_t *) packet; + sm_authorization_grant(current_pts_address_type, current_pts_address); break; } @@ -386,6 +396,7 @@ void show_usage(void){ printf("2 - clear Peripheral Privacy Flag on PTS\n"); printf("s/S - passive/active scanning\n"); printf("a - enable Advertisements\n"); + printf("b - start bonding\n"); printf("n - query GAP Device Name\n"); printf("o - set GAP Reconnection Address\n"); printf("t - terminate connection, stop connecting\n"); @@ -426,6 +437,9 @@ int stdin_process(struct data_source *ds){ case 'a': hci_send_cmd(&hci_le_set_advertise_enable, 1); break; + case 'b': + sm_request_authorization(current_pts_address_type, current_pts_address); + break; case 'c': gap_connectable = 1; update_advertisment_params(); @@ -546,7 +560,9 @@ int btstack_main(int argc, const char * argv[]){ sm_register_oob_data_callback(get_oob_data_callback); sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT); sm_io_capabilities = "IO_CAPABILITY_NO_INPUT_NO_OUTPUT"; - sm_set_authentication_requirements(0); + // sm_set_authentication_requirements(SM_AUTHREQ_NO_BONDING); + sm_set_authentication_requirements(SM_AUTHREQ_BONDING); + sm_set_encryption_key_size_range(sm_min_key_size, 16); sm_test_set_irk(test_irk);