1 // ***************************************************************************** 2 // 3 // test ANCS Client 4 // 5 // ***************************************************************************** 6 7 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "CppUTest/TestHarness.h" 14 #include "CppUTest/CommandLineTestRunner.h" 15 #include "CppUTestExt/MockSupport.h" 16 17 #include "bluetooth.h" 18 #include "bluetooth_gatt.h" 19 #include "btstack_debug.h" 20 #include "btstack_event.h" 21 #include "btstack_memory.h" 22 #include "btstack_util.h" 23 #include "hci.h" 24 25 #include "ble/gatt-service/ancs_client.h" 26 #include "mock_gatt_client.h" 27 28 extern "C" void ancs_client_set_invalid_parser_state(void); 29 30 // mock hci 31 32 static const uint8_t ancs_service_uuid[] = {0x79,0x05,0xF4,0x31,0xB5,0xCE,0x4E,0x99,0xA4,0x0F,0x4B,0x1E,0x12,0x2D,0x00,0xD0}; 33 static const uint8_t ancs_notification_source_uuid[] = {0x9F,0xBF,0x12,0x0D,0x63,0x01,0x42,0xD9,0x8C,0x58,0x25,0xE6,0x99,0xA2,0x1D,0xBD}; 34 static const uint8_t ancs_control_point_uuid[] = {0x69,0xD1,0xD8,0xF3,0x45,0xE1,0x49,0xA8,0x98,0x21,0x9B,0xBD,0xFD,0xAA,0xD9,0xD9}; 35 static const uint8_t ancs_data_source_uuid[] = {0x22,0xEA,0xC6,0xE9,0x24,0xD6,0x4B,0xB5,0xBE,0x44,0xB3,0x6A,0xCE,0x7C,0x7B,0xFB}; 36 37 static btstack_packet_callback_registration_t * ancs_callback_registration; 38 static const hci_con_handle_t ancs_con_handle = 0x001; 39 static bool ancs_connected; 40 41 void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){ 42 ancs_callback_registration = callback_handler; 43 } 44 45 static void hci_emit_event(uint8_t * event, uint16_t size, int dump){ 46 btstack_assert(ancs_callback_registration != NULL); 47 (*ancs_callback_registration->callback)(HCI_EVENT_PACKET, 0, event, size); 48 } 49 50 static void hci_create_gap_connection_complete_event(const uint8_t * hci_event, uint8_t * gap_event) { 51 gap_event[0] = HCI_EVENT_META_GAP; 52 gap_event[1] = 36 - 2; 53 gap_event[2] = GAP_SUBEVENT_LE_CONNECTION_COMPLETE; 54 switch (hci_event[2]){ 55 case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: 56 memcpy(&gap_event[3], &hci_event[3], 11); 57 memset(&gap_event[14], 0, 12); 58 memcpy(&gap_event[26], &hci_event[14], 7); 59 memset(&gap_event[33], 0xff, 3); 60 break; 61 case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE_V1: 62 memcpy(&gap_event[3], &hci_event[3], 30); 63 memset(&gap_event[33], 0xff, 3); 64 break; 65 case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE_V2: 66 memcpy(&gap_event[3], &hci_event[3], 33); 67 break; 68 default: 69 btstack_unreachable(); 70 break; 71 } 72 } 73 74 static void hci_emit_le_connection_complete(uint8_t address_type, const bd_addr_t address, hci_con_handle_t con_handle, uint8_t status){ 75 uint8_t hci_event[21]; 76 hci_event[0] = HCI_EVENT_LE_META; 77 hci_event[1] = sizeof(hci_event) - 2u; 78 hci_event[2] = HCI_SUBEVENT_LE_CONNECTION_COMPLETE; 79 hci_event[3] = status; 80 little_endian_store_16(hci_event, 4, con_handle); 81 hci_event[6] = 0; // TODO: role 82 hci_event[7] = address_type; 83 reverse_bd_addr(address, &hci_event[8]); 84 little_endian_store_16(hci_event, 14, 0); // interval 85 little_endian_store_16(hci_event, 16, 0); // latency 86 little_endian_store_16(hci_event, 18, 0); // supervision timeout 87 hci_event[20] = 0; // master clock accuracy 88 // emit GAP event, too 89 uint8_t gap_event[36]; 90 hci_create_gap_connection_complete_event(hci_event, gap_event); 91 hci_emit_event(gap_event, sizeof(gap_event), 1); 92 } 93 94 static void hci_emit_connection_encrypted(hci_con_handle_t con_handle, uint8_t encrypted){ 95 uint8_t encryption_complete_event[6] = { HCI_EVENT_ENCRYPTION_CHANGE, 4, 0, 0, 0, 0}; 96 little_endian_store_16(encryption_complete_event, 3, con_handle); 97 encryption_complete_event[5] = encrypted; 98 hci_emit_event(encryption_complete_event, sizeof(encryption_complete_event), 0); 99 } 100 101 static void hci_emit_disconnection_complete(hci_con_handle_t con_handle, uint8_t reason){ 102 uint8_t event[6]; 103 event[0] = HCI_EVENT_DISCONNECTION_COMPLETE; 104 event[1] = sizeof(event) - 2u; 105 event[2] = 0; // status = OK 106 little_endian_store_16(event, 3, con_handle); 107 event[5] = reason; 108 hci_emit_event(event, sizeof(event), 1); 109 } 110 111 // mock sm 112 void sm_request_pairing(hci_con_handle_t con_handle){ 113 } 114 115 116 // temp btstack run loop mock 117 118 static btstack_timer_source_t * btstack_timer = NULL; 119 120 void btstack_run_lopo_deinit(void){ 121 btstack_timer = NULL; 122 } 123 124 void btstack_run_loop_add_timer(btstack_timer_source_t * timer){ 125 btstack_timer = timer; 126 } 127 128 int btstack_run_loop_remove_timer(btstack_timer_source_t * timer){ 129 btstack_timer = NULL; 130 return 1; 131 } 132 133 void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms){ 134 } 135 136 void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)){ 137 timer->process = process; 138 } 139 140 void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context){ 141 timer->context = context; 142 } 143 144 void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){ 145 return timer->context; 146 } 147 148 void mock_btstack_run_loop_trigger_timer(void){ 149 btstack_assert(btstack_timer != NULL); 150 (*btstack_timer->process)(btstack_timer); 151 } 152 153 static void ancs_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 154 UNUSED(packet_type); 155 UNUSED(channel); 156 UNUSED(size); 157 158 switch (hci_event_gattservice_meta_get_subevent_code(packet)){ 159 case ANCS_SUBEVENT_CLIENT_CONNECTED: 160 ancs_connected = true; 161 break; 162 default: 163 break; 164 } 165 } 166 167 TEST_GROUP(ANCS_CLIENT){ 168 mock_gatt_client_service_t * service; 169 mock_gatt_client_characteristic_t * ancs_data_source_characteristic; 170 mock_gatt_client_characteristic_t * ancs_notification_source_characteristic; 171 mock_gatt_client_characteristic_t * ancs_control_point_characteristic; 172 mock_gatt_client_characteristic_descriptor_t * descriptor; 173 174 uint8_t value_buffer[3]; 175 176 void setup(void){ 177 ancs_connected = false; 178 mock_gatt_client_reset(); 179 ancs_client_init(); 180 ancs_client_register_callback(&ancs_client_event_handler); 181 } 182 183 void setup_service(bool add_characteristics, bool add_descriptors){ 184 // TODO: setup ANCS Service 185 service = mock_gatt_client_add_primary_service_uuid128(ancs_service_uuid); 186 187 if (!add_characteristics) return; 188 ancs_control_point_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_control_point_uuid, ATT_PROPERTY_NOTIFY); 189 if (add_descriptors) { 190 descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION); 191 } 192 ancs_data_source_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_data_source_uuid, ATT_PROPERTY_NOTIFY); 193 if (add_descriptors) { 194 descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION); 195 } 196 ancs_notification_source_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_notification_source_uuid, ATT_PROPERTY_NOTIFY); 197 if (add_descriptors) { 198 descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION); 199 } 200 // mock_gatt_client_dump_services(); 201 202 } 203 204 void connect(void){ 205 // simulated connected 206 bd_addr_t some_address; 207 hci_emit_le_connection_complete(0, some_address, ancs_con_handle, ERROR_CODE_SUCCESS); 208 hci_emit_connection_encrypted(ancs_con_handle, 1); 209 } 210 211 void teardown(void){ 212 } 213 }; 214 215 216 TEST(ANCS_CLIENT, resolve_ids){ 217 for (int i = 0; i<6; i++){ 218 const char * name = ancs_client_attribute_name_for_id(i); 219 CHECK_TRUE(name != NULL); 220 } 221 CHECK_EQUAL(NULL, ancs_client_attribute_name_for_id(6)); 222 } 223 224 TEST(ANCS_CLIENT, ignored_events){ 225 // default hci event 226 uint8_t some_other_event[] = { 0, 0}; 227 hci_emit_event(some_other_event, sizeof(some_other_event), 0); 228 // default hci le subevent 229 uint8_t some_le_event[] = { HCI_EVENT_LE_META, 1, 0}; 230 hci_emit_event(some_le_event, sizeof(some_le_event), 0); 231 // encypted but different con handle 232 hci_emit_connection_encrypted(ancs_con_handle+1, 1); 233 // encypted but different state 234 hci_emit_connection_encrypted(ancs_con_handle, 1); 235 // non-encypted 236 hci_emit_connection_encrypted(ancs_con_handle, 0); 237 // disconnected different handle 238 hci_emit_disconnection_complete(ancs_con_handle+1,0); 239 // disconnected different handle 240 hci_emit_disconnection_complete(ancs_con_handle,0); 241 } 242 243 TEST(ANCS_CLIENT, connect_no_service){ 244 connect(); 245 mock_gatt_client_run(); 246 } 247 248 TEST(ANCS_CLIENT, connect_unexpected_event_during_service_disc){ 249 connect(); 250 mock_gatt_client_emit_dummy_event(); 251 } 252 253 TEST(ANCS_CLIENT, connect_unexpected_events){ 254 setup_service(true, true); 255 connect(); 256 mock_gatt_client_run_once(); 257 mock_gatt_client_emit_dummy_event(); 258 mock_gatt_client_run_once(); 259 mock_gatt_client_emit_dummy_event(); 260 mock_gatt_client_run_once(); 261 mock_gatt_client_emit_dummy_event(); 262 mock_gatt_client_run_once(); 263 mock_gatt_client_emit_dummy_event(); 264 } 265 266 TEST(ANCS_CLIENT, connect){ 267 setup_service(true, true); 268 connect(); 269 mock_gatt_client_run(); 270 CHECK_TRUE(ancs_connected); 271 } 272 273 TEST(ANCS_CLIENT, connect_extra_characteristic){ 274 setup_service(true, true); 275 mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, 0); 276 connect(); 277 mock_gatt_client_run(); 278 } 279 280 TEST(ANCS_CLIENT, disconnect){ 281 setup_service(true, true); 282 connect(); 283 mock_gatt_client_run(); 284 hci_emit_disconnection_complete(ancs_con_handle,0); 285 } 286 287 TEST(ANCS_CLIENT, notification_characteristic){ 288 setup_service(true, true); 289 connect(); 290 mock_gatt_client_run(); 291 const uint8_t data[] = {}; 292 mock_gatt_client_send_notification(ancs_notification_source_characteristic, data, sizeof(data)); 293 } 294 295 TEST(ANCS_CLIENT, data_source_characteristic){ 296 setup_service(true, true); 297 connect(); 298 mock_gatt_client_run(); 299 // simulate notification 300 const uint8_t notification_data[] = {0,0,0,0,0,0,0,0}; 301 mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data)); 302 // command id = 0 / CommandIDGetNotificationAttributes 303 // notification uid 0x1111 304 // attribute id 1 305 // len 1 306 // attribute id 2 307 // len 0 308 const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0}; 309 mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 310 } 311 312 TEST(ANCS_CLIENT, data_source_characteristic_no_handler){ 313 ancs_client_register_callback(NULL); 314 setup_service(true, true); 315 connect(); 316 mock_gatt_client_run(); 317 // simulate notification 318 const uint8_t notification_data[] = {0,0,0,0,0,0,0,0}; 319 mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data)); 320 // command id = 0 / CommandIDGetNotificationAttributes 321 // notification uid 0x1111 322 // attribute id 1 323 // len 1 324 // attribute id 2 325 // len 0 326 const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0}; 327 mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 328 } 329 330 TEST(ANCS_CLIENT, notifications_other){ 331 setup_service(true, true); 332 connect(); 333 mock_gatt_client_run(); 334 const uint8_t data[] = {}; 335 mock_gatt_client_send_notification_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data)); 336 } 337 338 TEST(ANCS_CLIENT, indications_other){ 339 setup_service(true, true); 340 connect(); 341 mock_gatt_client_run(); 342 const uint8_t data[] = {}; 343 mock_gatt_client_send_indication_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data)); 344 } 345 346 TEST(ANCS_CLIENT, notifications_invalid_parser){ 347 setup_service(true, true); 348 ancs_client_set_invalid_parser_state(); 349 connect(); 350 mock_gatt_client_run(); 351 const uint8_t data[] = {1,2,3,4,5,6}; 352 mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 353 } 354 355 int main (int argc, const char * argv[]){ 356 return CommandLineTestRunner::RunAllTests(argc, argv); 357 } 358