xref: /btstack/test/mock/mock_gatt_client.c (revision 7e693ad3d4a56e38a8a8e0beafd705c64fc017fb)
10f7fd6c1SMilanka Ringwald #include <stdint.h>
20f7fd6c1SMilanka Ringwald #include <stdio.h>
30f7fd6c1SMilanka Ringwald #include <string.h>
40f7fd6c1SMilanka Ringwald 
5af770404SMilanka Ringwald #include "btstack_debug.h"
6*7e693ad3SMilanka 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,
18*7e693ad3SMilanka Ringwald     MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE,
19*7e693ad3SMilanka 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;
40*7e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_con_handle;
41*7e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_value_handle;
42ec1a0daeSMilanka Ringwald 
43*7e693ad3SMilanka 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;
47*7e693ad3SMilanka Ringwald 
48*7e693ad3SMilanka Ringwald     mock_gatt_client_wrong_con_handle = false;
49*7e693ad3SMilanka 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 
58*7e693ad3SMilanka 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 
95*7e693ad3SMilanka Ringwald void mock_gatt_client_simulate_invalid_con_handle(void){
96*7e693ad3SMilanka Ringwald     mock_gatt_client_wrong_con_handle = true;
97*7e693ad3SMilanka Ringwald }
98*7e693ad3SMilanka Ringwald void mock_gatt_client_simulate_invalid_value_handle(void){
99*7e693ad3SMilanka Ringwald     mock_gatt_client_wrong_value_handle = true;
100*7e693ad3SMilanka Ringwald }
101*7e693ad3SMilanka Ringwald 
102*7e693ad3SMilanka Ringwald void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){
103*7e693ad3SMilanka Ringwald     if (command_allowed){
104*7e693ad3SMilanka Ringwald         characteristic->notification_status_code = ERROR_CODE_SUCCESS;
105*7e693ad3SMilanka Ringwald     } else {
106*7e693ad3SMilanka Ringwald         characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED;
107*7e693ad3SMilanka Ringwald     }
108*7e693ad3SMilanka Ringwald }
109*7e693ad3SMilanka 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 
221*7e693ad3SMilanka 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 
227*7e693ad3SMilanka Ringwald void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
228*7e693ad3SMilanka Ringwald     btstack_assert(characteristic != NULL);
229*7e693ad3SMilanka Ringwald     characteristic->value_buffer = value_buffer;
230*7e693ad3SMilanka Ringwald     characteristic->value_len = value_len;
231*7e693ad3SMilanka Ringwald }
232*7e693ad3SMilanka Ringwald 
233*7e693ad3SMilanka 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 
267*7e693ad3SMilanka 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){
268*7e693ad3SMilanka Ringwald     btstack_assert(notification != NULL);
269*7e693ad3SMilanka Ringwald     btstack_assert(&callback != NULL);
270*7e693ad3SMilanka Ringwald 
271*7e693ad3SMilanka Ringwald     notification->callback = callback;
272*7e693ad3SMilanka Ringwald     notification->con_handle = con_handle;
273*7e693ad3SMilanka Ringwald 
274*7e693ad3SMilanka Ringwald 
275*7e693ad3SMilanka Ringwald     if (characteristic == NULL){
276*7e693ad3SMilanka Ringwald         // 'all characteristics': not used yet
277*7e693ad3SMilanka Ringwald         btstack_assert(false);
278*7e693ad3SMilanka Ringwald     } else {
279*7e693ad3SMilanka Ringwald         mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
280*7e693ad3SMilanka Ringwald         btstack_assert(mock_characteristic != NULL);
281*7e693ad3SMilanka Ringwald 
282*7e693ad3SMilanka Ringwald         notification->attribute_handle = characteristic->value_handle;
283*7e693ad3SMilanka Ringwald         mock_characteristic->notification = notification;
284*7e693ad3SMilanka Ringwald     }
285*7e693ad3SMilanka Ringwald }
286*7e693ad3SMilanka 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){
288*7e693ad3SMilanka Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
289*7e693ad3SMilanka Ringwald     btstack_assert(mock_characteristic != NULL);
290*7e693ad3SMilanka Ringwald 
291*7e693ad3SMilanka Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
292*7e693ad3SMilanka Ringwald         return mock_characteristic->notification_status_code;
293*7e693ad3SMilanka Ringwald     }
294*7e693ad3SMilanka 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;
305*7e693ad3SMilanka Ringwald 
306*7e693ad3SMilanka Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
307*7e693ad3SMilanka Ringwald     btstack_assert(mock_characteristic != NULL);
308*7e693ad3SMilanka Ringwald 
309*7e693ad3SMilanka Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
310*7e693ad3SMilanka Ringwald     gatt_client.callback = callback;
311*7e693ad3SMilanka 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 
319*7e693ad3SMilanka 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 
322*7e693ad3SMilanka Ringwald     gatt_client.callback = callback;
323*7e693ad3SMilanka 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 
328*7e693ad3SMilanka 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){
329*7e693ad3SMilanka Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE;
330*7e693ad3SMilanka Ringwald     mock_gatt_client_value_handle = descriptor_handle;
331*7e693ad3SMilanka Ringwald     return ERROR_CODE_SUCCESS;
332*7e693ad3SMilanka Ringwald }
333*7e693ad3SMilanka Ringwald 
334af770404SMilanka Ringwald void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
335af770404SMilanka Ringwald }
336af770404SMilanka Ringwald 
337af770404SMilanka Ringwald /**
338af770404SMilanka Ringwald  * copied from gatt_client.c - START
339af770404SMilanka Ringwald  */
3400f7fd6c1SMilanka Ringwald void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
3410f7fd6c1SMilanka Ringwald     service->start_group_handle = little_endian_read_16(packet, offset);
3420f7fd6c1SMilanka Ringwald     service->end_group_handle = little_endian_read_16(packet, offset + 2);
3430f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset + 4], service->uuid128);
3440f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(service->uuid128)){
3450f7fd6c1SMilanka Ringwald         service->uuid16 = big_endian_read_32(service->uuid128, 0);
3460f7fd6c1SMilanka Ringwald     } else {
3470f7fd6c1SMilanka Ringwald         service->uuid16 = 0;
3480f7fd6c1SMilanka Ringwald     }
3490f7fd6c1SMilanka Ringwald }
3500f7fd6c1SMilanka Ringwald 
3510f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
3520f7fd6c1SMilanka Ringwald     characteristic->start_handle = little_endian_read_16(packet, offset);
3530f7fd6c1SMilanka Ringwald     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
3540f7fd6c1SMilanka Ringwald     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
3550f7fd6c1SMilanka Ringwald     characteristic->properties = little_endian_read_16(packet, offset + 6);
3560f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+8], characteristic->uuid128);
3570f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
3580f7fd6c1SMilanka Ringwald         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
3590f7fd6c1SMilanka Ringwald     } else {
3600f7fd6c1SMilanka Ringwald         characteristic->uuid16 = 0;
3610f7fd6c1SMilanka Ringwald     }
3620f7fd6c1SMilanka Ringwald }
3630f7fd6c1SMilanka Ringwald 
3640f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
3650f7fd6c1SMilanka Ringwald     descriptor->handle = little_endian_read_16(packet, offset);
3660f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+2], descriptor->uuid128);
3670f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
3680f7fd6c1SMilanka Ringwald         descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
3690f7fd6c1SMilanka Ringwald     } else {
3700f7fd6c1SMilanka Ringwald         descriptor->uuid16 = 0;
3710f7fd6c1SMilanka Ringwald     }
3720f7fd6c1SMilanka Ringwald }
3730f7fd6c1SMilanka Ringwald 
374*7e693ad3SMilanka Ringwald static void emit_event(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
375af770404SMilanka Ringwald     if (!callback) return;
376*7e693ad3SMilanka Ringwald     if (mock_gatt_client_wrong_con_handle){
377*7e693ad3SMilanka Ringwald         little_endian_store_16(packet, 2, 0xFFFF);
378*7e693ad3SMilanka Ringwald     }
379af770404SMilanka Ringwald     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
3800f7fd6c1SMilanka Ringwald }
3810f7fd6c1SMilanka Ringwald 
382af770404SMilanka Ringwald static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
383af770404SMilanka Ringwald     // @format H1
384af770404SMilanka Ringwald     uint8_t packet[5];
385af770404SMilanka Ringwald     packet[0] = GATT_EVENT_QUERY_COMPLETE;
386af770404SMilanka Ringwald     packet[1] = 3;
387af770404SMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
388af770404SMilanka Ringwald     packet[4] = att_status;
389*7e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
3900f7fd6c1SMilanka Ringwald }
3910f7fd6c1SMilanka Ringwald 
3927da2c1baSMilanka 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){
3937da2c1baSMilanka Ringwald     // @format HX
3947da2c1baSMilanka Ringwald     uint8_t packet[24];
3957da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
3967da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
3977da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
3987da2c1baSMilanka Ringwald     ///
3997da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4, start_group_handle);
4007da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6, end_group_handle);
4017da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[8]);
402*7e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
4037da2c1baSMilanka Ringwald }
4047da2c1baSMilanka Ringwald 
4057da2c1baSMilanka 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,
4067da2c1baSMilanka Ringwald                                                         uint16_t properties, const uint8_t * uuid128){
4077da2c1baSMilanka Ringwald     // @format HY
4087da2c1baSMilanka Ringwald     uint8_t packet[28];
4097da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
4107da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
4117da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
4127da2c1baSMilanka Ringwald     ///
4137da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4,  start_handle);
4147da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6,  value_handle);
4157da2c1baSMilanka Ringwald     little_endian_store_16(packet, 8,  end_handle);
4167da2c1baSMilanka Ringwald     little_endian_store_16(packet, 10, properties);
4177da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[12]);
418*7e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
4197da2c1baSMilanka Ringwald }
4207da2c1baSMilanka Ringwald 
42176cdba3eSMilanka Ringwald static void emit_gatt_all_characteristic_descriptors_result_event(
42276cdba3eSMilanka Ringwald     gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
42376cdba3eSMilanka Ringwald     // @format HZ
42476cdba3eSMilanka Ringwald     uint8_t packet[22];
42576cdba3eSMilanka Ringwald     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
42676cdba3eSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
42776cdba3eSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
42876cdba3eSMilanka Ringwald     ///
42976cdba3eSMilanka Ringwald     little_endian_store_16(packet, 4,  descriptor_handle);
43076cdba3eSMilanka Ringwald     reverse_128(uuid128, &packet[6]);
431*7e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
43276cdba3eSMilanka Ringwald }
43376cdba3eSMilanka Ringwald 
434*7e693ad3SMilanka Ringwald static uint8_t event_packet[255];
43576cdba3eSMilanka 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){
43676cdba3eSMilanka Ringwald     // before the value inside the ATT PDU
437*7e693ad3SMilanka Ringwald     event_packet[0] = type;
438*7e693ad3SMilanka Ringwald     event_packet[1] = 6 + length;
439*7e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 2, con_handle);
440*7e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 4, attribute_handle);
441*7e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 6, length);
442*7e693ad3SMilanka Ringwald     memcpy(&event_packet[8], value, length);
443*7e693ad3SMilanka Ringwald     return &event_packet[0];
44476cdba3eSMilanka Ringwald }
44576cdba3eSMilanka Ringwald 
446*7e693ad3SMilanka 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){
447*7e693ad3SMilanka Ringwald     btstack_assert(characteristic != NULL);
448*7e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification != NULL);
449*7e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification->callback != NULL);
450*7e693ad3SMilanka Ringwald     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client.con_handle, value_handle, value_buffer, value_len);
451*7e693ad3SMilanka Ringwald     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
452*7e693ad3SMilanka Ringwald }
453*7e693ad3SMilanka Ringwald 
454*7e693ad3SMilanka Ringwald void mock_gatt_client_send_notification(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
455*7e693ad3SMilanka Ringwald     mock_gatt_client_send_notification_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
456*7e693ad3SMilanka Ringwald }
457*7e693ad3SMilanka Ringwald 
458*7e693ad3SMilanka Ringwald static void mock_gatt_client_send_characteristic_value(gatt_client_t * gatt_client, mock_gatt_client_characteristic_t * characteristic){
459*7e693ad3SMilanka 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);
460*7e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, 2 + packet[1]);
46176cdba3eSMilanka Ringwald }
46276cdba3eSMilanka Ringwald 
463af770404SMilanka Ringwald /**
464af770404SMilanka Ringwald  * copied from gatt_client.c - END
465af770404SMilanka Ringwald  */
4660f7fd6c1SMilanka Ringwald 
467*7e693ad3SMilanka Ringwald void mock_gatt_client_emit_complete(uint8_t status){
4687da2c1baSMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
4697da2c1baSMilanka Ringwald     emit_gatt_complete_event(&gatt_client, status);
4707da2c1baSMilanka Ringwald }
4710f7fd6c1SMilanka Ringwald 
472*7e693ad3SMilanka Ringwald void mock_gatt_client_run_once(void){
473af770404SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
47476cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_t * characteristic;
47576cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_descriptor_t * descriptor;
47676cdba3eSMilanka Ringwald 
4777da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
4787da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t characteristic_it;
47976cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t descriptor_it;
48076cdba3eSMilanka Ringwald 
4817da2c1baSMilanka Ringwald     uint8_t uuid128[16];
4827da2c1baSMilanka Ringwald 
483af770404SMilanka Ringwald     switch (mock_gatt_client_state){
484d41a8f51SMilanka Ringwald         case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16:
485af770404SMilanka Ringwald             // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service
486ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){
487ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_services);
488ec1a0daeSMilanka Ringwald                 return;
489ec1a0daeSMilanka Ringwald             }
490ec1a0daeSMilanka Ringwald 
4917da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
4927da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
4937da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
4947da2c1baSMilanka Ringwald                 if (service->uuid16 != mock_gatt_client_uuid) continue;
4957da2c1baSMilanka Ringwald                 mock_gatt_client_last_service = service;
4967da2c1baSMilanka Ringwald                 uuid_add_bluetooth_prefix(uuid128, service->uuid16);
49776cdba3eSMilanka Ringwald                 emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, uuid128);
4987da2c1baSMilanka Ringwald             }
4997da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
5007da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS);
5017da2c1baSMilanka Ringwald             break;
5027da2c1baSMilanka Ringwald 
503d41a8f51SMilanka Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16:
5047da2c1baSMilanka Ringwald             // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic
505ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){
506ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics);
507ec1a0daeSMilanka Ringwald                 return;
508ec1a0daeSMilanka Ringwald             }
509ec1a0daeSMilanka Ringwald 
5107da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
5117da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
5127da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
5137da2c1baSMilanka Ringwald 
5147da2c1baSMilanka Ringwald                 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
5157da2c1baSMilanka Ringwald                 while (btstack_linked_list_iterator_has_next(&characteristic_it)){
5167da2c1baSMilanka Ringwald                     mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
5177da2c1baSMilanka Ringwald                     if (characteristic->uuid16 != mock_gatt_client_uuid) continue;
51876cdba3eSMilanka Ringwald                     if (characteristic->start_handle < mock_gatt_client_start_handle) continue;
51976cdba3eSMilanka Ringwald                     if (characteristic->end_handle > mock_gatt_client_end_handle) continue;
52076cdba3eSMilanka Ringwald 
5217da2c1baSMilanka Ringwald                     uuid_add_bluetooth_prefix(uuid128, characteristic->uuid16);
52276cdba3eSMilanka Ringwald                     emit_gatt_characteristic_query_result_event(&gatt_client,
52376cdba3eSMilanka Ringwald                         characteristic->start_handle, characteristic->value_handle, characteristic->end_handle,
52476cdba3eSMilanka Ringwald                         characteristic->properties, uuid128);
5257da2c1baSMilanka Ringwald                 }
5267da2c1baSMilanka Ringwald             }
5277da2c1baSMilanka Ringwald 
5287da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
5297da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
530af770404SMilanka Ringwald             break;
53176cdba3eSMilanka Ringwald 
53276cdba3eSMilanka Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
53376cdba3eSMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
53476cdba3eSMilanka Ringwald             btstack_assert(characteristic != NULL);
53576cdba3eSMilanka Ringwald 
536ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){
537ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors);
538ec1a0daeSMilanka Ringwald                 return;
539ec1a0daeSMilanka Ringwald             }
540ec1a0daeSMilanka Ringwald 
54176cdba3eSMilanka Ringwald             btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors);
54276cdba3eSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&descriptor_it)){
54376cdba3eSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it);
54476cdba3eSMilanka Ringwald 
54576cdba3eSMilanka Ringwald                 uuid_add_bluetooth_prefix(uuid128, desc->uuid16);
54676cdba3eSMilanka Ringwald                 emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, uuid128);
54776cdba3eSMilanka Ringwald             }
54876cdba3eSMilanka Ringwald 
54976cdba3eSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
55076cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
55176cdba3eSMilanka Ringwald             break;
55276cdba3eSMilanka Ringwald 
55376cdba3eSMilanka Ringwald         case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
55476cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
55576cdba3eSMilanka Ringwald             break;
55676cdba3eSMilanka Ringwald 
55776cdba3eSMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE:
558*7e693ad3SMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
559*7e693ad3SMilanka Ringwald             btstack_assert(characteristic != NULL);
560*7e693ad3SMilanka Ringwald 
561*7e693ad3SMilanka Ringwald             mock_gatt_client_send_characteristic_value(&gatt_client, characteristic);
562*7e693ad3SMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
563*7e693ad3SMilanka Ringwald             break;
564*7e693ad3SMilanka Ringwald 
565*7e693ad3SMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE:
56676cdba3eSMilanka Ringwald             descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle);
56776cdba3eSMilanka Ringwald             btstack_assert(descriptor != NULL);
56876cdba3eSMilanka Ringwald             btstack_assert(descriptor->value_buffer != NULL);
56976cdba3eSMilanka Ringwald 
57076cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
57176cdba3eSMilanka Ringwald             break;
57276cdba3eSMilanka Ringwald 
573af770404SMilanka Ringwald         default:
574af770404SMilanka Ringwald             btstack_assert(false);
575af770404SMilanka Ringwald             break;
5760f7fd6c1SMilanka Ringwald     }
5777da2c1baSMilanka Ringwald }
578*7e693ad3SMilanka Ringwald 
579*7e693ad3SMilanka Ringwald void mock_gatt_client_run(void){
580*7e693ad3SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
581*7e693ad3SMilanka Ringwald     while (mock_gatt_client_state != MOCK_QUERY_IDLE){
582*7e693ad3SMilanka Ringwald         mock_gatt_client_run_once();
583*7e693ad3SMilanka Ringwald     }
5847da2c1baSMilanka Ringwald     mock_gatt_client_att_error = ERROR_CODE_SUCCESS;
585af770404SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
5860f7fd6c1SMilanka Ringwald }
587*7e693ad3SMilanka Ringwald 
588*7e693ad3SMilanka Ringwald void mock_gatt_client_emit_dummy_event(void){
589*7e693ad3SMilanka Ringwald         // @format H1
590*7e693ad3SMilanka Ringwald     uint8_t packet[2];
591*7e693ad3SMilanka Ringwald     packet[0] = 0;
592*7e693ad3SMilanka Ringwald     packet[1] = 0;
593*7e693ad3SMilanka Ringwald     emit_event(gatt_client.callback, packet, sizeof(packet));
594*7e693ad3SMilanka Ringwald }
595