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