xref: /btstack/test/mock/mock_gatt_client.c (revision 86d0910f317293eca170a5ee595d975884b9bdcc)
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,
14d41a8f51SMilanka Ringwald     MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16,
15d41a8f51SMilanka Ringwald     MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16,
1676cdba3eSMilanka Ringwald     MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS,
1776cdba3eSMilanka Ringwald     MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION,
187e693ad3SMilanka Ringwald     MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE,
197e693ad3SMilanka Ringwald     MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE
20af770404SMilanka Ringwald } mock_gatt_client_state;
21af770404SMilanka Ringwald 
2276cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_att_handle_generator;
2376cdba3eSMilanka Ringwald 
24af770404SMilanka Ringwald static uint8_t mock_gatt_client_att_error;
25af770404SMilanka Ringwald static uint16_t mock_gatt_client_uuid;
2676cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_value_handle;
2776cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_start_handle;
2876cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_end_handle;
2976cdba3eSMilanka Ringwald 
30af770404SMilanka Ringwald static gatt_client_t gatt_client;
310f7fd6c1SMilanka Ringwald 
327da2c1baSMilanka Ringwald static btstack_linked_list_t mock_gatt_client_services;
337da2c1baSMilanka Ringwald 
347da2c1baSMilanka Ringwald static mock_gatt_client_service_t * mock_gatt_client_last_service;
357da2c1baSMilanka Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic;
367da2c1baSMilanka Ringwald 
37ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_services;
38ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristics;
39ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristic_descriptors;
407e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_con_handle;
417e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_value_handle;
42ec1a0daeSMilanka Ringwald 
437e693ad3SMilanka Ringwald static void mock_gatt_client_reset_errors(void){
44ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_services = ATT_ERROR_SUCCESS;
45ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS;
46ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS;
477e693ad3SMilanka Ringwald 
487e693ad3SMilanka Ringwald     mock_gatt_client_wrong_con_handle = false;
497e693ad3SMilanka Ringwald     mock_gatt_client_wrong_value_handle = false;
50ec1a0daeSMilanka Ringwald }
51ec1a0daeSMilanka Ringwald 
520f7fd6c1SMilanka Ringwald void mock_gatt_client_reset(void){
53af770404SMilanka Ringwald     mock_gatt_client_att_error = 0;
54af770404SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
5576cdba3eSMilanka Ringwald     mock_gatt_client_att_handle_generator = 0;
5676cdba3eSMilanka Ringwald     mock_gatt_client_last_service = NULL;
577da2c1baSMilanka Ringwald 
587e693ad3SMilanka Ringwald     mock_gatt_client_reset_errors();
59ec1a0daeSMilanka Ringwald 
607da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
617da2c1baSMilanka Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
627da2c1baSMilanka Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
637da2c1baSMilanka Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
647da2c1baSMilanka Ringwald         btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service);
657da2c1baSMilanka Ringwald 
667da2c1baSMilanka Ringwald         btstack_linked_list_iterator_t characteristic_it;
677da2c1baSMilanka Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
687da2c1baSMilanka Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
697da2c1baSMilanka Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
707da2c1baSMilanka Ringwald             btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic);
717da2c1baSMilanka Ringwald 
727da2c1baSMilanka Ringwald             btstack_linked_list_iterator_t desc_it;
737da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
747da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
757da2c1baSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
767da2c1baSMilanka Ringwald                 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc);
777da2c1baSMilanka Ringwald                 free(desc);
787da2c1baSMilanka Ringwald             }
797da2c1baSMilanka Ringwald             free(characteristic);
807da2c1baSMilanka Ringwald         }
817da2c1baSMilanka Ringwald         free(service);
827da2c1baSMilanka Ringwald     }
830f7fd6c1SMilanka Ringwald }
84af770404SMilanka Ringwald 
85ec1a0daeSMilanka Ringwald void mock_gatt_client_set_att_error_discover_primary_services(void){
86ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED;
87ec1a0daeSMilanka Ringwald }
88ec1a0daeSMilanka Ringwald void mock_gatt_client_set_att_error_discover_characteristics(void){
89ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED;
90ec1a0daeSMilanka Ringwald }
91ec1a0daeSMilanka Ringwald void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){
92ec1a0daeSMilanka Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED;
93ec1a0daeSMilanka Ringwald }
94ec1a0daeSMilanka Ringwald 
957e693ad3SMilanka Ringwald void mock_gatt_client_simulate_invalid_con_handle(void){
967e693ad3SMilanka Ringwald     mock_gatt_client_wrong_con_handle = true;
977e693ad3SMilanka Ringwald }
987e693ad3SMilanka Ringwald void mock_gatt_client_simulate_invalid_value_handle(void){
997e693ad3SMilanka Ringwald     mock_gatt_client_wrong_value_handle = true;
1007e693ad3SMilanka Ringwald }
1017e693ad3SMilanka Ringwald 
1027e693ad3SMilanka Ringwald void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){
1037e693ad3SMilanka Ringwald     if (command_allowed){
1047e693ad3SMilanka Ringwald         characteristic->notification_status_code = ERROR_CODE_SUCCESS;
1057e693ad3SMilanka Ringwald     } else {
1067e693ad3SMilanka Ringwald         characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED;
1077e693ad3SMilanka Ringwald     }
1087e693ad3SMilanka Ringwald }
1097e693ad3SMilanka Ringwald 
11076cdba3eSMilanka Ringwald void mock_gatt_client_dump_services(void){
11176cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
11276cdba3eSMilanka Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
11376cdba3eSMilanka Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
11476cdba3eSMilanka Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
11576cdba3eSMilanka Ringwald         printf("0x%02x: START SERVICE 0%02x\n", service->start_group_handle, service->uuid16);
11676cdba3eSMilanka Ringwald 
11776cdba3eSMilanka Ringwald         btstack_linked_list_iterator_t characteristic_it;
11876cdba3eSMilanka Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
11976cdba3eSMilanka Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
12076cdba3eSMilanka Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
12176cdba3eSMilanka Ringwald             printf("0x%02x:   START CHR 0%02x\n", characteristic->start_handle, characteristic->uuid16);
12276cdba3eSMilanka Ringwald             printf("0x%02x:   VALUE HANDLE CHR 0%02x\n", characteristic->value_handle, characteristic->uuid16);
12376cdba3eSMilanka Ringwald 
12476cdba3eSMilanka Ringwald             btstack_linked_list_iterator_t desc_it;
12576cdba3eSMilanka Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
12676cdba3eSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
12776cdba3eSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
12876cdba3eSMilanka Ringwald                 printf("0x%02x:     DESC 0x%02x\n", desc->handle, desc->uuid16);
12976cdba3eSMilanka Ringwald             }
13076cdba3eSMilanka Ringwald 
13176cdba3eSMilanka Ringwald             printf("0x%02x:   END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16);
13276cdba3eSMilanka Ringwald 
13376cdba3eSMilanka Ringwald         }
13476cdba3eSMilanka Ringwald         printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16);
13576cdba3eSMilanka Ringwald 
13676cdba3eSMilanka Ringwald     }
13776cdba3eSMilanka Ringwald }
13876cdba3eSMilanka Ringwald 
13976cdba3eSMilanka Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){
14076cdba3eSMilanka Ringwald     // set lsat group handle
14176cdba3eSMilanka Ringwald     // create new service
1427da2c1baSMilanka Ringwald     mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t));
1437da2c1baSMilanka Ringwald     memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t));
1447da2c1baSMilanka Ringwald     mock_gatt_client_last_service->uuid16 = service_uuid;
14576cdba3eSMilanka Ringwald     mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++;
1466ad61799SMilanka Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle;
1475b92fca9SMilanka Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service);
14876cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic = NULL;
14976cdba3eSMilanka Ringwald     return mock_gatt_client_last_service;
1500f7fd6c1SMilanka Ringwald }
151af770404SMilanka Ringwald 
15276cdba3eSMilanka Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){
1537da2c1baSMilanka Ringwald     btstack_assert(mock_gatt_client_last_service != NULL);
1547da2c1baSMilanka Ringwald     mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t));
1557da2c1baSMilanka Ringwald     memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t));
1567da2c1baSMilanka Ringwald     mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid;
15776cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic->properties = properties;
15876cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++;
15976cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++;
16076cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle;
1615b92fca9SMilanka Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic);
16276cdba3eSMilanka Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
16376cdba3eSMilanka Ringwald     return mock_gatt_client_last_characteristic;
1640f7fd6c1SMilanka Ringwald }
165af770404SMilanka Ringwald 
16676cdba3eSMilanka Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){
16776cdba3eSMilanka Ringwald     btstack_assert(mock_gatt_client_last_characteristic != NULL);
1687da2c1baSMilanka Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t));
1697da2c1baSMilanka Ringwald     memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t));
1707da2c1baSMilanka Ringwald     desc->uuid16 = descriptor_uuid;
17176cdba3eSMilanka Ringwald     desc->handle = mock_gatt_client_att_handle_generator++;
1725b92fca9SMilanka Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc);
17376cdba3eSMilanka Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1;
17476cdba3eSMilanka Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
17576cdba3eSMilanka Ringwald     return desc;
1760f7fd6c1SMilanka Ringwald }
1770f7fd6c1SMilanka Ringwald 
17876cdba3eSMilanka Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){
17976cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
18076cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t characteristic_it;
18176cdba3eSMilanka Ringwald 
18276cdba3eSMilanka Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
18376cdba3eSMilanka Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
18476cdba3eSMilanka Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
18576cdba3eSMilanka Ringwald 
18676cdba3eSMilanka Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
18776cdba3eSMilanka Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
18876cdba3eSMilanka Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
18976cdba3eSMilanka Ringwald             if (characteristic->value_handle != value_handle) continue;
19076cdba3eSMilanka Ringwald             return characteristic;
19176cdba3eSMilanka Ringwald         }
19276cdba3eSMilanka Ringwald     }
19376cdba3eSMilanka Ringwald     return NULL;
19476cdba3eSMilanka Ringwald }
19576cdba3eSMilanka Ringwald 
19676cdba3eSMilanka Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){
19776cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
19876cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t characteristic_it;
19976cdba3eSMilanka Ringwald 
20076cdba3eSMilanka Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
20176cdba3eSMilanka Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
20276cdba3eSMilanka Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
20376cdba3eSMilanka Ringwald 
20476cdba3eSMilanka Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
20576cdba3eSMilanka Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
20676cdba3eSMilanka Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
20776cdba3eSMilanka Ringwald 
20876cdba3eSMilanka Ringwald             btstack_linked_list_iterator_t desc_it;
20976cdba3eSMilanka Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
21076cdba3eSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
21176cdba3eSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
21276cdba3eSMilanka Ringwald                 if (desc->handle != handle) continue;
21376cdba3eSMilanka Ringwald                 return desc;
21476cdba3eSMilanka Ringwald             }
21576cdba3eSMilanka Ringwald         }
21676cdba3eSMilanka Ringwald     }
21776cdba3eSMilanka Ringwald     return NULL;
21876cdba3eSMilanka Ringwald }
21976cdba3eSMilanka Ringwald 
22076cdba3eSMilanka Ringwald 
2217e693ad3SMilanka Ringwald void mock_gatt_client_set_descriptor_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){
22276cdba3eSMilanka Ringwald     btstack_assert(descriptor != NULL);
22376cdba3eSMilanka Ringwald     descriptor->value_buffer = value_buffer;
22476cdba3eSMilanka Ringwald     descriptor->value_len = value_len;
22576cdba3eSMilanka Ringwald }
2267da2c1baSMilanka Ringwald 
2277e693ad3SMilanka Ringwald void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
2287e693ad3SMilanka Ringwald     btstack_assert(characteristic != NULL);
2297e693ad3SMilanka Ringwald     characteristic->value_buffer = value_buffer;
2307e693ad3SMilanka Ringwald     characteristic->value_len = value_len;
2317e693ad3SMilanka Ringwald }
2327e693ad3SMilanka Ringwald 
2337e693ad3SMilanka Ringwald // simulate error
234af770404SMilanka Ringwald void mock_gatt_client_simulate_att_error(uint8_t att_error){
235af770404SMilanka Ringwald     mock_gatt_client_att_error = att_error;
2360f7fd6c1SMilanka Ringwald }
2370f7fd6c1SMilanka Ringwald 
2380f7fd6c1SMilanka Ringwald uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
239d41a8f51SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16;
240af770404SMilanka Ringwald     mock_gatt_client_uuid = uuid16;
241af770404SMilanka Ringwald 
242af770404SMilanka Ringwald     gatt_client.callback = callback;
243af770404SMilanka Ringwald     gatt_client.con_handle = con_handle;
2440f7fd6c1SMilanka Ringwald     return ERROR_CODE_SUCCESS;
2450f7fd6c1SMilanka Ringwald }
2460f7fd6c1SMilanka Ringwald 
2470f7fd6c1SMilanka 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){
248d41a8f51SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16;
2497da2c1baSMilanka Ringwald     mock_gatt_client_uuid = uuid16;
25076cdba3eSMilanka Ringwald     mock_gatt_client_start_handle = start_handle;
25176cdba3eSMilanka Ringwald     mock_gatt_client_end_handle = end_handle;
2527da2c1baSMilanka Ringwald 
2537da2c1baSMilanka Ringwald     gatt_client.callback = callback;
2547da2c1baSMilanka Ringwald     gatt_client.con_handle = con_handle;
2550f7fd6c1SMilanka Ringwald     return ERROR_CODE_SUCCESS;
2560f7fd6c1SMilanka Ringwald }
2570f7fd6c1SMilanka Ringwald 
2580f7fd6c1SMilanka Ringwald uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
25976cdba3eSMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS;
26076cdba3eSMilanka Ringwald     mock_gatt_client_value_handle = characteristic->value_handle;
26176cdba3eSMilanka Ringwald 
26276cdba3eSMilanka Ringwald     gatt_client.callback = callback;
26376cdba3eSMilanka Ringwald     gatt_client.con_handle = con_handle;
26476cdba3eSMilanka Ringwald     return ERROR_CODE_SUCCESS;
26576cdba3eSMilanka Ringwald }
26676cdba3eSMilanka Ringwald 
2677e693ad3SMilanka 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){
2687e693ad3SMilanka Ringwald     btstack_assert(notification != NULL);
2697e693ad3SMilanka Ringwald     btstack_assert(&callback != NULL);
2707e693ad3SMilanka Ringwald 
2717e693ad3SMilanka Ringwald     notification->callback = callback;
2727e693ad3SMilanka Ringwald     notification->con_handle = con_handle;
2737e693ad3SMilanka Ringwald 
2747e693ad3SMilanka Ringwald 
2757e693ad3SMilanka Ringwald     if (characteristic == NULL){
2767e693ad3SMilanka Ringwald         // 'all characteristics': not used yet
2777e693ad3SMilanka Ringwald         btstack_assert(false);
2787e693ad3SMilanka Ringwald     } else {
2797e693ad3SMilanka Ringwald         mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
2807e693ad3SMilanka Ringwald         btstack_assert(mock_characteristic != NULL);
2817e693ad3SMilanka Ringwald 
2827e693ad3SMilanka Ringwald         notification->attribute_handle = characteristic->value_handle;
2837e693ad3SMilanka Ringwald         mock_characteristic->notification = notification;
2847e693ad3SMilanka Ringwald     }
2857e693ad3SMilanka Ringwald }
2867e693ad3SMilanka Ringwald 
28776cdba3eSMilanka 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){
2887e693ad3SMilanka Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
2897e693ad3SMilanka Ringwald     btstack_assert(mock_characteristic != NULL);
2907e693ad3SMilanka Ringwald 
2917e693ad3SMilanka Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
2927e693ad3SMilanka Ringwald         return mock_characteristic->notification_status_code;
2937e693ad3SMilanka Ringwald     }
2947e693ad3SMilanka Ringwald 
29576cdba3eSMilanka Ringwald     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
29676cdba3eSMilanka Ringwald     mock_gatt_client_uuid = characteristic->uuid16;
29776cdba3eSMilanka Ringwald 
29876cdba3eSMilanka Ringwald     gatt_client.callback = callback;
29976cdba3eSMilanka Ringwald     gatt_client.con_handle = con_handle;
30076cdba3eSMilanka Ringwald     return ERROR_CODE_SUCCESS;
30176cdba3eSMilanka Ringwald }
30276cdba3eSMilanka Ringwald 
30376cdba3eSMilanka 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){
30476cdba3eSMilanka Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
3057e693ad3SMilanka Ringwald 
3067e693ad3SMilanka Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
3077e693ad3SMilanka Ringwald     btstack_assert(mock_characteristic != NULL);
3087e693ad3SMilanka Ringwald 
3097e693ad3SMilanka Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
3107e693ad3SMilanka Ringwald     gatt_client.callback = callback;
3117e693ad3SMilanka Ringwald     gatt_client.con_handle = con_handle;
312af770404SMilanka Ringwald     return ERROR_CODE_SUCCESS;
313af770404SMilanka Ringwald }
314af770404SMilanka Ringwald 
315af770404SMilanka 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){
31624152f08SMilanka Ringwald     btstack_assert(characteristic != NULL);
31724152f08SMilanka Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
31824152f08SMilanka Ringwald 
3197e693ad3SMilanka Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
32024152f08SMilanka Ringwald     btstack_assert(mock_characteristic != NULL);
32124152f08SMilanka Ringwald 
3227e693ad3SMilanka Ringwald     gatt_client.callback = callback;
3237e693ad3SMilanka Ringwald     gatt_client.con_handle = con_handle;
32424152f08SMilanka Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
3250f7fd6c1SMilanka Ringwald     return ERROR_CODE_SUCCESS;
3260f7fd6c1SMilanka Ringwald }
3270f7fd6c1SMilanka Ringwald 
3287e693ad3SMilanka 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){
3297e693ad3SMilanka Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE;
3307e693ad3SMilanka Ringwald     mock_gatt_client_value_handle = descriptor_handle;
3317e693ad3SMilanka Ringwald     return ERROR_CODE_SUCCESS;
3327e693ad3SMilanka Ringwald }
3337e693ad3SMilanka Ringwald 
334af770404SMilanka Ringwald void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
335af770404SMilanka Ringwald }
336af770404SMilanka Ringwald 
337*86d0910fSMilanka 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){
338*86d0910fSMilanka Ringwald     btstack_assert(false);
339*86d0910fSMilanka Ringwald     return ERROR_CODE_SUCCESS;
340*86d0910fSMilanka Ringwald }
341*86d0910fSMilanka Ringwald 
342*86d0910fSMilanka 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){
343*86d0910fSMilanka Ringwald     btstack_assert(false);
344*86d0910fSMilanka Ringwald     return ERROR_CODE_SUCCESS;
345*86d0910fSMilanka Ringwald }
346*86d0910fSMilanka Ringwald 
347*86d0910fSMilanka 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){
348*86d0910fSMilanka Ringwald     btstack_assert(false);
349*86d0910fSMilanka Ringwald     return ERROR_CODE_SUCCESS;
350*86d0910fSMilanka Ringwald }
351*86d0910fSMilanka Ringwald 
352af770404SMilanka Ringwald /**
353af770404SMilanka Ringwald  * copied from gatt_client.c - START
354af770404SMilanka Ringwald  */
3550f7fd6c1SMilanka Ringwald void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
3560f7fd6c1SMilanka Ringwald     service->start_group_handle = little_endian_read_16(packet, offset);
3570f7fd6c1SMilanka Ringwald     service->end_group_handle = little_endian_read_16(packet, offset + 2);
3580f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset + 4], service->uuid128);
3590f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(service->uuid128)){
3600f7fd6c1SMilanka Ringwald         service->uuid16 = big_endian_read_32(service->uuid128, 0);
3610f7fd6c1SMilanka Ringwald     } else {
3620f7fd6c1SMilanka Ringwald         service->uuid16 = 0;
3630f7fd6c1SMilanka Ringwald     }
3640f7fd6c1SMilanka Ringwald }
3650f7fd6c1SMilanka Ringwald 
3660f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
3670f7fd6c1SMilanka Ringwald     characteristic->start_handle = little_endian_read_16(packet, offset);
3680f7fd6c1SMilanka Ringwald     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
3690f7fd6c1SMilanka Ringwald     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
3700f7fd6c1SMilanka Ringwald     characteristic->properties = little_endian_read_16(packet, offset + 6);
3710f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+8], characteristic->uuid128);
3720f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
3730f7fd6c1SMilanka Ringwald         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
3740f7fd6c1SMilanka Ringwald     } else {
3750f7fd6c1SMilanka Ringwald         characteristic->uuid16 = 0;
3760f7fd6c1SMilanka Ringwald     }
3770f7fd6c1SMilanka Ringwald }
3780f7fd6c1SMilanka Ringwald 
3790f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
3800f7fd6c1SMilanka Ringwald     descriptor->handle = little_endian_read_16(packet, offset);
3810f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+2], descriptor->uuid128);
3820f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
3830f7fd6c1SMilanka Ringwald         descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
3840f7fd6c1SMilanka Ringwald     } else {
3850f7fd6c1SMilanka Ringwald         descriptor->uuid16 = 0;
3860f7fd6c1SMilanka Ringwald     }
3870f7fd6c1SMilanka Ringwald }
3880f7fd6c1SMilanka Ringwald 
3897e693ad3SMilanka Ringwald static void emit_event(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
390af770404SMilanka Ringwald     if (!callback) return;
3917e693ad3SMilanka Ringwald     if (mock_gatt_client_wrong_con_handle){
3927e693ad3SMilanka Ringwald         little_endian_store_16(packet, 2, 0xFFFF);
3937e693ad3SMilanka Ringwald     }
394af770404SMilanka Ringwald     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
3950f7fd6c1SMilanka Ringwald }
3960f7fd6c1SMilanka Ringwald 
397af770404SMilanka Ringwald static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
398af770404SMilanka Ringwald     // @format H1
399af770404SMilanka Ringwald     uint8_t packet[5];
400af770404SMilanka Ringwald     packet[0] = GATT_EVENT_QUERY_COMPLETE;
401af770404SMilanka Ringwald     packet[1] = 3;
402af770404SMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
403af770404SMilanka Ringwald     packet[4] = att_status;
4047e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
4050f7fd6c1SMilanka Ringwald }
4060f7fd6c1SMilanka Ringwald 
4077da2c1baSMilanka 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){
4087da2c1baSMilanka Ringwald     // @format HX
4097da2c1baSMilanka Ringwald     uint8_t packet[24];
4107da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
4117da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
4127da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
4137da2c1baSMilanka Ringwald     ///
4147da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4, start_group_handle);
4157da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6, end_group_handle);
4167da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[8]);
4177e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
4187da2c1baSMilanka Ringwald }
4197da2c1baSMilanka Ringwald 
4207da2c1baSMilanka 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,
4217da2c1baSMilanka Ringwald                                                         uint16_t properties, const uint8_t * uuid128){
4227da2c1baSMilanka Ringwald     // @format HY
4237da2c1baSMilanka Ringwald     uint8_t packet[28];
4247da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
4257da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
4267da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
4277da2c1baSMilanka Ringwald     ///
4287da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4,  start_handle);
4297da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6,  value_handle);
4307da2c1baSMilanka Ringwald     little_endian_store_16(packet, 8,  end_handle);
4317da2c1baSMilanka Ringwald     little_endian_store_16(packet, 10, properties);
4327da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[12]);
4337e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
4347da2c1baSMilanka Ringwald }
4357da2c1baSMilanka Ringwald 
43676cdba3eSMilanka Ringwald static void emit_gatt_all_characteristic_descriptors_result_event(
43776cdba3eSMilanka Ringwald     gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
43876cdba3eSMilanka Ringwald     // @format HZ
43976cdba3eSMilanka Ringwald     uint8_t packet[22];
44076cdba3eSMilanka Ringwald     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
44176cdba3eSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
44276cdba3eSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
44376cdba3eSMilanka Ringwald     ///
44476cdba3eSMilanka Ringwald     little_endian_store_16(packet, 4,  descriptor_handle);
44576cdba3eSMilanka Ringwald     reverse_128(uuid128, &packet[6]);
4467e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
44776cdba3eSMilanka Ringwald }
44876cdba3eSMilanka Ringwald 
4497e693ad3SMilanka Ringwald static uint8_t event_packet[255];
45076cdba3eSMilanka 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){
45176cdba3eSMilanka Ringwald     // before the value inside the ATT PDU
4527e693ad3SMilanka Ringwald     event_packet[0] = type;
4537e693ad3SMilanka Ringwald     event_packet[1] = 6 + length;
4547e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 2, con_handle);
4557e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 4, attribute_handle);
4567e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 6, length);
4577e693ad3SMilanka Ringwald     memcpy(&event_packet[8], value, length);
4587e693ad3SMilanka Ringwald     return &event_packet[0];
45976cdba3eSMilanka Ringwald }
46076cdba3eSMilanka Ringwald 
4617e693ad3SMilanka Ringwald void mock_gatt_client_send_notification_with_handle(mock_gatt_client_characteristic_t * characteristic, uint16_t value_handle, uint8_t * value_buffer, uint16_t value_len){
4627e693ad3SMilanka Ringwald     btstack_assert(characteristic != NULL);
4637e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification != NULL);
4647e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification->callback != NULL);
4657e693ad3SMilanka Ringwald     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client.con_handle, value_handle, value_buffer, value_len);
4667e693ad3SMilanka Ringwald     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
4677e693ad3SMilanka Ringwald }
4687e693ad3SMilanka Ringwald 
4697e693ad3SMilanka Ringwald void mock_gatt_client_send_notification(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
4707e693ad3SMilanka Ringwald     mock_gatt_client_send_notification_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
4717e693ad3SMilanka Ringwald }
4727e693ad3SMilanka Ringwald 
4737e693ad3SMilanka Ringwald static void mock_gatt_client_send_characteristic_value(gatt_client_t * gatt_client, mock_gatt_client_characteristic_t * characteristic){
4747e693ad3SMilanka 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);
4757e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, 2 + packet[1]);
47676cdba3eSMilanka Ringwald }
47776cdba3eSMilanka Ringwald 
478af770404SMilanka Ringwald /**
479af770404SMilanka Ringwald  * copied from gatt_client.c - END
480af770404SMilanka Ringwald  */
4810f7fd6c1SMilanka Ringwald 
4827e693ad3SMilanka Ringwald void mock_gatt_client_emit_complete(uint8_t status){
4837da2c1baSMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
4847da2c1baSMilanka Ringwald     emit_gatt_complete_event(&gatt_client, status);
4857da2c1baSMilanka Ringwald }
4860f7fd6c1SMilanka Ringwald 
4877e693ad3SMilanka Ringwald void mock_gatt_client_run_once(void){
488af770404SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
48976cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_t * characteristic;
49076cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_descriptor_t * descriptor;
49176cdba3eSMilanka Ringwald 
4927da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
4937da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t characteristic_it;
49476cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t descriptor_it;
49576cdba3eSMilanka Ringwald 
4967da2c1baSMilanka Ringwald     uint8_t uuid128[16];
4977da2c1baSMilanka Ringwald 
498af770404SMilanka Ringwald     switch (mock_gatt_client_state){
499d41a8f51SMilanka Ringwald         case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16:
500af770404SMilanka Ringwald             // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service
501ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){
502ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_services);
503ec1a0daeSMilanka Ringwald                 return;
504ec1a0daeSMilanka Ringwald             }
505ec1a0daeSMilanka Ringwald 
5067da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
5077da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
5087da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
5097da2c1baSMilanka Ringwald                 if (service->uuid16 != mock_gatt_client_uuid) continue;
5107da2c1baSMilanka Ringwald                 mock_gatt_client_last_service = service;
5117da2c1baSMilanka Ringwald                 uuid_add_bluetooth_prefix(uuid128, service->uuid16);
51276cdba3eSMilanka Ringwald                 emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, uuid128);
5137da2c1baSMilanka Ringwald             }
5147da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
5157da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS);
5167da2c1baSMilanka Ringwald             break;
5177da2c1baSMilanka Ringwald 
518d41a8f51SMilanka Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16:
5197da2c1baSMilanka Ringwald             // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic
520ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){
521ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics);
522ec1a0daeSMilanka Ringwald                 return;
523ec1a0daeSMilanka Ringwald             }
524ec1a0daeSMilanka Ringwald 
5257da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
5267da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
5277da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
5287da2c1baSMilanka Ringwald 
5297da2c1baSMilanka Ringwald                 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
5307da2c1baSMilanka Ringwald                 while (btstack_linked_list_iterator_has_next(&characteristic_it)){
5317da2c1baSMilanka Ringwald                     mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
5327da2c1baSMilanka Ringwald                     if (characteristic->uuid16 != mock_gatt_client_uuid) continue;
53376cdba3eSMilanka Ringwald                     if (characteristic->start_handle < mock_gatt_client_start_handle) continue;
53476cdba3eSMilanka Ringwald                     if (characteristic->end_handle > mock_gatt_client_end_handle) continue;
53576cdba3eSMilanka Ringwald 
5367da2c1baSMilanka Ringwald                     uuid_add_bluetooth_prefix(uuid128, characteristic->uuid16);
53776cdba3eSMilanka Ringwald                     emit_gatt_characteristic_query_result_event(&gatt_client,
53876cdba3eSMilanka Ringwald                         characteristic->start_handle, characteristic->value_handle, characteristic->end_handle,
53976cdba3eSMilanka Ringwald                         characteristic->properties, uuid128);
5407da2c1baSMilanka Ringwald                 }
5417da2c1baSMilanka Ringwald             }
5427da2c1baSMilanka Ringwald 
5437da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
5447da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
545af770404SMilanka Ringwald             break;
54676cdba3eSMilanka Ringwald 
54776cdba3eSMilanka Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
54876cdba3eSMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
54976cdba3eSMilanka Ringwald             btstack_assert(characteristic != NULL);
55076cdba3eSMilanka Ringwald 
551ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){
552ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors);
553ec1a0daeSMilanka Ringwald                 return;
554ec1a0daeSMilanka Ringwald             }
555ec1a0daeSMilanka Ringwald 
55676cdba3eSMilanka Ringwald             btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors);
55776cdba3eSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&descriptor_it)){
55876cdba3eSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it);
55976cdba3eSMilanka Ringwald 
56076cdba3eSMilanka Ringwald                 uuid_add_bluetooth_prefix(uuid128, desc->uuid16);
56176cdba3eSMilanka Ringwald                 emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, uuid128);
56276cdba3eSMilanka Ringwald             }
56376cdba3eSMilanka Ringwald 
56476cdba3eSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
56576cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
56676cdba3eSMilanka Ringwald             break;
56776cdba3eSMilanka Ringwald 
56876cdba3eSMilanka Ringwald         case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
56976cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
57076cdba3eSMilanka Ringwald             break;
57176cdba3eSMilanka Ringwald 
57276cdba3eSMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE:
5737e693ad3SMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
5747e693ad3SMilanka Ringwald             btstack_assert(characteristic != NULL);
5757e693ad3SMilanka Ringwald 
5767e693ad3SMilanka Ringwald             mock_gatt_client_send_characteristic_value(&gatt_client, characteristic);
5777e693ad3SMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
5787e693ad3SMilanka Ringwald             break;
5797e693ad3SMilanka Ringwald 
5807e693ad3SMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE:
58176cdba3eSMilanka Ringwald             descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle);
58276cdba3eSMilanka Ringwald             btstack_assert(descriptor != NULL);
58376cdba3eSMilanka Ringwald             btstack_assert(descriptor->value_buffer != NULL);
58476cdba3eSMilanka Ringwald 
58576cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
58676cdba3eSMilanka Ringwald             break;
58776cdba3eSMilanka Ringwald 
588af770404SMilanka Ringwald         default:
589af770404SMilanka Ringwald             btstack_assert(false);
590af770404SMilanka Ringwald             break;
5910f7fd6c1SMilanka Ringwald     }
5927da2c1baSMilanka Ringwald }
5937e693ad3SMilanka Ringwald 
5947e693ad3SMilanka Ringwald void mock_gatt_client_run(void){
5957e693ad3SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
5967e693ad3SMilanka Ringwald     while (mock_gatt_client_state != MOCK_QUERY_IDLE){
5977e693ad3SMilanka Ringwald         mock_gatt_client_run_once();
5987e693ad3SMilanka Ringwald     }
5997da2c1baSMilanka Ringwald     mock_gatt_client_att_error = ERROR_CODE_SUCCESS;
600af770404SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
6010f7fd6c1SMilanka Ringwald }
6027e693ad3SMilanka Ringwald 
6037e693ad3SMilanka Ringwald void mock_gatt_client_emit_dummy_event(void){
6047e693ad3SMilanka Ringwald         // @format H1
6057e693ad3SMilanka Ringwald     uint8_t packet[2];
6067e693ad3SMilanka Ringwald     packet[0] = 0;
6077e693ad3SMilanka Ringwald     packet[1] = 0;
6087e693ad3SMilanka Ringwald     emit_event(gatt_client.callback, packet, sizeof(packet));
6097e693ad3SMilanka Ringwald }
610