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