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