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