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