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