xref: /btstack/test/mock/mock_gatt_client.c (revision 76cdba3e40653998428b9e590094c54620ca56b2)
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "btstack_debug.h"
6 #include "mock_gatt_client.h"
7 
8 #include "CppUTest/TestHarness.h"
9 #include "CppUTestExt/MockSupport.h"
10 
11 static enum {
12     MOCK_QUERY_IDLE = 0,
13     MOCK_QUERY_DISCOVER_PRIMARY_SERVICES,
14     MOCK_QUERY_DISCOVER_CHARACTERISTICS,
15     MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS,
16     MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION,
17     MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE
18 } mock_gatt_client_state;
19 
20 static uint16_t mock_gatt_client_att_handle_generator;
21 
22 static uint8_t mock_gatt_client_att_error;
23 static uint16_t mock_gatt_client_uuid;
24 static uint16_t mock_gatt_client_value_handle;
25 static uint16_t mock_gatt_client_start_handle;
26 static uint16_t mock_gatt_client_end_handle;
27 
28 static gatt_client_t gatt_client;
29 
30 static btstack_linked_list_t mock_gatt_client_services;
31 
32 static mock_gatt_client_service_t * mock_gatt_client_last_service;
33 static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic;
34 
35 void mock_gatt_client_reset(void){
36     mock_gatt_client_att_error = 0;
37     mock_gatt_client_state = MOCK_QUERY_IDLE;
38     mock_gatt_client_att_handle_generator = 0;
39     mock_gatt_client_last_service = NULL;
40 
41     btstack_linked_list_iterator_t service_it;
42     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
43     while (btstack_linked_list_iterator_has_next(&service_it)){
44         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
45         btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service);
46 
47         btstack_linked_list_iterator_t characteristic_it;
48         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
49         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
50             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
51             btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic);
52 
53             btstack_linked_list_iterator_t desc_it;
54             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
55             while (btstack_linked_list_iterator_has_next(&desc_it)){
56                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
57                 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc);
58                 free(desc);
59             }
60             free(characteristic);
61         }
62         free(service);
63     }
64 }
65 
66 void mock_gatt_client_dump_services(void){
67     btstack_linked_list_iterator_t service_it;
68     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
69     while (btstack_linked_list_iterator_has_next(&service_it)){
70         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
71         printf("0x%02x: START SERVICE 0%02x\n", service->start_group_handle, service->uuid16);
72 
73         btstack_linked_list_iterator_t characteristic_it;
74         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
75         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
76             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
77             printf("0x%02x:   START CHR 0%02x\n", characteristic->start_handle, characteristic->uuid16);
78             printf("0x%02x:   VALUE HANDLE CHR 0%02x\n", characteristic->value_handle, characteristic->uuid16);
79 
80             btstack_linked_list_iterator_t desc_it;
81             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
82             while (btstack_linked_list_iterator_has_next(&desc_it)){
83                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
84                 printf("0x%02x:     DESC 0x%02x\n", desc->handle, desc->uuid16);
85             }
86 
87             printf("0x%02x:   END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16);
88 
89         }
90         printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16);
91 
92     }
93 }
94 
95 mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){
96     // set lsat group handle
97     // create new service
98     mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t));
99     memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t));
100     mock_gatt_client_last_service->uuid16 = service_uuid;
101     mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++;
102     mock_gatt_client_last_service->end_group_handle = 0xffff;
103     btstack_linked_list_add(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service);
104     mock_gatt_client_last_characteristic = NULL;
105     return mock_gatt_client_last_service;
106 }
107 
108 mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){
109     btstack_assert(mock_gatt_client_last_service != NULL);
110     mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t));
111     memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t));
112     mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid;
113     mock_gatt_client_last_characteristic->properties = properties;
114     mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++;
115     mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++;
116     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle;
117     btstack_linked_list_add(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic);
118     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
119     return mock_gatt_client_last_characteristic;
120 }
121 
122 mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){
123     btstack_assert(mock_gatt_client_last_characteristic != NULL);
124     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t));
125     memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t));
126     desc->uuid16 = descriptor_uuid;
127     desc->handle = mock_gatt_client_att_handle_generator++;
128     btstack_linked_list_add(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc);
129     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1;
130     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
131     return desc;
132 }
133 
134 static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){
135     btstack_linked_list_iterator_t service_it;
136     btstack_linked_list_iterator_t characteristic_it;
137 
138     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
139     while (btstack_linked_list_iterator_has_next(&service_it)){
140         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
141 
142         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
143         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
144             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
145             if (characteristic->value_handle != value_handle) continue;
146             return characteristic;
147         }
148     }
149     return NULL;
150 }
151 
152 static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){
153     btstack_linked_list_iterator_t service_it;
154     btstack_linked_list_iterator_t characteristic_it;
155 
156     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
157     while (btstack_linked_list_iterator_has_next(&service_it)){
158         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
159 
160         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
161         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
162             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
163 
164             btstack_linked_list_iterator_t desc_it;
165             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
166             while (btstack_linked_list_iterator_has_next(&desc_it)){
167                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
168                 if (desc->handle != handle) continue;
169                 return desc;
170             }
171         }
172     }
173     return NULL;
174 }
175 
176 
177 void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){
178     btstack_assert(descriptor != NULL);
179     descriptor->value_buffer = value_buffer;
180     descriptor->value_len = value_len;
181 }
182 
183 // simulate erro
184 void mock_gatt_client_simulate_att_error(uint8_t att_error){
185     mock_gatt_client_att_error = att_error;
186 }
187 
188 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
189     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES;
190     mock_gatt_client_uuid = uuid16;
191 
192     gatt_client.callback = callback;
193     gatt_client.con_handle = con_handle;
194     return ERROR_CODE_SUCCESS;
195 }
196 
197 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){
198     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS;
199     mock_gatt_client_uuid = uuid16;
200     mock_gatt_client_start_handle = start_handle;
201     mock_gatt_client_end_handle = end_handle;
202 
203     gatt_client.callback = callback;
204     gatt_client.con_handle = con_handle;
205     return ERROR_CODE_SUCCESS;
206 }
207 
208 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
209     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS;
210     mock_gatt_client_value_handle = characteristic->value_handle;
211 
212     gatt_client.callback = callback;
213     gatt_client.con_handle = con_handle;
214     return ERROR_CODE_SUCCESS;
215 }
216 
217 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){
218     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
219     mock_gatt_client_uuid = characteristic->uuid16;
220 
221     gatt_client.callback = callback;
222     gatt_client.con_handle = con_handle;
223     return ERROR_CODE_SUCCESS;
224 }
225 
226 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){
227     notification->callback = callback;
228     notification->con_handle = con_handle;
229 
230     if (characteristic == NULL){
231         // 'all characteristics': not used yet
232         btstack_assert(false);
233     } else {
234         notification->attribute_handle = characteristic->value_handle;
235     }
236 
237     // finc our characteristic and set point to notification
238 }
239 
240 
241 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){
242     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
243     mock_gatt_client_value_handle = value_handle;
244     return ERROR_CODE_SUCCESS;
245 }
246 
247 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
248     btstack_assert(false);
249     return ERROR_CODE_SUCCESS;
250 }
251 
252 void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
253     btstack_assert(false);
254 }
255 
256 /**
257  * copied from gatt_client.c - START
258  */
259 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
260     service->start_group_handle = little_endian_read_16(packet, offset);
261     service->end_group_handle = little_endian_read_16(packet, offset + 2);
262     reverse_128(&packet[offset + 4], service->uuid128);
263     if (uuid_has_bluetooth_prefix(service->uuid128)){
264         service->uuid16 = big_endian_read_32(service->uuid128, 0);
265     } else {
266         service->uuid16 = 0;
267     }
268 }
269 
270 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
271     characteristic->start_handle = little_endian_read_16(packet, offset);
272     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
273     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
274     characteristic->properties = little_endian_read_16(packet, offset + 6);
275     reverse_128(&packet[offset+8], characteristic->uuid128);
276     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
277         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
278     } else {
279         characteristic->uuid16 = 0;
280     }
281 }
282 
283 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
284     descriptor->handle = little_endian_read_16(packet, offset);
285     reverse_128(&packet[offset+2], descriptor->uuid128);
286     if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
287         descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
288     } else {
289         descriptor->uuid16 = 0;
290     }
291 }
292 
293 static void emit_event_new(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
294     if (!callback) return;
295     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
296 }
297 
298 static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
299     // @format H1
300     uint8_t packet[5];
301     packet[0] = GATT_EVENT_QUERY_COMPLETE;
302     packet[1] = 3;
303     little_endian_store_16(packet, 2, gatt_client->con_handle);
304     packet[4] = att_status;
305     emit_event_new(gatt_client->callback, packet, sizeof(packet));
306 }
307 
308 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){
309     // @format HX
310     uint8_t packet[24];
311     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
312     packet[1] = sizeof(packet) - 2u;
313     little_endian_store_16(packet, 2, gatt_client->con_handle);
314     ///
315     little_endian_store_16(packet, 4, start_group_handle);
316     little_endian_store_16(packet, 6, end_group_handle);
317     reverse_128(uuid128, &packet[8]);
318     emit_event_new(gatt_client->callback, packet, sizeof(packet));
319 }
320 
321 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,
322                                                         uint16_t properties, const uint8_t * uuid128){
323     // @format HY
324     uint8_t packet[28];
325     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
326     packet[1] = sizeof(packet) - 2u;
327     little_endian_store_16(packet, 2, gatt_client->con_handle);
328     ///
329     little_endian_store_16(packet, 4,  start_handle);
330     little_endian_store_16(packet, 6,  value_handle);
331     little_endian_store_16(packet, 8,  end_handle);
332     little_endian_store_16(packet, 10, properties);
333     reverse_128(uuid128, &packet[12]);
334     emit_event_new(gatt_client->callback, packet, sizeof(packet));
335 }
336 
337 static void emit_gatt_all_characteristic_descriptors_result_event(
338         gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
339     // @format HZ
340     uint8_t packet[22];
341     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
342     packet[1] = sizeof(packet) - 2u;
343     little_endian_store_16(packet, 2, gatt_client->con_handle);
344     ///
345     little_endian_store_16(packet, 4,  descriptor_handle);
346     reverse_128(uuid128, &packet[6]);
347     emit_event_new(gatt_client->callback, packet, sizeof(packet));
348 }
349 
350 
351 static const int characteristic_value_event_header_size = 8;
352 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){
353     // before the value inside the ATT PDU
354     uint8_t * packet = value - characteristic_value_event_header_size;
355     packet[0] = type;
356     packet[1] = characteristic_value_event_header_size - 2 + length;
357     little_endian_store_16(packet, 2, con_handle);
358     little_endian_store_16(packet, 4, attribute_handle);
359     little_endian_store_16(packet, 6, length);
360     return packet;
361 }
362 
363 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
364 static void report_gatt_characteristic_value(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * value, uint16_t length){
365     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, gatt_client->con_handle, attribute_handle, value, length);
366     emit_event_new(gatt_client->callback, packet, characteristic_value_event_header_size + length);
367 }
368 
369 /**
370  * copied from gatt_client.c - END
371  */
372 
373 static void mock_gatt_client_emit_complete(uint8_t status){
374     mock_gatt_client_state = MOCK_QUERY_IDLE;
375     emit_gatt_complete_event(&gatt_client, status);
376 }
377 
378 void mock_gatt_client_run(void){
379     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
380     mock_gatt_client_characteristic_t * characteristic;
381     mock_gatt_client_characteristic_descriptor_t * descriptor;
382 
383     btstack_linked_list_iterator_t service_it;
384     btstack_linked_list_iterator_t characteristic_it;
385     btstack_linked_list_iterator_t descriptor_it;
386 
387     uint8_t uuid128[16];
388 
389     while (mock_gatt_client_state != MOCK_QUERY_IDLE){
390         switch (mock_gatt_client_state){
391             case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES:
392                 // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service
393                 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
394                 while (btstack_linked_list_iterator_has_next(&service_it)){
395                     mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
396                     if (service->uuid16 != mock_gatt_client_uuid) continue;
397                     mock_gatt_client_last_service = service;
398                     uuid_add_bluetooth_prefix(uuid128, service->uuid16);
399                     emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, uuid128);
400                 }
401                 // emit GATT_EVENT_QUERY_COMPLETE
402                 mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS);
403                 break;
404 
405             case MOCK_QUERY_DISCOVER_CHARACTERISTICS:
406                 // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic
407                 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
408                 while (btstack_linked_list_iterator_has_next(&service_it)){
409                     mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
410 
411                     btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
412                     while (btstack_linked_list_iterator_has_next(&characteristic_it)){
413                         mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
414                         if (characteristic->uuid16 != mock_gatt_client_uuid) continue;
415                         if (characteristic->start_handle < mock_gatt_client_start_handle) continue;
416                         if (characteristic->end_handle > mock_gatt_client_end_handle) continue;
417 
418                         uuid_add_bluetooth_prefix(uuid128, characteristic->uuid16);
419                         emit_gatt_characteristic_query_result_event(&gatt_client,
420                             characteristic->start_handle, characteristic->value_handle, characteristic->end_handle,
421                             characteristic->properties, uuid128);
422                     }
423                 }
424 
425                 // emit GATT_EVENT_QUERY_COMPLETE
426                 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
427                 break;
428 
429             case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
430                 characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
431                 btstack_assert(characteristic != NULL);
432 
433                 btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors);
434                 while (btstack_linked_list_iterator_has_next(&descriptor_it)){
435                     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it);
436 
437                     uuid_add_bluetooth_prefix(uuid128, desc->uuid16);
438                     emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, uuid128);
439                 }
440 
441 
442                 // emit GATT_EVENT_QUERY_COMPLETE
443                 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
444                 break;
445 
446             case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
447                 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
448                 break;
449 
450             case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE:
451                 descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle);
452                 btstack_assert(descriptor != NULL);
453                 btstack_assert(descriptor->value_buffer != NULL);
454 
455                 report_gatt_characteristic_value(&gatt_client, descriptor->handle, descriptor->value_buffer, descriptor->value_len);
456                 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
457                 break;
458 
459             default:
460                 btstack_assert(false);
461                 break;
462         }
463     }
464     mock_gatt_client_att_error = ERROR_CODE_SUCCESS;
465     mock_gatt_client_state = MOCK_QUERY_IDLE;
466 }