10f7fd6c1SMilanka Ringwald #include <stdint.h> 20f7fd6c1SMilanka Ringwald #include <stdio.h> 30f7fd6c1SMilanka Ringwald #include <string.h> 40f7fd6c1SMilanka Ringwald 5af770404SMilanka Ringwald #include "btstack_debug.h" 67e693ad3SMilanka Ringwald #include "bluetooth_gatt.h" 70f7fd6c1SMilanka Ringwald #include "mock_gatt_client.h" 80f7fd6c1SMilanka Ringwald 90f7fd6c1SMilanka Ringwald #include "CppUTest/TestHarness.h" 100f7fd6c1SMilanka Ringwald #include "CppUTestExt/MockSupport.h" 110f7fd6c1SMilanka Ringwald 12af770404SMilanka Ringwald static enum { 13af770404SMilanka Ringwald MOCK_QUERY_IDLE = 0, 14*7dbac955SMatthias Ringwald MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID, 15*7dbac955SMatthias Ringwald MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID, 16*7dbac955SMatthias Ringwald MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS, 1776cdba3eSMilanka Ringwald MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS, 1876cdba3eSMilanka Ringwald MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION, 197e693ad3SMilanka Ringwald MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE, 207e693ad3SMilanka Ringwald MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE 21af770404SMilanka Ringwald } mock_gatt_client_state; 22af770404SMilanka Ringwald 2376cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_att_handle_generator; 2476cdba3eSMilanka Ringwald 25af770404SMilanka Ringwald static uint8_t mock_gatt_client_att_error; 26*7dbac955SMatthias Ringwald static uint8_t mock_gatt_client_uuid128[16]; 2776cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_value_handle; 2876cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_start_handle; 2976cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_end_handle; 3076cdba3eSMilanka Ringwald 31af770404SMilanka Ringwald static gatt_client_t gatt_client; 320f7fd6c1SMilanka Ringwald 337da2c1baSMilanka Ringwald static btstack_linked_list_t mock_gatt_client_services; 347da2c1baSMilanka Ringwald 357da2c1baSMilanka Ringwald static mock_gatt_client_service_t * mock_gatt_client_last_service; 367da2c1baSMilanka Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic; 377da2c1baSMilanka Ringwald 38ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_services; 39ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristics; 40ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristic_descriptors; 417e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_con_handle; 427e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_value_handle; 43ec1a0daeSMilanka Ringwald 4486d0910fSMilanka Ringwald 45af770404SMilanka Ringwald /** 46af770404SMilanka Ringwald * copied from gatt_client.c - START 47af770404SMilanka Ringwald */ 480f7fd6c1SMilanka Ringwald void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){ 490f7fd6c1SMilanka Ringwald service->start_group_handle = little_endian_read_16(packet, offset); 500f7fd6c1SMilanka Ringwald service->end_group_handle = little_endian_read_16(packet, offset + 2); 510f7fd6c1SMilanka Ringwald reverse_128(&packet[offset + 4], service->uuid128); 520f7fd6c1SMilanka Ringwald if (uuid_has_bluetooth_prefix(service->uuid128)){ 530f7fd6c1SMilanka Ringwald service->uuid16 = big_endian_read_32(service->uuid128, 0); 540f7fd6c1SMilanka Ringwald } else { 550f7fd6c1SMilanka Ringwald service->uuid16 = 0; 560f7fd6c1SMilanka Ringwald } 570f7fd6c1SMilanka Ringwald } 580f7fd6c1SMilanka Ringwald 590f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){ 600f7fd6c1SMilanka Ringwald characteristic->start_handle = little_endian_read_16(packet, offset); 610f7fd6c1SMilanka Ringwald characteristic->value_handle = little_endian_read_16(packet, offset + 2); 620f7fd6c1SMilanka Ringwald characteristic->end_handle = little_endian_read_16(packet, offset + 4); 630f7fd6c1SMilanka Ringwald characteristic->properties = little_endian_read_16(packet, offset + 6); 640f7fd6c1SMilanka Ringwald reverse_128(&packet[offset+8], characteristic->uuid128); 650f7fd6c1SMilanka Ringwald if (uuid_has_bluetooth_prefix(characteristic->uuid128)){ 660f7fd6c1SMilanka Ringwald characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0); 670f7fd6c1SMilanka Ringwald } else { 680f7fd6c1SMilanka Ringwald characteristic->uuid16 = 0; 690f7fd6c1SMilanka Ringwald } 700f7fd6c1SMilanka Ringwald } 710f7fd6c1SMilanka Ringwald 720f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){ 730f7fd6c1SMilanka Ringwald descriptor->handle = little_endian_read_16(packet, offset); 740f7fd6c1SMilanka Ringwald reverse_128(&packet[offset+2], descriptor->uuid128); 750f7fd6c1SMilanka Ringwald if (uuid_has_bluetooth_prefix(descriptor->uuid128)){ 760f7fd6c1SMilanka Ringwald descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0); 770f7fd6c1SMilanka Ringwald } else { 780f7fd6c1SMilanka Ringwald descriptor->uuid16 = 0; 790f7fd6c1SMilanka Ringwald } 800f7fd6c1SMilanka Ringwald } 810f7fd6c1SMilanka Ringwald 827e693ad3SMilanka Ringwald static void emit_event(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){ 83af770404SMilanka Ringwald if (!callback) return; 847e693ad3SMilanka Ringwald if (mock_gatt_client_wrong_con_handle){ 857e693ad3SMilanka Ringwald little_endian_store_16(packet, 2, 0xFFFF); 867e693ad3SMilanka Ringwald } 87af770404SMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, packet, size); 880f7fd6c1SMilanka Ringwald } 890f7fd6c1SMilanka Ringwald 90af770404SMilanka Ringwald static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){ 91af770404SMilanka Ringwald // @format H1 92af770404SMilanka Ringwald uint8_t packet[5]; 93af770404SMilanka Ringwald packet[0] = GATT_EVENT_QUERY_COMPLETE; 94af770404SMilanka Ringwald packet[1] = 3; 95af770404SMilanka Ringwald little_endian_store_16(packet, 2, gatt_client->con_handle); 96af770404SMilanka Ringwald packet[4] = att_status; 977e693ad3SMilanka Ringwald emit_event(gatt_client->callback, packet, sizeof(packet)); 980f7fd6c1SMilanka Ringwald } 990f7fd6c1SMilanka Ringwald 1007da2c1baSMilanka Ringwald static void emit_gatt_service_query_result_event(gatt_client_t * gatt_client, uint16_t start_group_handle, uint16_t end_group_handle, const uint8_t * uuid128){ 1017da2c1baSMilanka Ringwald // @format HX 1027da2c1baSMilanka Ringwald uint8_t packet[24]; 1037da2c1baSMilanka Ringwald packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT; 1047da2c1baSMilanka Ringwald packet[1] = sizeof(packet) - 2u; 1057da2c1baSMilanka Ringwald little_endian_store_16(packet, 2, gatt_client->con_handle); 1067da2c1baSMilanka Ringwald /// 1077da2c1baSMilanka Ringwald little_endian_store_16(packet, 4, start_group_handle); 1087da2c1baSMilanka Ringwald little_endian_store_16(packet, 6, end_group_handle); 1097da2c1baSMilanka Ringwald reverse_128(uuid128, &packet[8]); 1107e693ad3SMilanka Ringwald emit_event(gatt_client->callback, packet, sizeof(packet)); 1117da2c1baSMilanka Ringwald } 1127da2c1baSMilanka Ringwald 1137da2c1baSMilanka Ringwald static void emit_gatt_characteristic_query_result_event(gatt_client_t * gatt_client, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle, 1147da2c1baSMilanka Ringwald uint16_t properties, const uint8_t * uuid128){ 1157da2c1baSMilanka Ringwald // @format HY 1167da2c1baSMilanka Ringwald uint8_t packet[28]; 1177da2c1baSMilanka Ringwald packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT; 1187da2c1baSMilanka Ringwald packet[1] = sizeof(packet) - 2u; 1197da2c1baSMilanka Ringwald little_endian_store_16(packet, 2, gatt_client->con_handle); 1207da2c1baSMilanka Ringwald /// 1217da2c1baSMilanka Ringwald little_endian_store_16(packet, 4, start_handle); 1227da2c1baSMilanka Ringwald little_endian_store_16(packet, 6, value_handle); 1237da2c1baSMilanka Ringwald little_endian_store_16(packet, 8, end_handle); 1247da2c1baSMilanka Ringwald little_endian_store_16(packet, 10, properties); 1257da2c1baSMilanka Ringwald reverse_128(uuid128, &packet[12]); 1267e693ad3SMilanka Ringwald emit_event(gatt_client->callback, packet, sizeof(packet)); 1277da2c1baSMilanka Ringwald } 1287da2c1baSMilanka Ringwald 12976cdba3eSMilanka Ringwald static void emit_gatt_all_characteristic_descriptors_result_event( 13076cdba3eSMilanka Ringwald gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){ 13176cdba3eSMilanka Ringwald // @format HZ 13276cdba3eSMilanka Ringwald uint8_t packet[22]; 13376cdba3eSMilanka Ringwald packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT; 13476cdba3eSMilanka Ringwald packet[1] = sizeof(packet) - 2u; 13576cdba3eSMilanka Ringwald little_endian_store_16(packet, 2, gatt_client->con_handle); 13676cdba3eSMilanka Ringwald /// 13776cdba3eSMilanka Ringwald little_endian_store_16(packet, 4, descriptor_handle); 13876cdba3eSMilanka Ringwald reverse_128(uuid128, &packet[6]); 1397e693ad3SMilanka Ringwald emit_event(gatt_client->callback, packet, sizeof(packet)); 14076cdba3eSMilanka Ringwald } 14176cdba3eSMilanka Ringwald 1427e693ad3SMilanka Ringwald static uint8_t event_packet[255]; 14376cdba3eSMilanka Ringwald static uint8_t * setup_characteristic_value_packet(uint8_t type, hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t * value, uint16_t length){ 14476cdba3eSMilanka Ringwald // before the value inside the ATT PDU 1457e693ad3SMilanka Ringwald event_packet[0] = type; 1467e693ad3SMilanka Ringwald event_packet[1] = 6 + length; 1477e693ad3SMilanka Ringwald little_endian_store_16(event_packet, 2, con_handle); 1487e693ad3SMilanka Ringwald little_endian_store_16(event_packet, 4, attribute_handle); 1497e693ad3SMilanka Ringwald little_endian_store_16(event_packet, 6, length); 1507e693ad3SMilanka Ringwald memcpy(&event_packet[8], value, length); 1517e693ad3SMilanka Ringwald return &event_packet[0]; 15276cdba3eSMilanka Ringwald } 15376cdba3eSMilanka Ringwald 154*7dbac955SMatthias Ringwald void mock_gatt_client_send_notification_with_handle(mock_gatt_client_characteristic_t * characteristic, uint16_t value_handle, const uint8_t * value_buffer, uint16_t value_len){ 1557e693ad3SMilanka Ringwald btstack_assert(characteristic != NULL); 1567e693ad3SMilanka Ringwald btstack_assert(characteristic->notification != NULL); 1577e693ad3SMilanka Ringwald btstack_assert(characteristic->notification->callback != NULL); 158*7dbac955SMatthias Ringwald uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len); 1597e693ad3SMilanka Ringwald emit_event(characteristic->notification->callback, packet, 2 + packet[1]); 1607e693ad3SMilanka Ringwald } 1617e693ad3SMilanka Ringwald 162*7dbac955SMatthias Ringwald void mock_gatt_client_send_notification(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){ 1637e693ad3SMilanka Ringwald mock_gatt_client_send_notification_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len); 1647e693ad3SMilanka Ringwald } 1657e693ad3SMilanka Ringwald 166*7dbac955SMatthias Ringwald void mock_gatt_client_send_indication_with_handle(mock_gatt_client_characteristic_t * characteristic, uint16_t value_handle, const uint8_t * value_buffer, uint16_t value_len){ 167*7dbac955SMatthias Ringwald btstack_assert(characteristic != NULL); 168*7dbac955SMatthias Ringwald btstack_assert(characteristic->notification != NULL); 169*7dbac955SMatthias Ringwald btstack_assert(characteristic->notification->callback != NULL); 170*7dbac955SMatthias Ringwald uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len); 171*7dbac955SMatthias Ringwald emit_event(characteristic->notification->callback, packet, 2 + packet[1]); 172*7dbac955SMatthias Ringwald } 173*7dbac955SMatthias Ringwald 174*7dbac955SMatthias Ringwald void mock_gatt_client_send_indication(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){ 175*7dbac955SMatthias Ringwald mock_gatt_client_send_indication_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len); 176*7dbac955SMatthias Ringwald } 177*7dbac955SMatthias Ringwald 1787e693ad3SMilanka Ringwald static void mock_gatt_client_send_characteristic_value(gatt_client_t * gatt_client, mock_gatt_client_characteristic_t * characteristic){ 1797e693ad3SMilanka Ringwald uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, gatt_client->con_handle, characteristic->value_handle, characteristic->value_buffer, characteristic->value_len); 1807e693ad3SMilanka Ringwald emit_event(gatt_client->callback, packet, 2 + packet[1]); 18176cdba3eSMilanka Ringwald } 18276cdba3eSMilanka Ringwald 183af770404SMilanka Ringwald /** 184af770404SMilanka Ringwald * copied from gatt_client.c - END 185af770404SMilanka Ringwald */ 1860f7fd6c1SMilanka Ringwald 187*7dbac955SMatthias Ringwald 188*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){ 189*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t service_it; 190*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t characteristic_it; 191*7dbac955SMatthias Ringwald 192*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 193*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 194*7dbac955SMatthias Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 195*7dbac955SMatthias Ringwald 196*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 197*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 198*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 199*7dbac955SMatthias Ringwald if (characteristic->value_handle != value_handle) continue; 200*7dbac955SMatthias Ringwald return characteristic; 201*7dbac955SMatthias Ringwald } 202*7dbac955SMatthias Ringwald } 203*7dbac955SMatthias Ringwald return NULL; 204*7dbac955SMatthias Ringwald } 205*7dbac955SMatthias Ringwald 206*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){ 207*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t service_it; 208*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t characteristic_it; 209*7dbac955SMatthias Ringwald 210*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 211*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 212*7dbac955SMatthias Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 213*7dbac955SMatthias Ringwald 214*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 215*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 216*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 217*7dbac955SMatthias Ringwald 218*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t desc_it; 219*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 220*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&desc_it)){ 221*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 222*7dbac955SMatthias Ringwald if (desc->handle != handle) continue; 223*7dbac955SMatthias Ringwald return desc; 224*7dbac955SMatthias Ringwald } 225*7dbac955SMatthias Ringwald } 226*7dbac955SMatthias Ringwald } 227*7dbac955SMatthias Ringwald return NULL; 228*7dbac955SMatthias Ringwald } 229*7dbac955SMatthias Ringwald 230*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){ 231*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID; 232*7dbac955SMatthias Ringwald uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16); 233*7dbac955SMatthias Ringwald gatt_client.callback = callback; 234*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 235*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 236*7dbac955SMatthias Ringwald } 237*7dbac955SMatthias Ringwald 238*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, const uint8_t * uuid128){ 239*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID; 240*7dbac955SMatthias Ringwald memcpy(mock_gatt_client_uuid128, uuid128, 16); 241*7dbac955SMatthias Ringwald gatt_client.callback = callback; 242*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 243*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 244*7dbac955SMatthias Ringwald } 245*7dbac955SMatthias Ringwald 246*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_characteristics_for_handle_range_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){ 247*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID; 248*7dbac955SMatthias Ringwald uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16); 249*7dbac955SMatthias Ringwald mock_gatt_client_start_handle = start_handle; 250*7dbac955SMatthias Ringwald mock_gatt_client_end_handle = end_handle; 251*7dbac955SMatthias Ringwald 252*7dbac955SMatthias Ringwald gatt_client.callback = callback; 253*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 254*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 255*7dbac955SMatthias Ringwald } 256*7dbac955SMatthias Ringwald 257*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service){ 258*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS; 259*7dbac955SMatthias Ringwald mock_gatt_client_start_handle = service->start_group_handle; 260*7dbac955SMatthias Ringwald mock_gatt_client_end_handle = service->end_group_handle; 261*7dbac955SMatthias Ringwald gatt_client.callback = callback; 262*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 263*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 264*7dbac955SMatthias Ringwald } 265*7dbac955SMatthias Ringwald 266*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){ 267*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS; 268*7dbac955SMatthias Ringwald mock_gatt_client_value_handle = characteristic->value_handle; 269*7dbac955SMatthias Ringwald 270*7dbac955SMatthias Ringwald gatt_client.callback = callback; 271*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 272*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 273*7dbac955SMatthias Ringwald } 274*7dbac955SMatthias Ringwald 275*7dbac955SMatthias Ringwald void gatt_client_listen_for_characteristic_value_updates(gatt_client_notification_t * notification, btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){ 276*7dbac955SMatthias Ringwald btstack_assert(notification != NULL); 277*7dbac955SMatthias Ringwald btstack_assert(&callback != NULL); 278*7dbac955SMatthias Ringwald 279*7dbac955SMatthias Ringwald notification->callback = callback; 280*7dbac955SMatthias Ringwald notification->con_handle = con_handle; 281*7dbac955SMatthias Ringwald 282*7dbac955SMatthias Ringwald 283*7dbac955SMatthias Ringwald if (characteristic == NULL){ 284*7dbac955SMatthias Ringwald // 'all characteristics': not used yet 285*7dbac955SMatthias Ringwald btstack_assert(false); 286*7dbac955SMatthias Ringwald } else { 287*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle); 288*7dbac955SMatthias Ringwald btstack_assert(mock_characteristic != NULL); 289*7dbac955SMatthias Ringwald 290*7dbac955SMatthias Ringwald notification->attribute_handle = characteristic->value_handle; 291*7dbac955SMatthias Ringwald mock_characteristic->notification = notification; 292*7dbac955SMatthias Ringwald } 293*7dbac955SMatthias Ringwald } 294*7dbac955SMatthias Ringwald 295*7dbac955SMatthias Ringwald uint8_t gatt_client_write_client_characteristic_configuration(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic, uint16_t configuration){ 296*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle); 297*7dbac955SMatthias Ringwald btstack_assert(mock_characteristic != NULL); 298*7dbac955SMatthias Ringwald 299*7dbac955SMatthias Ringwald if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){ 300*7dbac955SMatthias Ringwald return mock_characteristic->notification_status_code; 301*7dbac955SMatthias Ringwald } 302*7dbac955SMatthias Ringwald 303*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION; 304*7dbac955SMatthias Ringwald 305*7dbac955SMatthias Ringwald gatt_client.callback = callback; 306*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 307*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 308*7dbac955SMatthias Ringwald } 309*7dbac955SMatthias Ringwald 310*7dbac955SMatthias Ringwald uint8_t gatt_client_read_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle){ 311*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE; 312*7dbac955SMatthias Ringwald 313*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle); 314*7dbac955SMatthias Ringwald btstack_assert(mock_characteristic != NULL); 315*7dbac955SMatthias Ringwald 316*7dbac955SMatthias Ringwald mock_gatt_client_value_handle = mock_characteristic->value_handle; 317*7dbac955SMatthias Ringwald gatt_client.callback = callback; 318*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 319*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 320*7dbac955SMatthias Ringwald } 321*7dbac955SMatthias Ringwald 322*7dbac955SMatthias Ringwald uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){ 323*7dbac955SMatthias Ringwald btstack_assert(characteristic != NULL); 324*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE; 325*7dbac955SMatthias Ringwald 326*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle); 327*7dbac955SMatthias Ringwald btstack_assert(mock_characteristic != NULL); 328*7dbac955SMatthias Ringwald 329*7dbac955SMatthias Ringwald gatt_client.callback = callback; 330*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 331*7dbac955SMatthias Ringwald mock_gatt_client_value_handle = mock_characteristic->value_handle; 332*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 333*7dbac955SMatthias Ringwald } 334*7dbac955SMatthias Ringwald 335*7dbac955SMatthias Ringwald uint8_t gatt_client_read_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle){ 336*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE; 337*7dbac955SMatthias Ringwald mock_gatt_client_value_handle = descriptor_handle; 338*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 339*7dbac955SMatthias Ringwald } 340*7dbac955SMatthias Ringwald 341*7dbac955SMatthias Ringwald void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){ 342*7dbac955SMatthias Ringwald } 343*7dbac955SMatthias Ringwald 344*7dbac955SMatthias Ringwald uint8_t gatt_client_write_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){ 345*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle); 346*7dbac955SMatthias Ringwald btstack_assert(mock_characteristic != NULL); 347*7dbac955SMatthias Ringwald 348*7dbac955SMatthias Ringwald if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){ 349*7dbac955SMatthias Ringwald return mock_characteristic->notification_status_code; 350*7dbac955SMatthias Ringwald } 351*7dbac955SMatthias Ringwald 352*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION; 353*7dbac955SMatthias Ringwald 354*7dbac955SMatthias Ringwald gatt_client.callback = callback; 355*7dbac955SMatthias Ringwald gatt_client.con_handle = con_handle; 356*7dbac955SMatthias Ringwald return ERROR_CODE_SUCCESS; 357*7dbac955SMatthias Ringwald } 358*7dbac955SMatthias Ringwald 3597e693ad3SMilanka Ringwald void mock_gatt_client_emit_complete(uint8_t status){ 3607da2c1baSMilanka Ringwald mock_gatt_client_state = MOCK_QUERY_IDLE; 3617da2c1baSMilanka Ringwald emit_gatt_complete_event(&gatt_client, status); 3627da2c1baSMilanka Ringwald } 3630f7fd6c1SMilanka Ringwald 3647e693ad3SMilanka Ringwald void mock_gatt_client_run_once(void){ 365af770404SMilanka Ringwald btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE); 36676cdba3eSMilanka Ringwald mock_gatt_client_characteristic_t * characteristic; 36776cdba3eSMilanka Ringwald mock_gatt_client_characteristic_descriptor_t * descriptor; 36876cdba3eSMilanka Ringwald 3697da2c1baSMilanka Ringwald btstack_linked_list_iterator_t service_it; 3707da2c1baSMilanka Ringwald btstack_linked_list_iterator_t characteristic_it; 37176cdba3eSMilanka Ringwald btstack_linked_list_iterator_t descriptor_it; 37276cdba3eSMilanka Ringwald 373af770404SMilanka Ringwald switch (mock_gatt_client_state){ 374*7dbac955SMatthias Ringwald case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID: 375af770404SMilanka Ringwald // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service 376ec1a0daeSMilanka Ringwald if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){ 377ec1a0daeSMilanka Ringwald mock_gatt_client_emit_complete(moc_att_error_code_discover_services); 378ec1a0daeSMilanka Ringwald return; 379ec1a0daeSMilanka Ringwald } 380ec1a0daeSMilanka Ringwald 3817da2c1baSMilanka Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 3827da2c1baSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 3837da2c1baSMilanka Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 384*7dbac955SMatthias Ringwald if (memcmp(service->uuid128, mock_gatt_client_uuid128, 16) != 0) continue; 3857da2c1baSMilanka Ringwald mock_gatt_client_last_service = service; 386*7dbac955SMatthias Ringwald emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, service->uuid128); 3877da2c1baSMilanka Ringwald } 3887da2c1baSMilanka Ringwald // emit GATT_EVENT_QUERY_COMPLETE 3897da2c1baSMilanka Ringwald mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS); 3907da2c1baSMilanka Ringwald break; 3917da2c1baSMilanka Ringwald 392*7dbac955SMatthias Ringwald case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID: 393*7dbac955SMatthias Ringwald case MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS: 3947da2c1baSMilanka Ringwald // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic 395ec1a0daeSMilanka Ringwald if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){ 396ec1a0daeSMilanka Ringwald mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics); 397ec1a0daeSMilanka Ringwald return; 398ec1a0daeSMilanka Ringwald } 399ec1a0daeSMilanka Ringwald 4007da2c1baSMilanka Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 4017da2c1baSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 4027da2c1baSMilanka Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 4037da2c1baSMilanka Ringwald 4047da2c1baSMilanka Ringwald btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 4057da2c1baSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 4067da2c1baSMilanka Ringwald mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 40776cdba3eSMilanka Ringwald if (characteristic->start_handle < mock_gatt_client_start_handle) continue; 40876cdba3eSMilanka Ringwald if (characteristic->end_handle > mock_gatt_client_end_handle) continue; 409*7dbac955SMatthias Ringwald if ((mock_gatt_client_state == MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID) && (memcmp(characteristic->uuid128, mock_gatt_client_uuid128, 16) != 0)) continue; 41076cdba3eSMilanka Ringwald 41176cdba3eSMilanka Ringwald emit_gatt_characteristic_query_result_event(&gatt_client, 41276cdba3eSMilanka Ringwald characteristic->start_handle, characteristic->value_handle, characteristic->end_handle, 413*7dbac955SMatthias Ringwald characteristic->properties, characteristic->uuid128); 4147da2c1baSMilanka Ringwald } 4157da2c1baSMilanka Ringwald } 4167da2c1baSMilanka Ringwald 4177da2c1baSMilanka Ringwald // emit GATT_EVENT_QUERY_COMPLETE 4187da2c1baSMilanka Ringwald mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 419af770404SMilanka Ringwald break; 42076cdba3eSMilanka Ringwald 42176cdba3eSMilanka Ringwald case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS: 42276cdba3eSMilanka Ringwald characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle); 42376cdba3eSMilanka Ringwald btstack_assert(characteristic != NULL); 42476cdba3eSMilanka Ringwald 425ec1a0daeSMilanka Ringwald if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){ 426ec1a0daeSMilanka Ringwald mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors); 427ec1a0daeSMilanka Ringwald return; 428ec1a0daeSMilanka Ringwald } 429ec1a0daeSMilanka Ringwald 43076cdba3eSMilanka Ringwald btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors); 43176cdba3eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&descriptor_it)){ 43276cdba3eSMilanka Ringwald mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it); 43376cdba3eSMilanka Ringwald 434*7dbac955SMatthias Ringwald emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, desc->uuid128); 43576cdba3eSMilanka Ringwald } 43676cdba3eSMilanka Ringwald 43776cdba3eSMilanka Ringwald // emit GATT_EVENT_QUERY_COMPLETE 43876cdba3eSMilanka Ringwald mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 43976cdba3eSMilanka Ringwald break; 44076cdba3eSMilanka Ringwald 44176cdba3eSMilanka Ringwald case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION: 44276cdba3eSMilanka Ringwald mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 44376cdba3eSMilanka Ringwald break; 44476cdba3eSMilanka Ringwald 44576cdba3eSMilanka Ringwald case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE: 4467e693ad3SMilanka Ringwald characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle); 4477e693ad3SMilanka Ringwald btstack_assert(characteristic != NULL); 4487e693ad3SMilanka Ringwald 4497e693ad3SMilanka Ringwald mock_gatt_client_send_characteristic_value(&gatt_client, characteristic); 4507e693ad3SMilanka Ringwald mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 4517e693ad3SMilanka Ringwald break; 4527e693ad3SMilanka Ringwald 4537e693ad3SMilanka Ringwald case MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE: 45476cdba3eSMilanka Ringwald descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle); 45576cdba3eSMilanka Ringwald btstack_assert(descriptor != NULL); 45676cdba3eSMilanka Ringwald btstack_assert(descriptor->value_buffer != NULL); 45776cdba3eSMilanka Ringwald 45876cdba3eSMilanka Ringwald mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 45976cdba3eSMilanka Ringwald break; 46076cdba3eSMilanka Ringwald 461af770404SMilanka Ringwald default: 462af770404SMilanka Ringwald btstack_assert(false); 463af770404SMilanka Ringwald break; 4640f7fd6c1SMilanka Ringwald } 4657da2c1baSMilanka Ringwald } 4667e693ad3SMilanka Ringwald 4677e693ad3SMilanka Ringwald void mock_gatt_client_run(void){ 4687e693ad3SMilanka Ringwald btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE); 4697e693ad3SMilanka Ringwald while (mock_gatt_client_state != MOCK_QUERY_IDLE){ 4707e693ad3SMilanka Ringwald mock_gatt_client_run_once(); 4717e693ad3SMilanka Ringwald } 4727da2c1baSMilanka Ringwald mock_gatt_client_att_error = ERROR_CODE_SUCCESS; 473af770404SMilanka Ringwald mock_gatt_client_state = MOCK_QUERY_IDLE; 4740f7fd6c1SMilanka Ringwald } 4757e693ad3SMilanka Ringwald 4767e693ad3SMilanka Ringwald void mock_gatt_client_emit_dummy_event(void){ 4777e693ad3SMilanka Ringwald // @format H1 4787e693ad3SMilanka Ringwald uint8_t packet[2]; 4797e693ad3SMilanka Ringwald packet[0] = 0; 4807e693ad3SMilanka Ringwald packet[1] = 0; 4817e693ad3SMilanka Ringwald emit_event(gatt_client.callback, packet, sizeof(packet)); 4827e693ad3SMilanka Ringwald } 483*7dbac955SMatthias Ringwald 484*7dbac955SMatthias Ringwald static void mock_gatt_client_reset_errors(void){ 485*7dbac955SMatthias Ringwald moc_att_error_code_discover_services = ATT_ERROR_SUCCESS; 486*7dbac955SMatthias Ringwald moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS; 487*7dbac955SMatthias Ringwald moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS; 488*7dbac955SMatthias Ringwald 489*7dbac955SMatthias Ringwald mock_gatt_client_wrong_con_handle = false; 490*7dbac955SMatthias Ringwald mock_gatt_client_wrong_value_handle = false; 491*7dbac955SMatthias Ringwald } 492*7dbac955SMatthias Ringwald 493*7dbac955SMatthias Ringwald void mock_gatt_client_reset(void){ 494*7dbac955SMatthias Ringwald mock_gatt_client_att_error = 0; 495*7dbac955SMatthias Ringwald mock_gatt_client_state = MOCK_QUERY_IDLE; 496*7dbac955SMatthias Ringwald mock_gatt_client_att_handle_generator = 0; 497*7dbac955SMatthias Ringwald mock_gatt_client_last_service = NULL; 498*7dbac955SMatthias Ringwald 499*7dbac955SMatthias Ringwald mock_gatt_client_reset_errors(); 500*7dbac955SMatthias Ringwald 501*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t service_it; 502*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 503*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 504*7dbac955SMatthias Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 505*7dbac955SMatthias Ringwald btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service); 506*7dbac955SMatthias Ringwald 507*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t characteristic_it; 508*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 509*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 510*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 511*7dbac955SMatthias Ringwald btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic); 512*7dbac955SMatthias Ringwald 513*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t desc_it; 514*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 515*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&desc_it)){ 516*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 517*7dbac955SMatthias Ringwald btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc); 518*7dbac955SMatthias Ringwald free(desc); 519*7dbac955SMatthias Ringwald } 520*7dbac955SMatthias Ringwald free(characteristic); 521*7dbac955SMatthias Ringwald } 522*7dbac955SMatthias Ringwald free(service); 523*7dbac955SMatthias Ringwald } 524*7dbac955SMatthias Ringwald } 525*7dbac955SMatthias Ringwald 526*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_primary_services(void){ 527*7dbac955SMatthias Ringwald moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED; 528*7dbac955SMatthias Ringwald } 529*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristics(void){ 530*7dbac955SMatthias Ringwald moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED; 531*7dbac955SMatthias Ringwald } 532*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){ 533*7dbac955SMatthias Ringwald moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED; 534*7dbac955SMatthias Ringwald } 535*7dbac955SMatthias Ringwald 536*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_con_handle(void){ 537*7dbac955SMatthias Ringwald mock_gatt_client_wrong_con_handle = true; 538*7dbac955SMatthias Ringwald } 539*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_value_handle(void){ 540*7dbac955SMatthias Ringwald mock_gatt_client_wrong_value_handle = true; 541*7dbac955SMatthias Ringwald } 542*7dbac955SMatthias Ringwald 543*7dbac955SMatthias Ringwald void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){ 544*7dbac955SMatthias Ringwald if (command_allowed){ 545*7dbac955SMatthias Ringwald characteristic->notification_status_code = ERROR_CODE_SUCCESS; 546*7dbac955SMatthias Ringwald } else { 547*7dbac955SMatthias Ringwald characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED; 548*7dbac955SMatthias Ringwald } 549*7dbac955SMatthias Ringwald } 550*7dbac955SMatthias Ringwald 551*7dbac955SMatthias Ringwald void mock_gatt_client_dump_services(void){ 552*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t service_it; 553*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 554*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&service_it)){ 555*7dbac955SMatthias Ringwald mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 556*7dbac955SMatthias Ringwald printf("0x%02x: START SERVICE ", service->start_group_handle); 557*7dbac955SMatthias Ringwald if (service->uuid16) { 558*7dbac955SMatthias Ringwald printf("%04x\n", service->uuid16); 559*7dbac955SMatthias Ringwald } else { 560*7dbac955SMatthias Ringwald printf("%s\n", uuid128_to_str(service->uuid128)); 561*7dbac955SMatthias Ringwald } 562*7dbac955SMatthias Ringwald 563*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t characteristic_it; 564*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 565*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 566*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 567*7dbac955SMatthias Ringwald printf("0x%02x: START CHR ", characteristic->start_handle); 568*7dbac955SMatthias Ringwald if (characteristic->uuid16) { 569*7dbac955SMatthias Ringwald printf("%04x\n", characteristic->uuid16); 570*7dbac955SMatthias Ringwald } else { 571*7dbac955SMatthias Ringwald printf("%s\n", uuid128_to_str(characteristic->uuid128)); 572*7dbac955SMatthias Ringwald } 573*7dbac955SMatthias Ringwald printf("0x%02x: VALUE HANDLE CHR\n", characteristic->value_handle); 574*7dbac955SMatthias Ringwald 575*7dbac955SMatthias Ringwald btstack_linked_list_iterator_t desc_it; 576*7dbac955SMatthias Ringwald btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 577*7dbac955SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&desc_it)){ 578*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 579*7dbac955SMatthias Ringwald printf("0x%02x: DESC 0x%02x\n", desc->handle, desc->uuid16); 580*7dbac955SMatthias Ringwald } 581*7dbac955SMatthias Ringwald 582*7dbac955SMatthias Ringwald printf("0x%02x: END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16); 583*7dbac955SMatthias Ringwald } 584*7dbac955SMatthias Ringwald printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16); 585*7dbac955SMatthias Ringwald 586*7dbac955SMatthias Ringwald } 587*7dbac955SMatthias Ringwald } 588*7dbac955SMatthias Ringwald 589*7dbac955SMatthias Ringwald static void mock_gatt_client_add_primary_service(void){ 590*7dbac955SMatthias Ringwald // set lsat group handle 591*7dbac955SMatthias Ringwald // create new service 592*7dbac955SMatthias Ringwald mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t)); 593*7dbac955SMatthias Ringwald memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t)); 594*7dbac955SMatthias Ringwald mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++; 595*7dbac955SMatthias Ringwald mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle; 596*7dbac955SMatthias Ringwald btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service); 597*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic = NULL; 598*7dbac955SMatthias Ringwald } 599*7dbac955SMatthias Ringwald 600*7dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){ 601*7dbac955SMatthias Ringwald mock_gatt_client_add_primary_service(); 602*7dbac955SMatthias Ringwald mock_gatt_client_last_service->uuid16 = service_uuid; 603*7dbac955SMatthias Ringwald uuid_add_bluetooth_prefix(mock_gatt_client_last_service->uuid128, service_uuid); 604*7dbac955SMatthias Ringwald return mock_gatt_client_last_service; 605*7dbac955SMatthias Ringwald } 606*7dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid128(const uint8_t * service_uuid){ 607*7dbac955SMatthias Ringwald mock_gatt_client_add_primary_service(); 608*7dbac955SMatthias Ringwald (void) memcpy(mock_gatt_client_last_service->uuid128, service_uuid, 16); 609*7dbac955SMatthias Ringwald return mock_gatt_client_last_service; 610*7dbac955SMatthias Ringwald } 611*7dbac955SMatthias Ringwald 612*7dbac955SMatthias Ringwald static void mock_gatt_client_add_characteristic(uint16_t properties){ 613*7dbac955SMatthias Ringwald btstack_assert(mock_gatt_client_last_service != NULL); 614*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t)); 615*7dbac955SMatthias Ringwald memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t)); 616*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->properties = properties; 617*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++; 618*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++; 619*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle; 620*7dbac955SMatthias Ringwald btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic); 621*7dbac955SMatthias Ringwald mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1; 622*7dbac955SMatthias Ringwald } 623*7dbac955SMatthias Ringwald 624*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){ 625*7dbac955SMatthias Ringwald mock_gatt_client_add_characteristic(properties); 626*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid; 627*7dbac955SMatthias Ringwald uuid_add_bluetooth_prefix(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid); 628*7dbac955SMatthias Ringwald return mock_gatt_client_last_characteristic; 629*7dbac955SMatthias Ringwald } 630*7dbac955SMatthias Ringwald 631*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid128(const uint8_t * characteristic_uuid, uint16_t properties){ 632*7dbac955SMatthias Ringwald mock_gatt_client_add_characteristic(properties); 633*7dbac955SMatthias Ringwald (void) memcpy(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid, 16); 634*7dbac955SMatthias Ringwald return mock_gatt_client_last_characteristic; 635*7dbac955SMatthias Ringwald } 636*7dbac955SMatthias Ringwald 637*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor(void){ 638*7dbac955SMatthias Ringwald btstack_assert(mock_gatt_client_last_characteristic != NULL); 639*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t)); 640*7dbac955SMatthias Ringwald memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t)); 641*7dbac955SMatthias Ringwald desc->handle = mock_gatt_client_att_handle_generator++; 642*7dbac955SMatthias Ringwald btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc); 643*7dbac955SMatthias Ringwald mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1; 644*7dbac955SMatthias Ringwald mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1; 645*7dbac955SMatthias Ringwald return desc; 646*7dbac955SMatthias Ringwald } 647*7dbac955SMatthias Ringwald 648*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){ 649*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor(); 650*7dbac955SMatthias Ringwald desc->uuid16 = descriptor_uuid; 651*7dbac955SMatthias Ringwald uuid_add_bluetooth_prefix(desc->uuid128, descriptor_uuid); 652*7dbac955SMatthias Ringwald return desc; 653*7dbac955SMatthias Ringwald } 654*7dbac955SMatthias Ringwald 655*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid128(const uint8_t * descriptor_uuid){ 656*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor(); 657*7dbac955SMatthias Ringwald (void) memcpy(desc->uuid128, descriptor_uuid, 16); 658*7dbac955SMatthias Ringwald return desc; 659*7dbac955SMatthias Ringwald } 660*7dbac955SMatthias Ringwald 661*7dbac955SMatthias Ringwald void mock_gatt_client_set_descriptor_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){ 662*7dbac955SMatthias Ringwald btstack_assert(descriptor != NULL); 663*7dbac955SMatthias Ringwald descriptor->value_buffer = value_buffer; 664*7dbac955SMatthias Ringwald descriptor->value_len = value_len; 665*7dbac955SMatthias Ringwald } 666*7dbac955SMatthias Ringwald 667*7dbac955SMatthias Ringwald void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){ 668*7dbac955SMatthias Ringwald btstack_assert(characteristic != NULL); 669*7dbac955SMatthias Ringwald characteristic->value_buffer = value_buffer; 670*7dbac955SMatthias Ringwald characteristic->value_len = value_len; 671*7dbac955SMatthias Ringwald } 672*7dbac955SMatthias Ringwald 673*7dbac955SMatthias Ringwald // simulate error 674*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_att_error(uint8_t att_error){ 675*7dbac955SMatthias Ringwald mock_gatt_client_att_error = att_error; 676*7dbac955SMatthias Ringwald } 677