xref: /btstack/test/mock/mock_gatt_client.c (revision bd8c526a6c11c1bc45c8e8569e5ad37961cba5a5)
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "btstack_debug.h"
6 #include "bluetooth_gatt.h"
7 #include "mock_gatt_client.h"
8 
9 //#include "CppUTest/TestHarness.h"
10 //#include "CppUTestExt/MockSupport.h"
11 
12 static enum {
13     MOCK_QUERY_IDLE = 0,
14     MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID,
15     MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID,
16     MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS,
17     MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS,
18     MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION,
19     MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE,
20     MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE
21 } mock_gatt_client_state;
22 
23 static uint16_t mock_gatt_client_att_handle_generator;
24 
25 static uint8_t mock_gatt_client_att_error;
26 static uint8_t  mock_gatt_client_uuid128[16];
27 static uint16_t mock_gatt_client_value_handle;
28 static uint16_t mock_gatt_client_start_handle;
29 static uint16_t mock_gatt_client_end_handle;
30 
31 static gatt_client_t gatt_client;
32 
33 static btstack_linked_list_t mock_gatt_client_services;
34 
35 static mock_gatt_client_service_t * mock_gatt_client_last_service;
36 static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic;
37 
38 static uint8_t moc_att_error_code_discover_services;
39 static uint8_t moc_att_error_code_discover_characteristics;
40 static uint8_t moc_att_error_code_discover_characteristic_descriptors;
41 static uint8_t moc_att_error_code_read_value_characteristics;
42 
43 /**
44  * copied from gatt_client.c - START
45  */
46 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
47     service->start_group_handle = little_endian_read_16(packet, offset);
48     service->end_group_handle = little_endian_read_16(packet, offset + 2);
49     reverse_128(&packet[offset + 4], service->uuid128);
50     if (uuid_has_bluetooth_prefix(service->uuid128)){
51         service->uuid16 = big_endian_read_32(service->uuid128, 0);
52     } else {
53         service->uuid16 = 0;
54     }
55 }
56 
57 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
58     characteristic->start_handle = little_endian_read_16(packet, offset);
59     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
60     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
61     characteristic->properties = little_endian_read_16(packet, offset + 6);
62     reverse_128(&packet[offset+8], characteristic->uuid128);
63     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
64         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
65     } else {
66         characteristic->uuid16 = 0;
67     }
68 }
69 
70 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
71     descriptor->handle = little_endian_read_16(packet, offset);
72     reverse_128(&packet[offset+2], descriptor->uuid128);
73     if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
74         descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
75     } else {
76         descriptor->uuid16 = 0;
77     }
78 }
79 
80 static void emit_event(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
81     if (!callback) return;
82     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
83 }
84 
85 static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
86     printf("emit complete handle %02x\n", gatt_client->con_handle);
87     // @format H1
88     uint8_t packet[5];
89     packet[0] = GATT_EVENT_QUERY_COMPLETE;
90     packet[1] = 3;
91     little_endian_store_16(packet, 2, gatt_client->con_handle);
92     packet[4] = att_status;
93     emit_event(gatt_client->callback, packet, sizeof(packet));
94 }
95 
96 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){
97     // @format HX
98     uint8_t packet[24];
99     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
100     packet[1] = sizeof(packet) - 2u;
101     little_endian_store_16(packet, 2, gatt_client->con_handle);
102     ///
103     little_endian_store_16(packet, 4, start_group_handle);
104     little_endian_store_16(packet, 6, end_group_handle);
105     reverse_128(uuid128, &packet[8]);
106     emit_event(gatt_client->callback, packet, sizeof(packet));
107 }
108 
109 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,
110                                                         uint16_t properties, const uint8_t * uuid128){
111     // @format HY
112     uint8_t packet[28];
113     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
114     packet[1] = sizeof(packet) - 2u;
115     little_endian_store_16(packet, 2, gatt_client->con_handle);
116     ///
117     little_endian_store_16(packet, 4,  start_handle);
118     little_endian_store_16(packet, 6,  value_handle);
119     little_endian_store_16(packet, 8,  end_handle);
120     little_endian_store_16(packet, 10, properties);
121     reverse_128(uuid128, &packet[12]);
122     emit_event(gatt_client->callback, packet, sizeof(packet));
123 }
124 
125 static void emit_gatt_all_characteristic_descriptors_result_event(
126         gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
127     // @format HZ
128     uint8_t packet[22];
129     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
130     packet[1] = sizeof(packet) - 2u;
131     little_endian_store_16(packet, 2, gatt_client->con_handle);
132     ///
133     little_endian_store_16(packet, 4,  descriptor_handle);
134     reverse_128(uuid128, &packet[6]);
135     emit_event(gatt_client->callback, packet, sizeof(packet));
136 }
137 
138 static uint8_t event_packet[255];
139 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){
140     // before the value inside the ATT PDU
141     event_packet[0] = type;
142     event_packet[1] = 6 + length;
143     little_endian_store_16(event_packet, 2, con_handle);
144     little_endian_store_16(event_packet, 4, attribute_handle);
145     little_endian_store_16(event_packet, 6, length);
146     memcpy(&event_packet[8], value, length);
147     return &event_packet[0];
148 }
149 
150 void mock_gatt_client_send_notification_with_handle(mock_gatt_client_characteristic_t * characteristic, uint16_t value_handle, const uint8_t * value_buffer, uint16_t value_len){
151     btstack_assert(characteristic != NULL);
152     btstack_assert(characteristic->notification != NULL);
153     btstack_assert(characteristic->notification->callback != NULL);
154     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len);
155     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
156 }
157 
158 void mock_gatt_client_send_notification(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){
159     mock_gatt_client_send_notification_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
160 }
161 
162 void mock_gatt_client_send_indication_with_handle(mock_gatt_client_characteristic_t * characteristic, uint16_t value_handle, const uint8_t * value_buffer, uint16_t value_len){
163     btstack_assert(characteristic != NULL);
164     btstack_assert(characteristic->notification != NULL);
165     btstack_assert(characteristic->notification->callback != NULL);
166     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len);
167     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
168 }
169 
170 void mock_gatt_client_send_indication(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){
171     mock_gatt_client_send_indication_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
172 }
173 
174 static void mock_gatt_client_send_characteristic_value(gatt_client_t * gatt_client, mock_gatt_client_characteristic_t * characteristic){
175     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);
176     emit_event(gatt_client->callback, packet, 2 + packet[1]);
177 }
178 
179 /**
180  * copied from gatt_client.c - END
181  */
182 
183 
184 static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){
185     btstack_linked_list_iterator_t service_it;
186     btstack_linked_list_iterator_t characteristic_it;
187 
188     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
189     while (btstack_linked_list_iterator_has_next(&service_it)){
190         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
191 
192         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
193         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
194             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
195             if (characteristic->value_handle != value_handle) continue;
196             return characteristic;
197         }
198     }
199     return NULL;
200 }
201 
202 static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_uuid16(uint16_t uuid16){
203     btstack_linked_list_iterator_t service_it;
204     btstack_linked_list_iterator_t characteristic_it;
205 
206     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
207     while (btstack_linked_list_iterator_has_next(&service_it)){
208         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
209 
210         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
211         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
212             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
213             if (characteristic->uuid16 != uuid16) continue;
214             return characteristic;
215         }
216     }
217     return NULL;
218 }
219 
220 static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){
221     btstack_linked_list_iterator_t service_it;
222     btstack_linked_list_iterator_t characteristic_it;
223 
224     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
225     while (btstack_linked_list_iterator_has_next(&service_it)){
226         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
227 
228         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
229         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
230             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
231 
232             btstack_linked_list_iterator_t desc_it;
233             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
234             while (btstack_linked_list_iterator_has_next(&desc_it)){
235                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
236                 if (desc->handle != handle) continue;
237                 return desc;
238             }
239         }
240     }
241     return NULL;
242 }
243 
244 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
245     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
246     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
247     gatt_client.callback = callback;
248     gatt_client.con_handle = con_handle;
249     return ERROR_CODE_SUCCESS;
250 }
251 
252 uint8_t gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, const uint8_t * uuid128){
253     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
254     memcpy(mock_gatt_client_uuid128, uuid128, 16);
255     gatt_client.callback = callback;
256     gatt_client.con_handle = con_handle;
257     return ERROR_CODE_SUCCESS;
258 }
259 
260 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){
261     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID;
262     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
263     mock_gatt_client_start_handle = start_handle;
264     mock_gatt_client_end_handle = end_handle;
265 
266     gatt_client.callback = callback;
267     gatt_client.con_handle = con_handle;
268     return ERROR_CODE_SUCCESS;
269 }
270 
271 uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service){
272     mock_gatt_client_state = MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS;
273     mock_gatt_client_start_handle = service->start_group_handle;
274     mock_gatt_client_end_handle = service->end_group_handle;
275     gatt_client.callback = callback;
276     gatt_client.con_handle = con_handle;
277     return ERROR_CODE_SUCCESS;
278 }
279 
280 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
281     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS;
282     mock_gatt_client_value_handle = characteristic->value_handle;
283 
284     gatt_client.callback = callback;
285     gatt_client.con_handle = con_handle;
286     return ERROR_CODE_SUCCESS;
287 }
288 
289 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){
290     btstack_assert(notification != NULL);
291     btstack_assert(&callback != NULL);
292 
293     notification->callback = callback;
294     notification->con_handle = con_handle;
295 
296 
297     if (characteristic == NULL){
298         // 'all characteristics': not used yet
299         btstack_assert(false);
300     } else {
301         mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
302         btstack_assert(mock_characteristic != NULL);
303 
304         notification->attribute_handle = characteristic->value_handle;
305         mock_characteristic->notification = notification;
306     }
307 }
308 
309 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){
310     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
311     btstack_assert(mock_characteristic != NULL);
312 
313     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
314         return mock_characteristic->notification_status_code;
315     }
316 
317     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
318 
319     gatt_client.callback = callback;
320     gatt_client.con_handle = con_handle;
321     return ERROR_CODE_SUCCESS;
322 }
323 
324 uint8_t gatt_client_read_value_of_characteristics_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){
325     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
326 
327     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_uuid16(uuid16);
328     if (mock_characteristic != NULL){
329         mock_gatt_client_value_handle = mock_characteristic->value_handle;
330         gatt_client.callback = callback;
331         gatt_client.con_handle = con_handle;
332     }
333     return ERROR_CODE_SUCCESS;
334 }
335 
336 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){
337     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
338 
339     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
340     btstack_assert(mock_characteristic != NULL);
341 
342     mock_gatt_client_value_handle = mock_characteristic->value_handle;
343     gatt_client.callback = callback;
344     gatt_client.con_handle = con_handle;
345     return ERROR_CODE_SUCCESS;
346 }
347 
348 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
349     btstack_assert(characteristic != NULL);
350     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
351 
352     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
353     btstack_assert(mock_characteristic != NULL);
354 
355     gatt_client.callback = callback;
356     gatt_client.con_handle = con_handle;
357     mock_gatt_client_value_handle = mock_characteristic->value_handle;
358     return ERROR_CODE_SUCCESS;
359 }
360 
361 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){
362     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE;
363     mock_gatt_client_value_handle = descriptor_handle;
364     return ERROR_CODE_SUCCESS;
365 }
366 
367 void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
368 }
369 
370 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){
371     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
372     btstack_assert(mock_characteristic != NULL);
373 
374     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
375         return mock_characteristic->notification_status_code;
376     }
377 
378     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
379 
380     gatt_client.callback = callback;
381     gatt_client.con_handle = con_handle;
382     return ERROR_CODE_SUCCESS;
383 }
384 
385 void mock_gatt_client_emit_complete(uint8_t status){
386     mock_gatt_client_state = MOCK_QUERY_IDLE;
387     emit_gatt_complete_event(&gatt_client, status);
388 }
389 
390 void mock_gatt_client_run_once(void){
391     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
392     mock_gatt_client_characteristic_t * characteristic;
393     mock_gatt_client_characteristic_descriptor_t * descriptor;
394 
395     btstack_linked_list_iterator_t service_it;
396     btstack_linked_list_iterator_t characteristic_it;
397     btstack_linked_list_iterator_t descriptor_it;
398 
399     switch (mock_gatt_client_state){
400         case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID:
401             // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service
402             if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){
403                 mock_gatt_client_emit_complete(moc_att_error_code_discover_services);
404                 return;
405             }
406 
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                 if (memcmp(service->uuid128, mock_gatt_client_uuid128, 16) != 0) continue;
411                 mock_gatt_client_last_service = service;
412                 emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, service->uuid128);
413             }
414             // emit GATT_EVENT_QUERY_COMPLETE
415             mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS);
416             break;
417 
418         case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID:
419         case MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS:
420             // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic
421             if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){
422                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics);
423                 return;
424             }
425 
426             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
427             while (btstack_linked_list_iterator_has_next(&service_it)){
428                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
429 
430                 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
431                 while (btstack_linked_list_iterator_has_next(&characteristic_it)){
432                     mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
433                     if (characteristic->start_handle < mock_gatt_client_start_handle) continue;
434                     if (characteristic->end_handle > mock_gatt_client_end_handle) continue;
435                     if ((mock_gatt_client_state == MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID) && (memcmp(characteristic->uuid128, mock_gatt_client_uuid128, 16) != 0)) continue;
436 
437                     emit_gatt_characteristic_query_result_event(&gatt_client,
438                         characteristic->start_handle, characteristic->value_handle, characteristic->end_handle,
439                         characteristic->properties, characteristic->uuid128);
440                 }
441             }
442 
443             // emit GATT_EVENT_QUERY_COMPLETE
444             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
445             break;
446 
447         case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
448             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
449             btstack_assert(characteristic != NULL);
450 
451             if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){
452                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors);
453                 return;
454             }
455 
456             btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors);
457             while (btstack_linked_list_iterator_has_next(&descriptor_it)){
458                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it);
459 
460                 emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, desc->uuid128);
461             }
462 
463             // emit GATT_EVENT_QUERY_COMPLETE
464             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
465             break;
466 
467         case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
468             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
469             break;
470 
471         case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE:
472             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
473             if (moc_att_error_code_read_value_characteristics != ATT_ERROR_SUCCESS){
474                 mock_gatt_client_emit_complete(moc_att_error_code_read_value_characteristics);
475                 break;
476             }
477             if (characteristic != NULL){
478                 mock_gatt_client_send_characteristic_value(&gatt_client, characteristic);
479             }
480             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
481             break;
482 
483         case MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE:
484             descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle);
485             btstack_assert(descriptor != NULL);
486             btstack_assert(descriptor->value_buffer != NULL);
487 
488             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
489             break;
490 
491         default:
492             btstack_assert(false);
493             break;
494     }
495 }
496 
497 void mock_gatt_client_run(void){
498     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
499     while (mock_gatt_client_state != MOCK_QUERY_IDLE){
500         mock_gatt_client_run_once();
501     }
502     mock_gatt_client_att_error = ERROR_CODE_SUCCESS;
503     mock_gatt_client_state = MOCK_QUERY_IDLE;
504 }
505 
506 void mock_gatt_client_emit_dummy_event(void){
507         // @format H1
508     uint8_t packet[2];
509     packet[0] = 0;
510     packet[1] = 0;
511     emit_event(gatt_client.callback, packet, sizeof(packet));
512 }
513 
514 static void mock_gatt_client_reset_errors(void){
515     moc_att_error_code_discover_services = ATT_ERROR_SUCCESS;
516     moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS;
517     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS;
518     moc_att_error_code_read_value_characteristics = ATT_ERROR_SUCCESS;
519 }
520 
521 void mock_gatt_client_reset(void){
522     mock_gatt_client_att_error = 0;
523     mock_gatt_client_state = MOCK_QUERY_IDLE;
524     mock_gatt_client_att_handle_generator = 0;
525     mock_gatt_client_last_service = NULL;
526 
527     mock_gatt_client_reset_errors();
528 
529     btstack_linked_list_iterator_t service_it;
530     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
531     while (btstack_linked_list_iterator_has_next(&service_it)){
532         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
533         btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service);
534 
535         btstack_linked_list_iterator_t characteristic_it;
536         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
537         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
538             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
539             btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic);
540 
541             btstack_linked_list_iterator_t desc_it;
542             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
543             while (btstack_linked_list_iterator_has_next(&desc_it)){
544                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
545                 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc);
546                 free(desc);
547             }
548             free(characteristic);
549         }
550         free(service);
551     }
552 }
553 
554 void mock_gatt_client_set_att_error_discover_primary_services(void){
555     moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED;
556 }
557 void mock_gatt_client_set_att_error_discover_characteristics(void){
558     moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED;
559 }
560 void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){
561     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED;
562 }
563 void mock_gatt_client_set_att_error_read_value_characteristics(void){
564     moc_att_error_code_read_value_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED;
565 }
566 
567 void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){
568     if (command_allowed){
569         characteristic->notification_status_code = ERROR_CODE_SUCCESS;
570     } else {
571         characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED;
572     }
573 }
574 
575 void mock_gatt_client_dump_services(void){
576     btstack_linked_list_iterator_t service_it;
577     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
578     while (btstack_linked_list_iterator_has_next(&service_it)){
579         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
580         printf("0x%02x: START SERVICE ", service->start_group_handle);
581         if (service->uuid16) {
582             printf("%04x\n", service->uuid16);
583         } else {
584             printf("%s\n", uuid128_to_str(service->uuid128));
585         }
586 
587         btstack_linked_list_iterator_t characteristic_it;
588         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
589         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
590             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
591             printf("0x%02x:   START CHR ", characteristic->start_handle);
592             if (characteristic->uuid16) {
593                 printf("%04x\n", characteristic->uuid16);
594             } else {
595                 printf("%s\n", uuid128_to_str(characteristic->uuid128));
596             }
597             printf("0x%02x:   VALUE HANDLE CHR\n", characteristic->value_handle);
598 
599             btstack_linked_list_iterator_t desc_it;
600             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
601             while (btstack_linked_list_iterator_has_next(&desc_it)){
602                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
603                 printf("0x%02x:     DESC 0x%02x\n", desc->handle, desc->uuid16);
604             }
605 
606             printf("0x%02x:   END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16);
607         }
608         printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16);
609 
610     }
611 }
612 
613 static void mock_gatt_client_add_primary_service(void){
614     // set lsat group handle
615     // create new service
616     mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t));
617     memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t));
618     mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++;
619     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle;
620     btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service);
621     mock_gatt_client_last_characteristic = NULL;
622 }
623 
624 mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){
625     mock_gatt_client_add_primary_service();
626     mock_gatt_client_last_service->uuid16 = service_uuid;
627     uuid_add_bluetooth_prefix(mock_gatt_client_last_service->uuid128, service_uuid);
628     return mock_gatt_client_last_service;
629 }
630 mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid128(const uint8_t * service_uuid){
631     mock_gatt_client_add_primary_service();
632     (void) memcpy(mock_gatt_client_last_service->uuid128, service_uuid, 16);
633     return mock_gatt_client_last_service;
634 }
635 
636 static void mock_gatt_client_add_characteristic(uint16_t properties){
637     btstack_assert(mock_gatt_client_last_service != NULL);
638     mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t));
639     memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t));
640     mock_gatt_client_last_characteristic->properties = properties;
641     mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++;
642     mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++;
643     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle;
644     btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic);
645     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
646 }
647 
648 mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){
649     mock_gatt_client_add_characteristic(properties);
650     mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid;
651     uuid_add_bluetooth_prefix(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid);
652     return mock_gatt_client_last_characteristic;
653 }
654 
655 mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid128(const uint8_t * characteristic_uuid, uint16_t properties){
656     mock_gatt_client_add_characteristic(properties);
657     (void) memcpy(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid, 16);
658     return mock_gatt_client_last_characteristic;
659 }
660 
661 static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor(void){
662     btstack_assert(mock_gatt_client_last_characteristic != NULL);
663     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t));
664     memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t));
665     desc->handle = mock_gatt_client_att_handle_generator++;
666     btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc);
667     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1;
668     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
669     return desc;
670 }
671 
672 mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){
673     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
674     desc->uuid16 = descriptor_uuid;
675     uuid_add_bluetooth_prefix(desc->uuid128, descriptor_uuid);
676     return desc;
677 }
678 
679 mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid128(const uint8_t * descriptor_uuid){
680     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
681     (void) memcpy(desc->uuid128, descriptor_uuid, 16);
682     return desc;
683 }
684 
685 void mock_gatt_client_set_descriptor_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){
686     btstack_assert(descriptor != NULL);
687     descriptor->value_buffer = value_buffer;
688     descriptor->value_len = value_len;
689 }
690 
691 void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
692     btstack_assert(characteristic != NULL);
693     characteristic->value_buffer = value_buffer;
694     characteristic->value_len = value_len;
695 }
696 
697 // simulate error
698 void mock_gatt_client_simulate_att_error(uint8_t att_error){
699     mock_gatt_client_att_error = att_error;
700 }
701