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