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