1 #include <stdint.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 #include "btstack_debug.h" 6 #include "mock_gatt_client.h" 7 8 #include "CppUTest/TestHarness.h" 9 #include "CppUTestExt/MockSupport.h" 10 11 static enum { 12 MOCK_QUERY_IDLE = 0, 13 MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16, 14 MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16, 15 MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS, 16 MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION, 17 MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE 18 } mock_gatt_client_state; 19 20 static uint16_t mock_gatt_client_att_handle_generator; 21 22 static uint8_t mock_gatt_client_att_error; 23 static uint16_t mock_gatt_client_uuid; 24 static uint16_t mock_gatt_client_value_handle; 25 static uint16_t mock_gatt_client_start_handle; 26 static uint16_t mock_gatt_client_end_handle; 27 28 static gatt_client_t gatt_client; 29 30 static btstack_linked_list_t mock_gatt_client_services; 31 32 static mock_gatt_client_service_t * mock_gatt_client_last_service; 33 static mock_gatt_client_characteristic_t * mock_gatt_client_last_characteristic; 34 35 static uint8_t moc_att_error_code_discover_services; 36 static uint8_t moc_att_error_code_discover_characteristics; 37 static uint8_t moc_att_error_code_discover_characteristic_descriptors; 38 39 static void mock_gatt_client_reset_att_errors(void){ 40 moc_att_error_code_discover_services = ATT_ERROR_SUCCESS; 41 moc_att_error_code_discover_characteristics = ATT_ERROR_SUCCESS; 42 moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_SUCCESS; 43 } 44 45 void mock_gatt_client_reset(void){ 46 mock_gatt_client_att_error = 0; 47 mock_gatt_client_state = MOCK_QUERY_IDLE; 48 mock_gatt_client_att_handle_generator = 0; 49 mock_gatt_client_last_service = NULL; 50 51 mock_gatt_client_reset_att_errors(); 52 53 btstack_linked_list_iterator_t service_it; 54 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 55 while (btstack_linked_list_iterator_has_next(&service_it)){ 56 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 57 btstack_linked_list_remove(&mock_gatt_client_services, (btstack_linked_item_t *) service); 58 59 btstack_linked_list_iterator_t characteristic_it; 60 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 61 while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 62 mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 63 btstack_linked_list_remove(&service->characteristics, (btstack_linked_item_t *) characteristic); 64 65 btstack_linked_list_iterator_t desc_it; 66 btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 67 while (btstack_linked_list_iterator_has_next(&desc_it)){ 68 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 69 btstack_linked_list_remove(&characteristic->descriptors, (btstack_linked_item_t *) desc); 70 free(desc); 71 } 72 free(characteristic); 73 } 74 free(service); 75 } 76 } 77 78 void mock_gatt_client_set_att_error_discover_primary_services(void){ 79 moc_att_error_code_discover_services = ATT_ERROR_REQUEST_NOT_SUPPORTED; 80 } 81 void mock_gatt_client_set_att_error_discover_characteristics(void){ 82 moc_att_error_code_discover_characteristics = ATT_ERROR_REQUEST_NOT_SUPPORTED; 83 } 84 void mock_gatt_client_set_att_error_discover_characteristic_descriptors(void){ 85 moc_att_error_code_discover_characteristic_descriptors = ATT_ERROR_REQUEST_NOT_SUPPORTED; 86 } 87 88 void mock_gatt_client_dump_services(void){ 89 btstack_linked_list_iterator_t service_it; 90 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 91 while (btstack_linked_list_iterator_has_next(&service_it)){ 92 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 93 printf("0x%02x: START SERVICE 0%02x\n", service->start_group_handle, service->uuid16); 94 95 btstack_linked_list_iterator_t characteristic_it; 96 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 97 while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 98 mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 99 printf("0x%02x: START CHR 0%02x\n", characteristic->start_handle, characteristic->uuid16); 100 printf("0x%02x: VALUE HANDLE CHR 0%02x\n", characteristic->value_handle, characteristic->uuid16); 101 102 btstack_linked_list_iterator_t desc_it; 103 btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 104 while (btstack_linked_list_iterator_has_next(&desc_it)){ 105 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 106 printf("0x%02x: DESC 0x%02x\n", desc->handle, desc->uuid16); 107 } 108 109 printf("0x%02x: END CHR 0%02x\n", characteristic->end_handle, characteristic->uuid16); 110 111 } 112 printf("0x%02x: END SERVICE 0%02x\n", service->end_group_handle, service->uuid16); 113 114 } 115 } 116 117 mock_gatt_client_service_t * mock_gatt_client_add_primary_service_uuid16(uint16_t service_uuid){ 118 // set lsat group handle 119 // create new service 120 mock_gatt_client_last_service = (mock_gatt_client_service_t * )malloc(sizeof(mock_gatt_client_service_t)); 121 memset(mock_gatt_client_last_service, 0, sizeof(mock_gatt_client_service_t)); 122 mock_gatt_client_last_service->uuid16 = service_uuid; 123 mock_gatt_client_last_service->start_group_handle = mock_gatt_client_att_handle_generator++; 124 mock_gatt_client_last_service->end_group_handle = mock_gatt_client_last_service->start_group_handle; 125 btstack_linked_list_add_tail(&mock_gatt_client_services, (btstack_linked_item_t*)mock_gatt_client_last_service); 126 mock_gatt_client_last_characteristic = NULL; 127 return mock_gatt_client_last_service; 128 } 129 130 mock_gatt_client_characteristic_t * mock_gatt_client_add_characteristic_uuid16(uint16_t characteristic_uuid, uint16_t properties){ 131 btstack_assert(mock_gatt_client_last_service != NULL); 132 mock_gatt_client_last_characteristic = (mock_gatt_client_characteristic_t * )malloc(sizeof(mock_gatt_client_characteristic_t)); 133 memset(mock_gatt_client_last_characteristic, 0, sizeof(mock_gatt_client_characteristic_t)); 134 mock_gatt_client_last_characteristic->uuid16 = characteristic_uuid; 135 mock_gatt_client_last_characteristic->properties = properties; 136 mock_gatt_client_last_characteristic->start_handle = mock_gatt_client_att_handle_generator++; 137 mock_gatt_client_last_characteristic->value_handle = mock_gatt_client_att_handle_generator++; 138 mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_last_characteristic->value_handle; 139 btstack_linked_list_add_tail(&mock_gatt_client_last_service->characteristics, (btstack_linked_item_t*)mock_gatt_client_last_characteristic); 140 mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1; 141 return mock_gatt_client_last_characteristic; 142 } 143 144 mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_add_characteristic_descriptor_uuid16(uint16_t descriptor_uuid){ 145 btstack_assert(mock_gatt_client_last_characteristic != NULL); 146 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t * )malloc(sizeof(mock_gatt_client_characteristic_descriptor_t)); 147 memset(desc, 0, sizeof(mock_gatt_client_characteristic_descriptor_t)); 148 desc->uuid16 = descriptor_uuid; 149 desc->handle = mock_gatt_client_att_handle_generator++; 150 btstack_linked_list_add_tail(&mock_gatt_client_last_characteristic->descriptors, (btstack_linked_item_t*)desc); 151 mock_gatt_client_last_characteristic->end_handle = mock_gatt_client_att_handle_generator - 1; 152 mock_gatt_client_last_service->end_group_handle = mock_gatt_client_att_handle_generator - 1; 153 return desc; 154 } 155 156 static mock_gatt_client_characteristic_t * mock_gatt_client_get_characteristic_for_value_handle(uint16_t value_handle){ 157 btstack_linked_list_iterator_t service_it; 158 btstack_linked_list_iterator_t characteristic_it; 159 160 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 161 while (btstack_linked_list_iterator_has_next(&service_it)){ 162 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 163 164 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 165 while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 166 mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 167 if (characteristic->value_handle != value_handle) continue; 168 return characteristic; 169 } 170 } 171 return NULL; 172 } 173 174 static mock_gatt_client_characteristic_descriptor_t * mock_gatt_client_get_characteristic_descriptor_for_handle(uint16_t handle){ 175 btstack_linked_list_iterator_t service_it; 176 btstack_linked_list_iterator_t characteristic_it; 177 178 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 179 while (btstack_linked_list_iterator_has_next(&service_it)){ 180 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 181 182 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 183 while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 184 mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 185 186 btstack_linked_list_iterator_t desc_it; 187 btstack_linked_list_iterator_init(&desc_it, &characteristic->descriptors); 188 while (btstack_linked_list_iterator_has_next(&desc_it)){ 189 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&desc_it); 190 if (desc->handle != handle) continue; 191 return desc; 192 } 193 } 194 } 195 return NULL; 196 } 197 198 199 void mock_gatt_client_set_characteristic_value(mock_gatt_client_characteristic_descriptor_t * descriptor, uint8_t * value_buffer, uint16_t value_len){ 200 btstack_assert(descriptor != NULL); 201 descriptor->value_buffer = value_buffer; 202 descriptor->value_len = value_len; 203 } 204 205 // simulate erro 206 void mock_gatt_client_simulate_att_error(uint8_t att_error){ 207 mock_gatt_client_att_error = att_error; 208 } 209 210 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){ 211 mock_gatt_client_state = MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16; 212 mock_gatt_client_uuid = uuid16; 213 214 gatt_client.callback = callback; 215 gatt_client.con_handle = con_handle; 216 return ERROR_CODE_SUCCESS; 217 } 218 219 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){ 220 mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16; 221 mock_gatt_client_uuid = uuid16; 222 mock_gatt_client_start_handle = start_handle; 223 mock_gatt_client_end_handle = end_handle; 224 225 gatt_client.callback = callback; 226 gatt_client.con_handle = con_handle; 227 return ERROR_CODE_SUCCESS; 228 } 229 230 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){ 231 mock_gatt_client_state = MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS; 232 mock_gatt_client_value_handle = characteristic->value_handle; 233 234 gatt_client.callback = callback; 235 gatt_client.con_handle = con_handle; 236 return ERROR_CODE_SUCCESS; 237 } 238 239 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){ 240 mock_gatt_client_state = MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION; 241 mock_gatt_client_uuid = characteristic->uuid16; 242 243 gatt_client.callback = callback; 244 gatt_client.con_handle = con_handle; 245 return ERROR_CODE_SUCCESS; 246 } 247 248 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){ 249 notification->callback = callback; 250 notification->con_handle = con_handle; 251 252 if (characteristic == NULL){ 253 // 'all characteristics': not used yet 254 btstack_assert(false); 255 } else { 256 notification->attribute_handle = characteristic->value_handle; 257 } 258 259 // finc our characteristic and set point to notification 260 } 261 262 263 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){ 264 mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE; 265 mock_gatt_client_value_handle = value_handle; 266 return ERROR_CODE_SUCCESS; 267 } 268 269 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){ 270 btstack_assert(characteristic != NULL); 271 mock_gatt_client_state = MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE; 272 mock_gatt_client_characteristic_t * mock_characteristic = mock_gatt_client_get_characteristic_for_value_handle(characteristic->value_handle); 273 274 btstack_assert(mock_characteristic != NULL); 275 276 mock_gatt_client_value_handle = mock_characteristic->value_handle; 277 return ERROR_CODE_SUCCESS; 278 } 279 280 void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){ 281 } 282 283 /** 284 * copied from gatt_client.c - START 285 */ 286 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){ 287 service->start_group_handle = little_endian_read_16(packet, offset); 288 service->end_group_handle = little_endian_read_16(packet, offset + 2); 289 reverse_128(&packet[offset + 4], service->uuid128); 290 if (uuid_has_bluetooth_prefix(service->uuid128)){ 291 service->uuid16 = big_endian_read_32(service->uuid128, 0); 292 } else { 293 service->uuid16 = 0; 294 } 295 } 296 297 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){ 298 characteristic->start_handle = little_endian_read_16(packet, offset); 299 characteristic->value_handle = little_endian_read_16(packet, offset + 2); 300 characteristic->end_handle = little_endian_read_16(packet, offset + 4); 301 characteristic->properties = little_endian_read_16(packet, offset + 6); 302 reverse_128(&packet[offset+8], characteristic->uuid128); 303 if (uuid_has_bluetooth_prefix(characteristic->uuid128)){ 304 characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0); 305 } else { 306 characteristic->uuid16 = 0; 307 } 308 } 309 310 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){ 311 descriptor->handle = little_endian_read_16(packet, offset); 312 reverse_128(&packet[offset+2], descriptor->uuid128); 313 if (uuid_has_bluetooth_prefix(descriptor->uuid128)){ 314 descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0); 315 } else { 316 descriptor->uuid16 = 0; 317 } 318 } 319 320 static void emit_event_new(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){ 321 if (!callback) return; 322 (*callback)(HCI_EVENT_PACKET, 0, packet, size); 323 } 324 325 static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){ 326 // @format H1 327 uint8_t packet[5]; 328 packet[0] = GATT_EVENT_QUERY_COMPLETE; 329 packet[1] = 3; 330 little_endian_store_16(packet, 2, gatt_client->con_handle); 331 packet[4] = att_status; 332 emit_event_new(gatt_client->callback, packet, sizeof(packet)); 333 } 334 335 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){ 336 // @format HX 337 uint8_t packet[24]; 338 packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT; 339 packet[1] = sizeof(packet) - 2u; 340 little_endian_store_16(packet, 2, gatt_client->con_handle); 341 /// 342 little_endian_store_16(packet, 4, start_group_handle); 343 little_endian_store_16(packet, 6, end_group_handle); 344 reverse_128(uuid128, &packet[8]); 345 emit_event_new(gatt_client->callback, packet, sizeof(packet)); 346 } 347 348 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, 349 uint16_t properties, const uint8_t * uuid128){ 350 // @format HY 351 uint8_t packet[28]; 352 packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT; 353 packet[1] = sizeof(packet) - 2u; 354 little_endian_store_16(packet, 2, gatt_client->con_handle); 355 /// 356 little_endian_store_16(packet, 4, start_handle); 357 little_endian_store_16(packet, 6, value_handle); 358 little_endian_store_16(packet, 8, end_handle); 359 little_endian_store_16(packet, 10, properties); 360 reverse_128(uuid128, &packet[12]); 361 emit_event_new(gatt_client->callback, packet, sizeof(packet)); 362 } 363 364 static void emit_gatt_all_characteristic_descriptors_result_event( 365 gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){ 366 // @format HZ 367 uint8_t packet[22]; 368 packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT; 369 packet[1] = sizeof(packet) - 2u; 370 little_endian_store_16(packet, 2, gatt_client->con_handle); 371 /// 372 little_endian_store_16(packet, 4, descriptor_handle); 373 reverse_128(uuid128, &packet[6]); 374 emit_event_new(gatt_client->callback, packet, sizeof(packet)); 375 } 376 377 378 static const int characteristic_value_event_header_size = 8; 379 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){ 380 // before the value inside the ATT PDU 381 uint8_t * packet = value - characteristic_value_event_header_size; 382 packet[0] = type; 383 packet[1] = characteristic_value_event_header_size - 2 + length; 384 little_endian_store_16(packet, 2, con_handle); 385 little_endian_store_16(packet, 4, attribute_handle); 386 little_endian_store_16(packet, 6, length); 387 return packet; 388 } 389 390 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes 391 static void report_gatt_characteristic_value(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * value, uint16_t length){ 392 uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, gatt_client->con_handle, attribute_handle, value, length); 393 emit_event_new(gatt_client->callback, packet, characteristic_value_event_header_size + length); 394 } 395 396 /** 397 * copied from gatt_client.c - END 398 */ 399 400 static void mock_gatt_client_emit_complete(uint8_t status){ 401 mock_gatt_client_state = MOCK_QUERY_IDLE; 402 emit_gatt_complete_event(&gatt_client, status); 403 } 404 405 void mock_gatt_client_run(void){ 406 btstack_assert(mock_gatt_client_state != MOCK_QUERY_IDLE); 407 mock_gatt_client_characteristic_t * characteristic; 408 mock_gatt_client_characteristic_descriptor_t * descriptor; 409 410 btstack_linked_list_iterator_t service_it; 411 btstack_linked_list_iterator_t characteristic_it; 412 btstack_linked_list_iterator_t descriptor_it; 413 414 uint8_t uuid128[16]; 415 416 while (mock_gatt_client_state != MOCK_QUERY_IDLE){ 417 switch (mock_gatt_client_state){ 418 case MOCK_QUERY_DISCOVER_PRIMARY_SERVICES_BY_UUID16: 419 // emit GATT_EVENT_SERVICE_QUERY_RESULT for each matching service 420 if (moc_att_error_code_discover_services != ATT_ERROR_SUCCESS){ 421 mock_gatt_client_emit_complete(moc_att_error_code_discover_services); 422 return; 423 } 424 425 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 426 while (btstack_linked_list_iterator_has_next(&service_it)){ 427 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 428 if (service->uuid16 != mock_gatt_client_uuid) continue; 429 mock_gatt_client_last_service = service; 430 uuid_add_bluetooth_prefix(uuid128, service->uuid16); 431 emit_gatt_service_query_result_event(&gatt_client, service->start_group_handle, service->end_group_handle, uuid128); 432 } 433 // emit GATT_EVENT_QUERY_COMPLETE 434 mock_gatt_client_emit_complete(ATT_ERROR_SUCCESS); 435 break; 436 437 case MOCK_QUERY_DISCOVER_CHARACTERISTICS_BY_UUID16: 438 // emit GATT_EVENT_CHARACTERISTIC_QUERY_RESULT for each matching characteristic 439 if (moc_att_error_code_discover_characteristics != ATT_ERROR_SUCCESS){ 440 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristics); 441 return; 442 } 443 444 btstack_linked_list_iterator_init(&service_it, &mock_gatt_client_services); 445 while (btstack_linked_list_iterator_has_next(&service_it)){ 446 mock_gatt_client_service_t * service = (mock_gatt_client_service_t *) btstack_linked_list_iterator_next(&service_it); 447 448 btstack_linked_list_iterator_init(&characteristic_it, &service->characteristics); 449 while (btstack_linked_list_iterator_has_next(&characteristic_it)){ 450 mock_gatt_client_characteristic_t * characteristic = (mock_gatt_client_characteristic_t *) btstack_linked_list_iterator_next(&characteristic_it); 451 if (characteristic->uuid16 != mock_gatt_client_uuid) continue; 452 if (characteristic->start_handle < mock_gatt_client_start_handle) continue; 453 if (characteristic->end_handle > mock_gatt_client_end_handle) continue; 454 455 uuid_add_bluetooth_prefix(uuid128, characteristic->uuid16); 456 emit_gatt_characteristic_query_result_event(&gatt_client, 457 characteristic->start_handle, characteristic->value_handle, characteristic->end_handle, 458 characteristic->properties, uuid128); 459 } 460 } 461 462 // emit GATT_EVENT_QUERY_COMPLETE 463 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 464 break; 465 466 case MOCK_QUERY_DISCOVER_CHARACTERISTIC_DESCRIPTORS: 467 characteristic = mock_gatt_client_get_characteristic_for_value_handle(mock_gatt_client_value_handle); 468 btstack_assert(characteristic != NULL); 469 470 if (moc_att_error_code_discover_characteristic_descriptors != ATT_ERROR_SUCCESS){ 471 mock_gatt_client_emit_complete(moc_att_error_code_discover_characteristic_descriptors); 472 return; 473 } 474 475 btstack_linked_list_iterator_init(&descriptor_it, &characteristic->descriptors); 476 while (btstack_linked_list_iterator_has_next(&descriptor_it)){ 477 mock_gatt_client_characteristic_descriptor_t * desc = (mock_gatt_client_characteristic_descriptor_t *) btstack_linked_list_iterator_next(&descriptor_it); 478 479 uuid_add_bluetooth_prefix(uuid128, desc->uuid16); 480 emit_gatt_all_characteristic_descriptors_result_event(&gatt_client, desc->handle, uuid128); 481 } 482 483 // emit GATT_EVENT_QUERY_COMPLETE 484 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 485 break; 486 487 case MOCK_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION: 488 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 489 break; 490 491 case MOCK_READ_VALUE_OF_CHARACTERISTIC_USING_VALUE_HANDLE: 492 descriptor = mock_gatt_client_get_characteristic_descriptor_for_handle(mock_gatt_client_value_handle); 493 btstack_assert(descriptor != NULL); 494 btstack_assert(descriptor->value_buffer != NULL); 495 496 report_gatt_characteristic_value(&gatt_client, descriptor->handle, descriptor->value_buffer, descriptor->value_len); 497 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 498 break; 499 500 default: 501 btstack_assert(false); 502 break; 503 } 504 } 505 mock_gatt_client_att_error = ERROR_CODE_SUCCESS; 506 mock_gatt_client_state = MOCK_QUERY_IDLE; 507 }