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