xref: /btstack/test/mock/mock_gatt_client.c (revision 43bef108c248ed553b4f1acb68282c41ee9c646c)
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 
9*43bef108SMatthias Ringwald //#include "CppUTest/TestHarness.h"
10*43bef108SMatthias Ringwald //#include "CppUTestExt/MockSupport.h"
110f7fd6c1SMilanka Ringwald 
12af770404SMilanka Ringwald static enum {
13af770404SMilanka Ringwald     MOCK_QUERY_IDLE = 0,
147dbac955SMatthias Ringwald     MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID,
157dbac955SMatthias Ringwald     MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID,
167dbac955SMatthias 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;
267dbac955SMatthias 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 
1547dbac955SMatthias 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);
1587dbac955SMatthias 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 
1627dbac955SMatthias 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 
1667dbac955SMatthias 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){
1677dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
1687dbac955SMatthias Ringwald     btstack_assert(characteristic->notification != NULL);
1697dbac955SMatthias Ringwald     btstack_assert(characteristic->notification->callback != NULL);
1707dbac955SMatthias Ringwald     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, gatt_client.con_handle, value_handle, (uint8_t *) value_buffer, value_len);
1717dbac955SMatthias Ringwald     emit_event(characteristic->notification->callback, packet, 2 + packet[1]);
1727dbac955SMatthias Ringwald }
1737dbac955SMatthias Ringwald 
1747dbac955SMatthias Ringwald void mock_gatt_client_send_indication(mock_gatt_client_characteristic_t * characteristic, const uint8_t * value_buffer, uint16_t value_len){
1757dbac955SMatthias Ringwald     mock_gatt_client_send_indication_with_handle(characteristic, characteristic->value_handle, value_buffer, value_len);
1767dbac955SMatthias Ringwald }
1777dbac955SMatthias 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 
1877dbac955SMatthias Ringwald 
1887dbac955SMatthias Ringwald static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){
1897dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
1907dbac955SMatthias Ringwald     btstack_linked_list_iterator_t characteristic_it;
1917dbac955SMatthias Ringwald 
1927dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
1937dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
1947dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
1957dbac955SMatthias Ringwald 
1967dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
1977dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
1987dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
1997dbac955SMatthias Ringwald             if (characteristic->value_handle != value_handle) continue;
2007dbac955SMatthias Ringwald             return characteristic;
2017dbac955SMatthias Ringwald         }
2027dbac955SMatthias Ringwald     }
2037dbac955SMatthias Ringwald     return NULL;
2047dbac955SMatthias Ringwald }
2057dbac955SMatthias Ringwald 
2067dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){
2077dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
2087dbac955SMatthias Ringwald     btstack_linked_list_iterator_t characteristic_it;
2097dbac955SMatthias Ringwald 
2107dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
2117dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
2127dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
2137dbac955SMatthias Ringwald 
2147dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
2157dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
2167dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
2177dbac955SMatthias Ringwald 
2187dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
2197dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
2207dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
2217dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
2227dbac955SMatthias Ringwald                 if (desc->handle != handle) continue;
2237dbac955SMatthias Ringwald                 return desc;
2247dbac955SMatthias Ringwald             }
2257dbac955SMatthias Ringwald         }
2267dbac955SMatthias Ringwald     }
2277dbac955SMatthias Ringwald     return NULL;
2287dbac955SMatthias Ringwald }
2297dbac955SMatthias Ringwald 
2307dbac955SMatthias Ringwald uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
2317dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
2327dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
2337dbac955SMatthias Ringwald     gatt_client.callback = callback;
2347dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
2357dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
2367dbac955SMatthias Ringwald }
2377dbac955SMatthias Ringwald 
2387dbac955SMatthias 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){
2397dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID;
2407dbac955SMatthias Ringwald     memcpy(mock_gatt_client_uuid128, uuid128, 16);
2417dbac955SMatthias Ringwald     gatt_client.callback = callback;
2427dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
2437dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
2447dbac955SMatthias Ringwald }
2457dbac955SMatthias Ringwald 
2467dbac955SMatthias 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){
2477dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID;
2487dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_uuid128, uuid16);
2497dbac955SMatthias Ringwald     mock_gatt_client_start_handle = start_handle;
2507dbac955SMatthias Ringwald     mock_gatt_client_end_handle = end_handle;
2517dbac955SMatthias Ringwald 
2527dbac955SMatthias Ringwald     gatt_client.callback = callback;
2537dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
2547dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
2557dbac955SMatthias Ringwald }
2567dbac955SMatthias Ringwald 
2577dbac955SMatthias 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){
2587dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_ALL_CHARACTERISTICS;
2597dbac955SMatthias Ringwald     mock_gatt_client_start_handle = service->start_group_handle;
2607dbac955SMatthias Ringwald     mock_gatt_client_end_handle = service->end_group_handle;
2617dbac955SMatthias Ringwald     gatt_client.callback = callback;
2627dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
2637dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
2647dbac955SMatthias Ringwald }
2657dbac955SMatthias Ringwald 
2667dbac955SMatthias Ringwald uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
2677dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS;
2687dbac955SMatthias Ringwald     mock_gatt_client_value_handle = characteristic->value_handle;
2697dbac955SMatthias Ringwald 
2707dbac955SMatthias Ringwald     gatt_client.callback = callback;
2717dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
2727dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
2737dbac955SMatthias Ringwald }
2747dbac955SMatthias Ringwald 
2757dbac955SMatthias 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){
2767dbac955SMatthias Ringwald     btstack_assert(notification != NULL);
2777dbac955SMatthias Ringwald     btstack_assert(&callback != NULL);
2787dbac955SMatthias Ringwald 
2797dbac955SMatthias Ringwald     notification->callback = callback;
2807dbac955SMatthias Ringwald     notification->con_handle = con_handle;
2817dbac955SMatthias Ringwald 
2827dbac955SMatthias Ringwald 
2837dbac955SMatthias Ringwald     if (characteristic == NULL){
2847dbac955SMatthias Ringwald         // 'all characteristics': not used yet
2857dbac955SMatthias Ringwald         btstack_assert(false);
2867dbac955SMatthias Ringwald     } else {
2877dbac955SMatthias Ringwald         mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
2887dbac955SMatthias Ringwald         btstack_assert(mock_characteristic != NULL);
2897dbac955SMatthias Ringwald 
2907dbac955SMatthias Ringwald         notification->attribute_handle = characteristic->value_handle;
2917dbac955SMatthias Ringwald         mock_characteristic->notification = notification;
2927dbac955SMatthias Ringwald     }
2937dbac955SMatthias Ringwald }
2947dbac955SMatthias Ringwald 
2957dbac955SMatthias 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){
2967dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
2977dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
2987dbac955SMatthias Ringwald 
2997dbac955SMatthias Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
3007dbac955SMatthias Ringwald         return mock_characteristic->notification_status_code;
3017dbac955SMatthias Ringwald     }
3027dbac955SMatthias Ringwald 
3037dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
3047dbac955SMatthias Ringwald 
3057dbac955SMatthias Ringwald     gatt_client.callback = callback;
3067dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
3077dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
3087dbac955SMatthias Ringwald }
3097dbac955SMatthias Ringwald 
3107dbac955SMatthias 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){
3117dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
3127dbac955SMatthias Ringwald 
3137dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
3147dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
3157dbac955SMatthias Ringwald 
3167dbac955SMatthias Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
3177dbac955SMatthias Ringwald     gatt_client.callback = callback;
3187dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
3197dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
3207dbac955SMatthias Ringwald }
3217dbac955SMatthias Ringwald 
3227dbac955SMatthias 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){
3237dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
3247dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE;
3257dbac955SMatthias Ringwald 
3267dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle);
3277dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
3287dbac955SMatthias Ringwald 
3297dbac955SMatthias Ringwald     gatt_client.callback = callback;
3307dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
3317dbac955SMatthias Ringwald     mock_gatt_client_value_handle = mock_characteristic->value_handle;
3327dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
3337dbac955SMatthias Ringwald }
3347dbac955SMatthias Ringwald 
3357dbac955SMatthias 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){
3367dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_DESCRIPTOR_USING_VALUE_HANDLE;
3377dbac955SMatthias Ringwald     mock_gatt_client_value_handle = descriptor_handle;
3387dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
3397dbac955SMatthias Ringwald }
3407dbac955SMatthias Ringwald 
3417dbac955SMatthias Ringwald void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
3427dbac955SMatthias Ringwald }
3437dbac955SMatthias Ringwald 
3447dbac955SMatthias 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){
3457dbac955SMatthias Ringwald     mock_gatt_client_characteristic_t * mock_characteristic  = mock_gatt_client_get_characteristic_for_value_handle(value_handle);
3467dbac955SMatthias Ringwald     btstack_assert(mock_characteristic != NULL);
3477dbac955SMatthias Ringwald 
3487dbac955SMatthias Ringwald     if (mock_characteristic->notification_status_code != ERROR_CODE_SUCCESS){
3497dbac955SMatthias Ringwald         return mock_characteristic->notification_status_code;
3507dbac955SMatthias Ringwald     }
3517dbac955SMatthias Ringwald 
3527dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
3537dbac955SMatthias Ringwald 
3547dbac955SMatthias Ringwald     gatt_client.callback = callback;
3557dbac955SMatthias Ringwald     gatt_client.con_handle = con_handle;
3567dbac955SMatthias Ringwald     return ERROR_CODE_SUCCESS;
3577dbac955SMatthias Ringwald }
3587dbac955SMatthias 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){
3747dbac955SMatthias 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);
3847dbac955SMatthias Ringwald                 if (memcmp(service->uuid128, mock_gatt_client_uuid128, 16) != 0) continue;
3857da2c1baSMilanka Ringwald                 mock_gatt_client_last_service = service;
3867dbac955SMatthias 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 
3927dbac955SMatthias Ringwald         case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID:
3937dbac955SMatthias 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;
4097dbac955SMatthias 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,
4137dbac955SMatthias 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 
4347dbac955SMatthias 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 }
4837dbac955SMatthias Ringwald 
4847dbac955SMatthias Ringwald static void mock_gatt_client_reset_errors(void){
4857dbac955SMatthias Ringwald     moc_att_error_code_discover_services = ATT_ERROR_SUCCESS;
4867dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS;
4877dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS;
4887dbac955SMatthias Ringwald 
4897dbac955SMatthias Ringwald     mock_gatt_client_wrong_con_handle = false;
4907dbac955SMatthias Ringwald     mock_gatt_client_wrong_value_handle = false;
4917dbac955SMatthias Ringwald }
4927dbac955SMatthias Ringwald 
4937dbac955SMatthias Ringwald void mock_gatt_client_reset(void){
4947dbac955SMatthias Ringwald     mock_gatt_client_att_error = 0;
4957dbac955SMatthias Ringwald     mock_gatt_client_state = MOCK_QUERY_IDLE;
4967dbac955SMatthias Ringwald     mock_gatt_client_att_handle_generator = 0;
4977dbac955SMatthias Ringwald     mock_gatt_client_last_service = NULL;
4987dbac955SMatthias Ringwald 
4997dbac955SMatthias Ringwald     mock_gatt_client_reset_errors();
5007dbac955SMatthias Ringwald 
5017dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
5027dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
5037dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
5047dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
5057dbac955SMatthias Ringwald         btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service);
5067dbac955SMatthias Ringwald 
5077dbac955SMatthias Ringwald         btstack_linked_list_iterator_t characteristic_it;
5087dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
5097dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
5107dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
5117dbac955SMatthias Ringwald             btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic);
5127dbac955SMatthias Ringwald 
5137dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
5147dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
5157dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
5167dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
5177dbac955SMatthias Ringwald                 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc);
5187dbac955SMatthias Ringwald                 free(desc);
5197dbac955SMatthias Ringwald             }
5207dbac955SMatthias Ringwald             free(characteristic);
5217dbac955SMatthias Ringwald         }
5227dbac955SMatthias Ringwald         free(service);
5237dbac955SMatthias Ringwald     }
5247dbac955SMatthias Ringwald }
5257dbac955SMatthias Ringwald 
5267dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_primary_services(void){
5277dbac955SMatthias Ringwald     moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED;
5287dbac955SMatthias Ringwald }
5297dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristics(void){
5307dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED;
5317dbac955SMatthias Ringwald }
5327dbac955SMatthias Ringwald void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){
5337dbac955SMatthias Ringwald     moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED;
5347dbac955SMatthias Ringwald }
5357dbac955SMatthias Ringwald 
5367dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_con_handle(void){
5377dbac955SMatthias Ringwald     mock_gatt_client_wrong_con_handle = true;
5387dbac955SMatthias Ringwald }
5397dbac955SMatthias Ringwald void mock_gatt_client_simulate_invalid_value_handle(void){
5407dbac955SMatthias Ringwald     mock_gatt_client_wrong_value_handle = true;
5417dbac955SMatthias Ringwald }
5427dbac955SMatthias Ringwald 
5437dbac955SMatthias Ringwald void mock_gatt_client_enable_notification(mock_gatt_client_characteristic_t * characteristic, bool command_allowed){
5447dbac955SMatthias Ringwald     if (command_allowed){
5457dbac955SMatthias Ringwald         characteristic->notification_status_code = ERROR_CODE_SUCCESS;
5467dbac955SMatthias Ringwald     } else {
5477dbac955SMatthias Ringwald         characteristic->notification_status_code = ERROR_CODE_COMMAND_DISALLOWED;
5487dbac955SMatthias Ringwald     }
5497dbac955SMatthias Ringwald }
5507dbac955SMatthias Ringwald 
5517dbac955SMatthias Ringwald void mock_gatt_client_dump_services(void){
5527dbac955SMatthias Ringwald     btstack_linked_list_iterator_t service_it;
5537dbac955SMatthias Ringwald     btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services);
5547dbac955SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&service_it)){
5557dbac955SMatthias Ringwald         mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it);
5567dbac955SMatthias Ringwald         printf("0x%02x: START SERVICE ", service->start_group_handle);
5577dbac955SMatthias Ringwald         if (service->uuid16) {
5587dbac955SMatthias Ringwald             printf("%04x\n", service->uuid16);
5597dbac955SMatthias Ringwald         } else {
5607dbac955SMatthias Ringwald             printf("%s\n", uuid128_to_str(service->uuid128));
5617dbac955SMatthias Ringwald         }
5627dbac955SMatthias Ringwald 
5637dbac955SMatthias Ringwald         btstack_linked_list_iterator_t characteristic_it;
5647dbac955SMatthias Ringwald         btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics);
5657dbac955SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&characteristic_it)){
5667dbac955SMatthias Ringwald             mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it);
5677dbac955SMatthias Ringwald             printf("0x%02x:   START CHR ", characteristic->start_handle);
5687dbac955SMatthias Ringwald             if (characteristic->uuid16) {
5697dbac955SMatthias Ringwald                 printf("%04x\n", characteristic->uuid16);
5707dbac955SMatthias Ringwald             } else {
5717dbac955SMatthias Ringwald                 printf("%s\n", uuid128_to_str(characteristic->uuid128));
5727dbac955SMatthias Ringwald             }
5737dbac955SMatthias Ringwald             printf("0x%02x:   VALUE HANDLE CHR\n", characteristic->value_handle);
5747dbac955SMatthias Ringwald 
5757dbac955SMatthias Ringwald             btstack_linked_list_iterator_t desc_it;
5767dbac955SMatthias Ringwald             btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors);
5777dbac955SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&desc_it)){
5787dbac955SMatthias Ringwald                 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it);
5797dbac955SMatthias Ringwald                 printf("0x%02x:     DESC 0x%02x\n", desc->handle, desc->uuid16);
5807dbac955SMatthias Ringwald             }
5817dbac955SMatthias Ringwald 
5827dbac955SMatthias Ringwald             printf("0x%02x:   END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16);
5837dbac955SMatthias Ringwald         }
5847dbac955SMatthias Ringwald         printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16);
5857dbac955SMatthias Ringwald 
5867dbac955SMatthias Ringwald     }
5877dbac955SMatthias Ringwald }
5887dbac955SMatthias Ringwald 
5897dbac955SMatthias Ringwald static void mock_gatt_client_add_primary_service(void){
5907dbac955SMatthias Ringwald     // set lsat group handle
5917dbac955SMatthias Ringwald     // create new service
5927dbac955SMatthias Ringwald     mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t));
5937dbac955SMatthias Ringwald     memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t));
5947dbac955SMatthias Ringwald     mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++;
5957dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle;
5967dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service);
5977dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic = NULL;
5987dbac955SMatthias Ringwald }
5997dbac955SMatthias Ringwald 
6007dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){
6017dbac955SMatthias Ringwald     mock_gatt_client_add_primary_service();
6027dbac955SMatthias Ringwald     mock_gatt_client_last_service->uuid16 = service_uuid;
6037dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_last_service->uuid128, service_uuid);
6047dbac955SMatthias Ringwald     return mock_gatt_client_last_service;
6057dbac955SMatthias Ringwald }
6067dbac955SMatthias Ringwald mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid128(const uint8_t * service_uuid){
6077dbac955SMatthias Ringwald     mock_gatt_client_add_primary_service();
6087dbac955SMatthias Ringwald     (void) memcpy(mock_gatt_client_last_service->uuid128, service_uuid, 16);
6097dbac955SMatthias Ringwald     return mock_gatt_client_last_service;
6107dbac955SMatthias Ringwald }
6117dbac955SMatthias Ringwald 
6127dbac955SMatthias Ringwald static void mock_gatt_client_add_characteristic(uint16_t properties){
6137dbac955SMatthias Ringwald     btstack_assert(mock_gatt_client_last_service != NULL);
6147dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t));
6157dbac955SMatthias Ringwald     memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t));
6167dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->properties = properties;
6177dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++;
6187dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++;
6197dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle;
6207dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic);
6217dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
6227dbac955SMatthias Ringwald }
6237dbac955SMatthias Ringwald 
6247dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){
6257dbac955SMatthias Ringwald     mock_gatt_client_add_characteristic(properties);
6267dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid;
6277dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid);
6287dbac955SMatthias Ringwald     return mock_gatt_client_last_characteristic;
6297dbac955SMatthias Ringwald }
6307dbac955SMatthias Ringwald 
6317dbac955SMatthias Ringwald mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid128(const uint8_t * characteristic_uuid, uint16_t properties){
6327dbac955SMatthias Ringwald     mock_gatt_client_add_characteristic(properties);
6337dbac955SMatthias Ringwald     (void) memcpy(mock_gatt_client_last_characteristic->uuid128, characteristic_uuid, 16);
6347dbac955SMatthias Ringwald     return mock_gatt_client_last_characteristic;
6357dbac955SMatthias Ringwald }
6367dbac955SMatthias Ringwald 
6377dbac955SMatthias Ringwald static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor(void){
6387dbac955SMatthias Ringwald     btstack_assert(mock_gatt_client_last_characteristic != NULL);
6397dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t));
6407dbac955SMatthias Ringwald     memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t));
6417dbac955SMatthias Ringwald     desc->handle = mock_gatt_client_att_handle_generator++;
6427dbac955SMatthias Ringwald     btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc);
6437dbac955SMatthias Ringwald     mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1;
6447dbac955SMatthias Ringwald     mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1;
6457dbac955SMatthias Ringwald     return desc;
6467dbac955SMatthias Ringwald }
6477dbac955SMatthias Ringwald 
6487dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){
6497dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
6507dbac955SMatthias Ringwald     desc->uuid16 = descriptor_uuid;
6517dbac955SMatthias Ringwald     uuid_add_bluetooth_prefix(desc->uuid128, descriptor_uuid);
6527dbac955SMatthias Ringwald     return desc;
6537dbac955SMatthias Ringwald }
6547dbac955SMatthias Ringwald 
6557dbac955SMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid128(const uint8_t * descriptor_uuid){
6567dbac955SMatthias Ringwald     mock_gatt_client_characteristic_descriptor_t * desc = mock_gatt_client_add_characteristic_descriptor();
6577dbac955SMatthias Ringwald     (void) memcpy(desc->uuid128, descriptor_uuid, 16);
6587dbac955SMatthias Ringwald     return desc;
6597dbac955SMatthias Ringwald }
6607dbac955SMatthias Ringwald 
6617dbac955SMatthias Ringwald void mock_gatt_client_set_descriptor_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){
6627dbac955SMatthias Ringwald     btstack_assert(descriptor != NULL);
6637dbac955SMatthias Ringwald     descriptor->value_buffer = value_buffer;
6647dbac955SMatthias Ringwald     descriptor->value_len = value_len;
6657dbac955SMatthias Ringwald }
6667dbac955SMatthias Ringwald 
6677dbac955SMatthias Ringwald void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_t * characteristic, uint8_t * value_buffer, uint16_t value_len){
6687dbac955SMatthias Ringwald     btstack_assert(characteristic != NULL);
6697dbac955SMatthias Ringwald     characteristic->value_buffer = value_buffer;
6707dbac955SMatthias Ringwald     characteristic->value_len = value_len;
6717dbac955SMatthias Ringwald }
6727dbac955SMatthias Ringwald 
6737dbac955SMatthias Ringwald // simulate error
6747dbac955SMatthias Ringwald void mock_gatt_client_simulate_att_error(uint8_t att_error){
6757dbac955SMatthias Ringwald     mock_gatt_client_att_error = att_error;
6767dbac955SMatthias Ringwald }
677