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