xref: /btstack/test/mock/mock_gatt_client.c (revision 7dbac955712cda229237d6822781650fef3cd3a7)
10f7fd6c1SMilanka Ringwald #include <stdint.h>
20f7fd6c1SMilanka Ringwald #include <stdio.h>
30f7fd6c1SMilanka Ringwald #include <string.h>
40f7fd6c1SMilanka Ringwald 
5af770404SMilanka Ringwald #include "btstack_debug.h"
67e693ad3SMilanka Ringwald #include "bluetooth_gatt.h"
70f7fd6c1SMilanka Ringwald #include "mock_gatt_client.h"
80f7fd6c1SMilanka Ringwald 
90f7fd6c1SMilanka Ringwald #include "CppUTest/TestHarness.h"
100f7fd6c1SMilanka Ringwald #include "CppUTestExt/MockSupport.h"
110f7fd6c1SMilanka Ringwald 
12af770404SMilanka Ringwald static enum {
13af770404SMilanka Ringwald     MOCK_QUERY_IDLE = 0,
14*7dbac955SMatthias Ringwald     MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID,
15*7dbac955SMatthias Ringwald     MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID,
16*7dbac955SMatthias Ringwald     MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS,
1776cdba3eSMilanka Ringwald     MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS,
1876cdba3eSMilanka Ringwald     MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION,
197e693ad3SMilanka Ringwald     MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE,
207e693ad3SMilanka Ringwald     MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE
21af770404SMilanka Ringwald } mock_gatt_client_state;
22af770404SMilanka Ringwald 
2376cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_att_handle_generator;
2476cdba3eSMilanka Ringwald 
25af770404SMilanka Ringwald static uint8_t mock_gatt_client_att_error;
26*7dbac955SMatthias Ringwald static uint8_t  mock_gatt_client_uuid128[16];
2776cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_value_handle;
2876cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_start_handle;
2976cdba3eSMilanka Ringwald static uint16_t mock_gatt_client_end_handle;
3076cdba3eSMilanka Ringwald 
31af770404SMilanka Ringwald static gatt_client_t gatt_client;
320f7fd6c1SMilanka Ringwald 
337da2c1baSMilanka Ringwald static btstack_linked_list_t mock_gatt_client_services;
347da2c1baSMilanka Ringwald 
357da2c1baSMilanka Ringwald static mock_gatt_client_service_t * mock_gatt_client_last_service;
367da2c1baSMilanka Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic;
377da2c1baSMilanka Ringwald 
38ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_services;
39ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristics;
40ec1a0daeSMilanka Ringwald static uint8_t moc_att_error_code_discover_characteristic_descriptors;
417e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_con_handle;
427e693ad3SMilanka Ringwald static bool mock_gatt_client_wrong_value_handle;
43ec1a0daeSMilanka Ringwald 
4486d0910fSMilanka Ringwald 
45af770404SMilanka Ringwald /**
46af770404SMilanka Ringwald  * copied from gatt_client.c - START
47af770404SMilanka Ringwald  */
480f7fd6c1SMilanka Ringwald void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
490f7fd6c1SMilanka Ringwald     service->start_group_handle = little_endian_read_16(packet, offset);
500f7fd6c1SMilanka Ringwald     service->end_group_handle = little_endian_read_16(packet, offset + 2);
510f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset + 4], service->uuid128);
520f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(service->uuid128)){
530f7fd6c1SMilanka Ringwald         service->uuid16 = big_endian_read_32(service->uuid128, 0);
540f7fd6c1SMilanka Ringwald     } else {
550f7fd6c1SMilanka Ringwald         service->uuid16 = 0;
560f7fd6c1SMilanka Ringwald     }
570f7fd6c1SMilanka Ringwald }
580f7fd6c1SMilanka Ringwald 
590f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
600f7fd6c1SMilanka Ringwald     characteristic->start_handle = little_endian_read_16(packet, offset);
610f7fd6c1SMilanka Ringwald     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
620f7fd6c1SMilanka Ringwald     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
630f7fd6c1SMilanka Ringwald     characteristic->properties = little_endian_read_16(packet, offset + 6);
640f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+8], characteristic->uuid128);
650f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
660f7fd6c1SMilanka Ringwald         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
670f7fd6c1SMilanka Ringwald     } else {
680f7fd6c1SMilanka Ringwald         characteristic->uuid16 = 0;
690f7fd6c1SMilanka Ringwald     }
700f7fd6c1SMilanka Ringwald }
710f7fd6c1SMilanka Ringwald 
720f7fd6c1SMilanka Ringwald void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
730f7fd6c1SMilanka Ringwald     descriptor->handle = little_endian_read_16(packet, offset);
740f7fd6c1SMilanka Ringwald     reverse_128(&packet[offset+2], descriptor->uuid128);
750f7fd6c1SMilanka Ringwald     if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
760f7fd6c1SMilanka Ringwald         descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
770f7fd6c1SMilanka Ringwald     } else {
780f7fd6c1SMilanka Ringwald         descriptor->uuid16 = 0;
790f7fd6c1SMilanka Ringwald     }
800f7fd6c1SMilanka Ringwald }
810f7fd6c1SMilanka Ringwald 
827e693ad3SMilanka Ringwald static void emit_event(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
83af770404SMilanka Ringwald     if (!callback) return;
847e693ad3SMilanka Ringwald     if (mock_gatt_client_wrong_con_handle){
857e693ad3SMilanka Ringwald         little_endian_store_16(packet, 2, 0xFFFF);
867e693ad3SMilanka Ringwald     }
87af770404SMilanka Ringwald     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
880f7fd6c1SMilanka Ringwald }
890f7fd6c1SMilanka Ringwald 
90af770404SMilanka Ringwald static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
91af770404SMilanka Ringwald     // @format H1
92af770404SMilanka Ringwald     uint8_t packet[5];
93af770404SMilanka Ringwald     packet[0] = GATT_EVENT_QUERY_COMPLETE;
94af770404SMilanka Ringwald     packet[1] = 3;
95af770404SMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
96af770404SMilanka Ringwald     packet[4] = att_status;
977e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
980f7fd6c1SMilanka Ringwald }
990f7fd6c1SMilanka Ringwald 
1007da2c1baSMilanka Ringwald 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){
1017da2c1baSMilanka Ringwald     // @format HX
1027da2c1baSMilanka Ringwald     uint8_t packet[24];
1037da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
1047da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
1057da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
1067da2c1baSMilanka Ringwald     ///
1077da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4, start_group_handle);
1087da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6, end_group_handle);
1097da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[8]);
1107e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
1117da2c1baSMilanka Ringwald }
1127da2c1baSMilanka Ringwald 
1137da2c1baSMilanka Ringwald 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,
1147da2c1baSMilanka Ringwald                                                         uint16_t properties, const uint8_t * uuid128){
1157da2c1baSMilanka Ringwald     // @format HY
1167da2c1baSMilanka Ringwald     uint8_t packet[28];
1177da2c1baSMilanka Ringwald     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
1187da2c1baSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
1197da2c1baSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
1207da2c1baSMilanka Ringwald     ///
1217da2c1baSMilanka Ringwald     little_endian_store_16(packet, 4,  start_handle);
1227da2c1baSMilanka Ringwald     little_endian_store_16(packet, 6,  value_handle);
1237da2c1baSMilanka Ringwald     little_endian_store_16(packet, 8,  end_handle);
1247da2c1baSMilanka Ringwald     little_endian_store_16(packet, 10, properties);
1257da2c1baSMilanka Ringwald     reverse_128(uuid128, &packet[12]);
1267e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
1277da2c1baSMilanka Ringwald }
1287da2c1baSMilanka Ringwald 
12976cdba3eSMilanka Ringwald static void emit_gatt_all_characteristic_descriptors_result_event(
13076cdba3eSMilanka Ringwald         gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
13176cdba3eSMilanka Ringwald     // @format HZ
13276cdba3eSMilanka Ringwald     uint8_t packet[22];
13376cdba3eSMilanka Ringwald     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
13476cdba3eSMilanka Ringwald     packet[1] = sizeof(packet) - 2u;
13576cdba3eSMilanka Ringwald     little_endian_store_16(packet, 2, gatt_client->con_handle);
13676cdba3eSMilanka Ringwald     ///
13776cdba3eSMilanka Ringwald     little_endian_store_16(packet, 4,  descriptor_handle);
13876cdba3eSMilanka Ringwald     reverse_128(uuid128, &packet[6]);
1397e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, sizeof(packet));
14076cdba3eSMilanka Ringwald }
14176cdba3eSMilanka Ringwald 
1427e693ad3SMilanka Ringwald static uint8_t event_packet[255];
14376cdba3eSMilanka Ringwald 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){
14476cdba3eSMilanka Ringwald     // before the value inside the ATT PDU
1457e693ad3SMilanka Ringwald     event_packet[0] = type;
1467e693ad3SMilanka Ringwald     event_packet[1] = 6 + length;
1477e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 2, con_handle);
1487e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 4, attribute_handle);
1497e693ad3SMilanka Ringwald     little_endian_store_16(event_packet, 6, length);
1507e693ad3SMilanka Ringwald     memcpy(&event_packet[8], value, length);
1517e693ad3SMilanka Ringwald     return &event_packet[0];
15276cdba3eSMilanka Ringwald }
15376cdba3eSMilanka Ringwald 
154*7dbac955SMatthias Ringwald 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){
1557e693ad3SMilanka Ringwald     btstack_assert(characteristic != NULL);
1567e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification != NULL);
1577e693ad3SMilanka Ringwald     btstack_assert(characteristic->notification->callback != NULL);
158*7dbac955SMatthias Ringwald     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len);
1597e693ad3SMilanka Ringwald     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
1607e693ad3SMilanka Ringwald }
1617e693ad3SMilanka Ringwald 
162*7dbac955SMatthias Ringwald void mock_gatt_client_send_notification(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){
1637e693ad3SMilanka Ringwald     mock_gatt_client_send_notification_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
1647e693ad3SMilanka Ringwald }
1657e693ad3SMilanka Ringwald 
166*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
168*7dbac955SMatthias Ringwald     btstack_assert(characteristic->notification != NULL);
169*7dbac955SMatthias Ringwald     btstack_assert(characteristic->notification->callback != NULL);
170*7dbac955SMatthias Ringwald     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len);
171*7dbac955SMatthias Ringwald     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
172*7dbac955SMatthias Ringwald }
173*7dbac955SMatthias Ringwald 
174*7dbac955SMatthias Ringwald void mock_gatt_client_send_indication(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){
175*7dbac955SMatthias Ringwald     mock_gatt_client_send_indication_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
176*7dbac955SMatthias Ringwald }
177*7dbac955SMatthias Ringwald 
1787e693ad3SMilanka Ringwald static void mock_gatt_client_send_characteristic_value(gatt_client_t * gatt_client, mock_gatt_client_characteristic_t * characteristic){
1797e693ad3SMilanka Ringwald     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);
1807e693ad3SMilanka Ringwald     emit_event(gatt_client->callback, packet, 2 + packet[1]);
18176cdba3eSMilanka Ringwald }
18276cdba3eSMilanka Ringwald 
183af770404SMilanka Ringwald /**
184af770404SMilanka Ringwald  * copied from gatt_client.c - END
185af770404SMilanka Ringwald  */
1860f7fd6c1SMilanka Ringwald 
187*7dbac955SMatthias Ringwald 
188*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){
189*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
190*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t characteristic_it;
191*7dbac955SMatthias Ringwald 
192*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
193*7dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
194*7dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
195*7dbac955SMatthias Ringwald 
196*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
197*7dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
198*7dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
199*7dbac955SMatthias Ringwald             if (characteristic->value_handle != value_handle) continue;
200*7dbac955SMatthias Ringwald             return characteristic;
201*7dbac955SMatthias Ringwald         }
202*7dbac955SMatthias Ringwald     }
203*7dbac955SMatthias Ringwald     return NULL;
204*7dbac955SMatthias Ringwald }
205*7dbac955SMatthias Ringwald 
206*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){
207*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
208*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t characteristic_it;
209*7dbac955SMatthias Ringwald 
210*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
211*7dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
212*7dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
213*7dbac955SMatthias Ringwald 
214*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
215*7dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
216*7dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
217*7dbac955SMatthias Ringwald 
218*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
219*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
220*7dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
221*7dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
222*7dbac955SMatthias Ringwald                 if (desc->handle != handle) continue;
223*7dbac955SMatthias Ringwald                 return desc;
224*7dbac955SMatthias Ringwald             }
225*7dbac955SMatthias Ringwald         }
226*7dbac955SMatthias Ringwald     }
227*7dbac955SMatthias Ringwald     return NULL;
228*7dbac955SMatthias Ringwald }
229*7dbac955SMatthias Ringwald 
230*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
231*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
232*7dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
233*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
234*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
235*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
236*7dbac955SMatthias Ringwald }
237*7dbac955SMatthias Ringwald 
238*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
240*7dbac955SMatthias Ringwald     memcpy(mock_gatt_client_uuid128, uuid128, 16);
241*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
242*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
243*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
244*7dbac955SMatthias Ringwald }
245*7dbac955SMatthias Ringwald 
246*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID;
248*7dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
249*7dbac955SMatthias Ringwald     mock_gatt_client_start_handle = start_handle;
250*7dbac955SMatthias Ringwald     mock_gatt_client_end_handle = end_handle;
251*7dbac955SMatthias Ringwald 
252*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
253*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
254*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
255*7dbac955SMatthias Ringwald }
256*7dbac955SMatthias Ringwald 
257*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS;
259*7dbac955SMatthias Ringwald     mock_gatt_client_start_handle = service->start_group_handle;
260*7dbac955SMatthias Ringwald     mock_gatt_client_end_handle = service->end_group_handle;
261*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
262*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
263*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
264*7dbac955SMatthias Ringwald }
265*7dbac955SMatthias Ringwald 
266*7dbac955SMatthias Ringwald uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
267*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS;
268*7dbac955SMatthias Ringwald     mock_gatt_client_value_handle = characteristic->value_handle;
269*7dbac955SMatthias Ringwald 
270*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
271*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
272*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
273*7dbac955SMatthias Ringwald }
274*7dbac955SMatthias Ringwald 
275*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     btstack_assert(notification != NULL);
277*7dbac955SMatthias Ringwald     btstack_assert(&callback != NULL);
278*7dbac955SMatthias Ringwald 
279*7dbac955SMatthias Ringwald     notification->callback = callback;
280*7dbac955SMatthias Ringwald     notification->con_handle = con_handle;
281*7dbac955SMatthias Ringwald 
282*7dbac955SMatthias Ringwald 
283*7dbac955SMatthias Ringwald     if (characteristic == NULL){
284*7dbac955SMatthias Ringwald         // 'all characteristics': not used yet
285*7dbac955SMatthias Ringwald         btstack_assert(false);
286*7dbac955SMatthias Ringwald     } else {
287*7dbac955SMatthias Ringwald         mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
288*7dbac955SMatthias Ringwald         btstack_assert(mock_characteristic != NULL);
289*7dbac955SMatthias Ringwald 
290*7dbac955SMatthias Ringwald         notification->attribute_handle = characteristic->value_handle;
291*7dbac955SMatthias Ringwald         mock_characteristic->notification = notification;
292*7dbac955SMatthias Ringwald     }
293*7dbac955SMatthias Ringwald }
294*7dbac955SMatthias Ringwald 
295*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
297*7dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
298*7dbac955SMatthias Ringwald 
299*7dbac955SMatthias Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
300*7dbac955SMatthias Ringwald         return mock_characteristic->notification_status_code;
301*7dbac955SMatthias Ringwald     }
302*7dbac955SMatthias Ringwald 
303*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
304*7dbac955SMatthias Ringwald 
305*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
306*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
307*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
308*7dbac955SMatthias Ringwald }
309*7dbac955SMatthias Ringwald 
310*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
312*7dbac955SMatthias Ringwald 
313*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
314*7dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
315*7dbac955SMatthias Ringwald 
316*7dbac955SMatthias Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
317*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
318*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
319*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
320*7dbac955SMatthias Ringwald }
321*7dbac955SMatthias Ringwald 
322*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
324*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
325*7dbac955SMatthias Ringwald 
326*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
327*7dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
328*7dbac955SMatthias Ringwald 
329*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
330*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
331*7dbac955SMatthias Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
332*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
333*7dbac955SMatthias Ringwald }
334*7dbac955SMatthias Ringwald 
335*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE;
337*7dbac955SMatthias Ringwald     mock_gatt_client_value_handle = descriptor_handle;
338*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
339*7dbac955SMatthias Ringwald }
340*7dbac955SMatthias Ringwald 
341*7dbac955SMatthias Ringwald void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
342*7dbac955SMatthias Ringwald }
343*7dbac955SMatthias Ringwald 
344*7dbac955SMatthias Ringwald 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*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
346*7dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
347*7dbac955SMatthias Ringwald 
348*7dbac955SMatthias Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
349*7dbac955SMatthias Ringwald         return mock_characteristic->notification_status_code;
350*7dbac955SMatthias Ringwald     }
351*7dbac955SMatthias Ringwald 
352*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
353*7dbac955SMatthias Ringwald 
354*7dbac955SMatthias Ringwald     gatt_client.callback = callback;
355*7dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
356*7dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
357*7dbac955SMatthias Ringwald }
358*7dbac955SMatthias Ringwald 
3597e693ad3SMilanka Ringwald void mock_gatt_client_emit_complete(uint8_t status){
3607da2c1baSMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
3617da2c1baSMilanka Ringwald     emit_gatt_complete_event(&gatt_client, status);
3627da2c1baSMilanka Ringwald }
3630f7fd6c1SMilanka Ringwald 
3647e693ad3SMilanka Ringwald void mock_gatt_client_run_once(void){
365af770404SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
36676cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_t * characteristic;
36776cdba3eSMilanka Ringwald     mock_gatt_client_characteristic_descriptor_t * descriptor;
36876cdba3eSMilanka Ringwald 
3697da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t service_it;
3707da2c1baSMilanka Ringwald     btstack_linked_list_iterator_t characteristic_it;
37176cdba3eSMilanka Ringwald     btstack_linked_list_iterator_t descriptor_it;
37276cdba3eSMilanka Ringwald 
373af770404SMilanka Ringwald     switch (mock_gatt_client_state){
374*7dbac955SMatthias Ringwald         case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID:
375af770404SMilanka Ringwald             // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service
376ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){
377ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_services);
378ec1a0daeSMilanka Ringwald                 return;
379ec1a0daeSMilanka Ringwald             }
380ec1a0daeSMilanka Ringwald 
3817da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
3827da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
3837da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
384*7dbac955SMatthias Ringwald                 if (memcmp(service->uuid128, mock_gatt_client_uuid128, 16) != 0) continue;
3857da2c1baSMilanka Ringwald                 mock_gatt_client_last_service = service;
386*7dbac955SMatthias Ringwald                 emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, service->uuid128);
3877da2c1baSMilanka Ringwald             }
3887da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
3897da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS);
3907da2c1baSMilanka Ringwald             break;
3917da2c1baSMilanka Ringwald 
392*7dbac955SMatthias Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID:
393*7dbac955SMatthias Ringwald         case MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS:
3947da2c1baSMilanka Ringwald             // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic
395ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){
396ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics);
397ec1a0daeSMilanka Ringwald                 return;
398ec1a0daeSMilanka Ringwald             }
399ec1a0daeSMilanka Ringwald 
4007da2c1baSMilanka Ringwald             btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
4017da2c1baSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&service_it)){
4027da2c1baSMilanka Ringwald                 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
4037da2c1baSMilanka Ringwald 
4047da2c1baSMilanka Ringwald                 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
4057da2c1baSMilanka Ringwald                 while (btstack_linked_list_iterator_has_next(&characteristic_it)){
4067da2c1baSMilanka Ringwald                     mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
40776cdba3eSMilanka Ringwald                     if (characteristic->start_handle < mock_gatt_client_start_handle) continue;
40876cdba3eSMilanka Ringwald                     if (characteristic->end_handle > mock_gatt_client_end_handle) continue;
409*7dbac955SMatthias Ringwald                     if ((mock_gatt_client_state == MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID) && (memcmp(characteristic->uuid128, mock_gatt_client_uuid128, 16) != 0)) continue;
41076cdba3eSMilanka Ringwald 
41176cdba3eSMilanka Ringwald                     emit_gatt_characteristic_query_result_event(&gatt_client,
41276cdba3eSMilanka Ringwald                         characteristic->start_handle, characteristic->value_handle, characteristic->end_handle,
413*7dbac955SMatthias Ringwald                         characteristic->properties, characteristic->uuid128);
4147da2c1baSMilanka Ringwald                 }
4157da2c1baSMilanka Ringwald             }
4167da2c1baSMilanka Ringwald 
4177da2c1baSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
4187da2c1baSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
419af770404SMilanka Ringwald             break;
42076cdba3eSMilanka Ringwald 
42176cdba3eSMilanka Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
42276cdba3eSMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
42376cdba3eSMilanka Ringwald             btstack_assert(characteristic != NULL);
42476cdba3eSMilanka Ringwald 
425ec1a0daeSMilanka Ringwald             if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){
426ec1a0daeSMilanka Ringwald                 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors);
427ec1a0daeSMilanka Ringwald                 return;
428ec1a0daeSMilanka Ringwald             }
429ec1a0daeSMilanka Ringwald 
43076cdba3eSMilanka Ringwald             btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors);
43176cdba3eSMilanka Ringwald             while (btstack_linked_list_iterator_has_next(&descriptor_it)){
43276cdba3eSMilanka Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it);
43376cdba3eSMilanka Ringwald 
434*7dbac955SMatthias Ringwald                 emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, desc->uuid128);
43576cdba3eSMilanka Ringwald             }
43676cdba3eSMilanka Ringwald 
43776cdba3eSMilanka Ringwald             // emit GATT_EVENT_QUERY_COMPLETE
43876cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
43976cdba3eSMilanka Ringwald             break;
44076cdba3eSMilanka Ringwald 
44176cdba3eSMilanka Ringwald         case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
44276cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
44376cdba3eSMilanka Ringwald             break;
44476cdba3eSMilanka Ringwald 
44576cdba3eSMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE:
4467e693ad3SMilanka Ringwald             characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle);
4477e693ad3SMilanka Ringwald             btstack_assert(characteristic != NULL);
4487e693ad3SMilanka Ringwald 
4497e693ad3SMilanka Ringwald             mock_gatt_client_send_characteristic_value(&gatt_client, characteristic);
4507e693ad3SMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
4517e693ad3SMilanka Ringwald             break;
4527e693ad3SMilanka Ringwald 
4537e693ad3SMilanka Ringwald         case MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE:
45476cdba3eSMilanka Ringwald             descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle);
45576cdba3eSMilanka Ringwald             btstack_assert(descriptor != NULL);
45676cdba3eSMilanka Ringwald             btstack_assert(descriptor->value_buffer != NULL);
45776cdba3eSMilanka Ringwald 
45876cdba3eSMilanka Ringwald             mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
45976cdba3eSMilanka Ringwald             break;
46076cdba3eSMilanka Ringwald 
461af770404SMilanka Ringwald         default:
462af770404SMilanka Ringwald             btstack_assert(false);
463af770404SMilanka Ringwald             break;
4640f7fd6c1SMilanka Ringwald     }
4657da2c1baSMilanka Ringwald }
4667e693ad3SMilanka Ringwald 
4677e693ad3SMilanka Ringwald void mock_gatt_client_run(void){
4687e693ad3SMilanka Ringwald     btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE);
4697e693ad3SMilanka Ringwald     while (mock_gatt_client_state != MOCK_QUERY_IDLE){
4707e693ad3SMilanka Ringwald         mock_gatt_client_run_once();
4717e693ad3SMilanka Ringwald     }
4727da2c1baSMilanka Ringwald     mock_gatt_client_att_error = ERROR_CODE_SUCCESS;
473af770404SMilanka Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
4740f7fd6c1SMilanka Ringwald }
4757e693ad3SMilanka Ringwald 
4767e693ad3SMilanka Ringwald void mock_gatt_client_emit_dummy_event(void){
4777e693ad3SMilanka Ringwald         // @format H1
4787e693ad3SMilanka Ringwald     uint8_t packet[2];
4797e693ad3SMilanka Ringwald     packet[0] = 0;
4807e693ad3SMilanka Ringwald     packet[1] = 0;
4817e693ad3SMilanka Ringwald     emit_event(gatt_client.callback, packet, sizeof(packet));
4827e693ad3SMilanka Ringwald }
483*7dbac955SMatthias Ringwald 
484*7dbac955SMatthias Ringwald static void mock_gatt_client_reset_errors(void){
485*7dbac955SMatthias Ringwald     moc_att_error_code_discover_services = ATT_ERROR_SUCCESS;
486*7dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS;
487*7dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS;
488*7dbac955SMatthias Ringwald 
489*7dbac955SMatthias Ringwald     mock_gatt_client_wrong_con_handle = false;
490*7dbac955SMatthias Ringwald     mock_gatt_client_wrong_value_handle = false;
491*7dbac955SMatthias Ringwald }
492*7dbac955SMatthias Ringwald 
493*7dbac955SMatthias Ringwald void mock_gatt_client_reset(void){
494*7dbac955SMatthias Ringwald     mock_gatt_client_att_error = 0;
495*7dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
496*7dbac955SMatthias Ringwald     mock_gatt_client_att_handle_generator = 0;
497*7dbac955SMatthias Ringwald     mock_gatt_client_last_service = NULL;
498*7dbac955SMatthias Ringwald 
499*7dbac955SMatthias Ringwald     mock_gatt_client_reset_errors();
500*7dbac955SMatthias Ringwald 
501*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
502*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
503*7dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
504*7dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
505*7dbac955SMatthias Ringwald         btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service);
506*7dbac955SMatthias Ringwald 
507*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_t characteristic_it;
508*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
509*7dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
510*7dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
511*7dbac955SMatthias Ringwald             btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic);
512*7dbac955SMatthias Ringwald 
513*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
514*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
515*7dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
516*7dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
517*7dbac955SMatthias Ringwald                 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc);
518*7dbac955SMatthias Ringwald                 free(desc);
519*7dbac955SMatthias Ringwald             }
520*7dbac955SMatthias Ringwald             free(characteristic);
521*7dbac955SMatthias Ringwald         }
522*7dbac955SMatthias Ringwald         free(service);
523*7dbac955SMatthias Ringwald     }
524*7dbac955SMatthias Ringwald }
525*7dbac955SMatthias Ringwald 
526*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_primary_services(void){
527*7dbac955SMatthias Ringwald     moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED;
528*7dbac955SMatthias Ringwald }
529*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristics(void){
530*7dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED;
531*7dbac955SMatthias Ringwald }
532*7dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){
533*7dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED;
534*7dbac955SMatthias Ringwald }
535*7dbac955SMatthias Ringwald 
536*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_con_handle(void){
537*7dbac955SMatthias Ringwald     mock_gatt_client_wrong_con_handle = true;
538*7dbac955SMatthias Ringwald }
539*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_value_handle(void){
540*7dbac955SMatthias Ringwald     mock_gatt_client_wrong_value_handle = true;
541*7dbac955SMatthias Ringwald }
542*7dbac955SMatthias Ringwald 
543*7dbac955SMatthias Ringwald void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){
544*7dbac955SMatthias Ringwald     if (command_allowed){
545*7dbac955SMatthias Ringwald         characteristic->notification_status_code = ERROR_CODE_SUCCESS;
546*7dbac955SMatthias Ringwald     } else {
547*7dbac955SMatthias Ringwald         characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED;
548*7dbac955SMatthias Ringwald     }
549*7dbac955SMatthias Ringwald }
550*7dbac955SMatthias Ringwald 
551*7dbac955SMatthias Ringwald void mock_gatt_client_dump_services(void){
552*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
553*7dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
554*7dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
555*7dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
556*7dbac955SMatthias Ringwald         printf("0x%02x: START SERVICE ", service->start_group_handle);
557*7dbac955SMatthias Ringwald         if (service->uuid16) {
558*7dbac955SMatthias Ringwald             printf("%04x\n", service->uuid16);
559*7dbac955SMatthias Ringwald         } else {
560*7dbac955SMatthias Ringwald             printf("%s\n", uuid128_to_str(service->uuid128));
561*7dbac955SMatthias Ringwald         }
562*7dbac955SMatthias Ringwald 
563*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_t characteristic_it;
564*7dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
565*7dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
566*7dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
567*7dbac955SMatthias Ringwald             printf("0x%02x:   START CHR ", characteristic->start_handle);
568*7dbac955SMatthias Ringwald             if (characteristic->uuid16) {
569*7dbac955SMatthias Ringwald                 printf("%04x\n", characteristic->uuid16);
570*7dbac955SMatthias Ringwald             } else {
571*7dbac955SMatthias Ringwald                 printf("%s\n", uuid128_to_str(characteristic->uuid128));
572*7dbac955SMatthias Ringwald             }
573*7dbac955SMatthias Ringwald             printf("0x%02x:   VALUE HANDLE CHR\n", characteristic->value_handle);
574*7dbac955SMatthias Ringwald 
575*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
576*7dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
577*7dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
578*7dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
579*7dbac955SMatthias Ringwald                 printf("0x%02x:     DESC 0x%02x\n", desc->handle, desc->uuid16);
580*7dbac955SMatthias Ringwald             }
581*7dbac955SMatthias Ringwald 
582*7dbac955SMatthias Ringwald             printf("0x%02x:   END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16);
583*7dbac955SMatthias Ringwald         }
584*7dbac955SMatthias Ringwald         printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16);
585*7dbac955SMatthias Ringwald 
586*7dbac955SMatthias Ringwald     }
587*7dbac955SMatthias Ringwald }
588*7dbac955SMatthias Ringwald 
589*7dbac955SMatthias Ringwald static void mock_gatt_client_add_primary_service(void){
590*7dbac955SMatthias Ringwald     // set lsat group handle
591*7dbac955SMatthias Ringwald     // create new service
592*7dbac955SMatthias Ringwald     mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t));
593*7dbac955SMatthias Ringwald     memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t));
594*7dbac955SMatthias Ringwald     mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++;
595*7dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle;
596*7dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service);
597*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic = NULL;
598*7dbac955SMatthias Ringwald }
599*7dbac955SMatthias Ringwald 
600*7dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){
601*7dbac955SMatthias Ringwald     mock_gatt_client_add_primary_service();
602*7dbac955SMatthias Ringwald     mock_gatt_client_last_service->uuid16 = service_uuid;
603*7dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_last_service->uuid128, service_uuid);
604*7dbac955SMatthias Ringwald     return mock_gatt_client_last_service;
605*7dbac955SMatthias Ringwald }
606*7dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid128(const uint8_t * service_uuid){
607*7dbac955SMatthias Ringwald     mock_gatt_client_add_primary_service();
608*7dbac955SMatthias Ringwald     (void) memcpy(mock_gatt_client_last_service->uuid128, service_uuid, 16);
609*7dbac955SMatthias Ringwald     return mock_gatt_client_last_service;
610*7dbac955SMatthias Ringwald }
611*7dbac955SMatthias Ringwald 
612*7dbac955SMatthias Ringwald static void mock_gatt_client_add_characteristic(uint16_t properties){
613*7dbac955SMatthias Ringwald     btstack_assert(mock_gatt_client_last_service != NULL);
614*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t));
615*7dbac955SMatthias Ringwald     memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t));
616*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->properties = properties;
617*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++;
618*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++;
619*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle;
620*7dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic);
621*7dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
622*7dbac955SMatthias Ringwald }
623*7dbac955SMatthias Ringwald 
624*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){
625*7dbac955SMatthias Ringwald     mock_gatt_client_add_characteristic(properties);
626*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid;
627*7dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid);
628*7dbac955SMatthias Ringwald     return mock_gatt_client_last_characteristic;
629*7dbac955SMatthias Ringwald }
630*7dbac955SMatthias Ringwald 
631*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid128(const uint8_t * characteristic_uuid, uint16_t properties){
632*7dbac955SMatthias Ringwald     mock_gatt_client_add_characteristic(properties);
633*7dbac955SMatthias Ringwald     (void) memcpy(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid, 16);
634*7dbac955SMatthias Ringwald     return mock_gatt_client_last_characteristic;
635*7dbac955SMatthias Ringwald }
636*7dbac955SMatthias Ringwald 
637*7dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor(void){
638*7dbac955SMatthias Ringwald     btstack_assert(mock_gatt_client_last_characteristic != NULL);
639*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t));
640*7dbac955SMatthias Ringwald     memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t));
641*7dbac955SMatthias Ringwald     desc->handle = mock_gatt_client_att_handle_generator++;
642*7dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc);
643*7dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1;
644*7dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
645*7dbac955SMatthias Ringwald     return desc;
646*7dbac955SMatthias Ringwald }
647*7dbac955SMatthias Ringwald 
648*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){
649*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
650*7dbac955SMatthias Ringwald     desc->uuid16 = descriptor_uuid;
651*7dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(desc->uuid128, descriptor_uuid);
652*7dbac955SMatthias Ringwald     return desc;
653*7dbac955SMatthias Ringwald }
654*7dbac955SMatthias Ringwald 
655*7dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid128(const uint8_t * descriptor_uuid){
656*7dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
657*7dbac955SMatthias Ringwald     (void) memcpy(desc->uuid128, descriptor_uuid, 16);
658*7dbac955SMatthias Ringwald     return desc;
659*7dbac955SMatthias Ringwald }
660*7dbac955SMatthias Ringwald 
661*7dbac955SMatthias Ringwald void mock_gatt_client_set_descriptor_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){
662*7dbac955SMatthias Ringwald     btstack_assert(descriptor != NULL);
663*7dbac955SMatthias Ringwald     descriptor->value_buffer = value_buffer;
664*7dbac955SMatthias Ringwald     descriptor->value_len = value_len;
665*7dbac955SMatthias Ringwald }
666*7dbac955SMatthias Ringwald 
667*7dbac955SMatthias Ringwald void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
668*7dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
669*7dbac955SMatthias Ringwald     characteristic->value_buffer = value_buffer;
670*7dbac955SMatthias Ringwald     characteristic->value_len = value_len;
671*7dbac955SMatthias Ringwald }
672*7dbac955SMatthias Ringwald 
673*7dbac955SMatthias Ringwald // simulate error
674*7dbac955SMatthias Ringwald void mock_gatt_client_simulate_att_error(uint8_t att_error){
675*7dbac955SMatthias Ringwald     mock_gatt_client_att_error = att_error;
676*7dbac955SMatthias Ringwald }
677