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