1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 39 #include <stdint.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include "CppUTest/TestHarness.h" 45 #include "CppUTest/CommandLineTestRunner.h" 46 47 #include "hci.h" 48 #include "ble/att_db.h" 49 #include "ble/att_db_util.h" 50 #include "btstack_util.h" 51 #include "bluetooth.h" 52 53 #include "btstack_crypto.h" 54 #include "bluetooth_gatt.h" 55 56 typedef enum { 57 READ_CALLBACK_MODE_RETURN_DEFAULT = 0, 58 READ_CALLBACK_MODE_RETURN_ONE_BYTE, 59 READ_CALLBACK_MODE_RETURN_PENDING 60 } read_callback_mode_t; 61 62 typedef enum { 63 WRITE_CALLBACK_MODE_RETURN_DEFAULT = 0, 64 WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING, 65 WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH 66 } write_callback_mode_t; 67 68 69 static uint8_t battery_level = 100; 70 static uint8_t att_request[200]; 71 static uint8_t att_response[1000]; 72 73 static read_callback_mode_t read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT; 74 static write_callback_mode_t write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 75 76 // these can be tweaked to report errors or some data as needed by test case 77 static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 78 switch (read_callback_mode){ 79 case READ_CALLBACK_MODE_RETURN_ONE_BYTE: 80 return att_read_callback_handle_byte(0x55, offset, buffer, buffer_size); 81 case READ_CALLBACK_MODE_RETURN_PENDING: 82 return ATT_READ_RESPONSE_PENDING; 83 default: 84 return 0; 85 } 86 } 87 88 static int att_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){ 89 switch (write_callback_mode){ 90 case WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING: 91 return ATT_ERROR_WRITE_RESPONSE_PENDING; 92 case WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH: 93 return ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH; 94 default: 95 return 0; 96 } 97 } 98 99 static uint16_t att_read_multiple_request(uint16_t num_value_handles, uint16_t * value_handles){ 100 att_request[0] = ATT_READ_MULTIPLE_REQUEST; 101 int i; 102 int offset = 1; 103 for (i=0;i<num_value_handles;i++){ 104 little_endian_store_16(att_request, offset, value_handles[i]); 105 offset += 2; 106 } 107 return offset; 108 } 109 110 static uint16_t att_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_length, const uint8_t * value){ 111 att_request[0] = request_type; 112 little_endian_store_16(att_request, 1, attribute_handle); 113 (void)memcpy(&att_request[3], value, value_length); 114 return 3 + value_length; 115 } 116 117 static uint16_t att_prepare_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_offset){ 118 att_request[0] = request_type; 119 little_endian_store_16(att_request, 1, attribute_handle); 120 little_endian_store_16(att_request, 3, value_offset); 121 return 5; 122 } 123 124 // ignore for now 125 extern "C" void btstack_crypto_aes128_cmac_generator(btstack_crypto_aes128_cmac_t * request, const uint8_t * key, uint16_t size, uint8_t (*get_byte_callback)(uint16_t pos), uint8_t * hash, void (* callback)(void * arg), void * callback_arg){ 126 } 127 128 TEST_GROUP(AttDb){ 129 att_connection_t att_connection; 130 uint16_t att_request_len; 131 uint16_t att_response_len; 132 uint8_t callback_buffer[10]; 133 134 void setup(void){ 135 memset(&callback_buffer, 0, sizeof(callback_buffer)); 136 137 read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE; 138 memset(&att_connection, 0, sizeof(att_connection)); 139 att_connection.max_mtu = 150; 140 att_connection.mtu = ATT_DEFAULT_MTU; 141 142 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 143 read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT; 144 145 // init att db util and add a service and characteristic 146 att_db_util_init(); 147 // 0x180F 148 att_db_util_add_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE); 149 // 0x2A19 150 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, ATT_PROPERTY_WRITE | ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 151 // 0x2A1B 152 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATE, ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 153 // 0x2A1A 154 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_POWER_STATE, ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1); 155 // 0x2A49 156 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_FEATURE, ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 157 // 0x2A35 158 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_MEASUREMENT, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1); 159 // 0x2A38 160 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BODY_SENSOR_LOCATION, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 161 162 const uint8_t uuid128[] = {0x00, 0x00, 0xFF, 0x11, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; 163 att_db_util_add_characteristic_uuid128(uuid128, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 164 165 // 0x2AA7 166 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_MEASUREMENT, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1); 167 168 // 0x2AAB 169 att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_RUN_TIME, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1); 170 171 // set callbacks 172 att_set_db(att_db_util_get_address()); 173 att_set_read_callback(&att_read_callback); 174 att_set_write_callback(&att_write_callback); 175 } 176 }; 177 178 TEST(AttDb, MtuExchange){ 179 // test some function 180 att_request_len = 3; 181 const uint8_t att_request[3] = { ATT_EXCHANGE_MTU_REQUEST, 0, att_connection.max_mtu}; 182 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 183 CHECK_EQUAL(att_request_len, att_response_len); 184 const uint8_t expected_response[] = { ATT_EXCHANGE_MTU_RESPONSE, att_connection.max_mtu, 0}; 185 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 186 } 187 188 189 TEST(AttDb, handle_read_multiple_request){ 190 uint16_t value_handles[2]; 191 uint16_t num_value_handles; 192 193 // less then two values 194 num_value_handles = 0; 195 memset(&value_handles, 0, sizeof(value_handles)); 196 { 197 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 198 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 199 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 200 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU}; 201 CHECK_EQUAL(sizeof(expected_response), att_response_len); 202 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 203 } 204 205 num_value_handles = 1; 206 value_handles[0] = 0x1; 207 { 208 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 209 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 210 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 211 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_PDU}; 212 CHECK_EQUAL(sizeof(expected_response), att_response_len); 213 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 214 } 215 216 // invalid handle 217 num_value_handles = 2; 218 value_handles[0] = 0x0; 219 { 220 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 221 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 222 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 223 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, 0, 0, ATT_ERROR_INVALID_HANDLE}; 224 CHECK_EQUAL(sizeof(expected_response), att_response_len); 225 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 226 } 227 228 num_value_handles = 2; 229 value_handles[0] = 0xF1; 230 value_handles[1] = 0xF2; 231 { 232 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 233 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 234 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 235 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[0], 0, ATT_ERROR_INVALID_HANDLE}; 236 CHECK_EQUAL(sizeof(expected_response), att_response_len); 237 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 238 } 239 240 // handle read not permitted 241 num_value_handles = 2; 242 value_handles[0] = 0x05; 243 value_handles[1] = 0x06; 244 { 245 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 246 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 247 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 248 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_READ_NOT_PERMITTED}; 249 CHECK_EQUAL(sizeof(expected_response), att_response_len); 250 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 251 } 252 253 // security validation (single case) 254 num_value_handles = 2; 255 value_handles[0] = 0x05; 256 value_handles[1] = 0x09; 257 { 258 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 259 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 260 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 261 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, ATT_READ_MULTIPLE_REQUEST, value_handles[1], 0, ATT_ERROR_INSUFFICIENT_AUTHENTICATION}; 262 CHECK_EQUAL(sizeof(expected_response), att_response_len); 263 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 264 } 265 266 267 // static read 268 num_value_handles = 2; 269 value_handles[0] = 0x03; 270 value_handles[1] = 0x05; 271 { 272 read_callback_mode = READ_CALLBACK_MODE_RETURN_ONE_BYTE; 273 274 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 275 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 276 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 277 const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64, 0x10, 0x06, 0x00, 0x1B, 0x2A}; 278 CHECK_EQUAL(sizeof(expected_response), att_response_len); 279 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 280 281 read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT; 282 } 283 284 #ifdef ENABLE_ATT_DELAYED_RESPONSE 285 // dynamic read 286 num_value_handles = 2; 287 value_handles[0] = 0x03; 288 value_handles[1] = 0x0c; 289 { 290 read_callback_mode = READ_CALLBACK_MODE_RETURN_PENDING; 291 292 att_request_len = att_read_multiple_request(num_value_handles, value_handles); 293 CHECK_EQUAL(1 + 2 * num_value_handles, att_request_len); 294 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 295 const uint8_t expected_response[] = {ATT_READ_MULTIPLE_RESPONSE, 0x64}; 296 CHECK_EQUAL(sizeof(expected_response), att_response_len); 297 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 298 299 read_callback_mode = READ_CALLBACK_MODE_RETURN_DEFAULT; 300 } 301 #endif 302 } 303 304 TEST(AttDb, handle_write_request){ 305 uint16_t attribute_handle = 0x03; 306 307 // not sufficient request length 308 { 309 att_request[0] = ATT_WRITE_REQUEST; 310 att_request_len = 1; 311 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 312 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU}; 313 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 314 CHECK_EQUAL(sizeof(expected_response), att_response_len); 315 } 316 317 { 318 att_request[0] = ATT_WRITE_REQUEST; 319 att_request[1] = 0x03; 320 att_request_len = 2; 321 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 322 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU}; 323 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 324 CHECK_EQUAL(sizeof(expected_response), att_response_len); 325 } 326 327 // invalid handle 328 { 329 att_request[0] = ATT_WRITE_REQUEST; 330 att_request[1] = 0; 331 att_request[2] = 0; 332 att_request_len = 3; 333 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 334 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE}; 335 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 336 CHECK_EQUAL(sizeof(expected_response), att_response_len); 337 } 338 339 // write not permited: invalid write callback 340 { 341 att_set_write_callback(NULL); 342 343 const uint8_t value[] = {0x50}; 344 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 345 CHECK_EQUAL(3 + sizeof(value), att_request_len); 346 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 347 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 348 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 349 CHECK_EQUAL(sizeof(expected_response), att_response_len); 350 351 att_set_write_callback(&att_write_callback); 352 } 353 354 // write not permited: no ATT_PROPERTY_WRITE 355 { 356 const uint8_t value[] = {0x50}; 357 attribute_handle = 0x000c; // 0x2A49 358 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 359 CHECK_EQUAL(3 + sizeof(value), att_request_len); 360 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 361 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 362 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 363 CHECK_EQUAL(sizeof(expected_response), att_response_len); 364 } 365 366 // write not permited: no ATT_PROPERTY_DYNAMIC 367 { 368 const uint8_t value[] = {0x50}; 369 attribute_handle = 0x0003; 370 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 371 CHECK_EQUAL(3 + sizeof(value), att_request_len); 372 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 373 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 374 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 375 CHECK_EQUAL(sizeof(expected_response), att_response_len); 376 } 377 378 // security validation 379 { 380 const uint8_t value[] = {0x50}; 381 attribute_handle = 0x000f; // 0x2A35 382 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 383 CHECK_EQUAL(3 + sizeof(value), att_request_len); 384 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 385 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION}; 386 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 387 CHECK_EQUAL(sizeof(expected_response), att_response_len); 388 } 389 390 // att_persistent_ccc_cache: ATT_PROPERTY_UUID16 391 // att_persistent_ccc_cache: ATT_PROPERTY_UUID128 392 393 // some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING 394 { 395 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH; 396 397 const uint8_t value[] = {0x50}; 398 attribute_handle = 0x0011; // 0x2A38 399 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 400 CHECK_EQUAL(3 + sizeof(value), att_request_len); 401 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 402 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH}; 403 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 404 CHECK_EQUAL(sizeof(expected_response), att_response_len); 405 406 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 407 } 408 409 #ifdef ENABLE_ATT_DELAYED_RESPONSE 410 // delayed response 411 { 412 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING; 413 414 const uint8_t value[] = {0x50}; 415 attribute_handle = 0x0011; // 0x2A38 416 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 417 CHECK_EQUAL(3 + sizeof(value), att_request_len); 418 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 419 CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len); 420 421 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 422 } 423 #endif 424 425 // correct write 426 { 427 const uint8_t value[] = {0x50}; 428 attribute_handle = 0x0011; 429 att_request_len = att_write_request(ATT_WRITE_REQUEST, attribute_handle, sizeof(value), value); 430 CHECK_EQUAL(3 + sizeof(value), att_request_len); 431 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 432 const uint8_t expected_response[] = {ATT_WRITE_RESPONSE}; 433 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 434 CHECK_EQUAL(sizeof(expected_response), att_response_len); 435 } 436 } 437 438 TEST(AttDb, handle_prepare_write_request){ 439 uint16_t attribute_handle = 0x0011; 440 uint16_t value_offset = 0x10; 441 442 // not sufficient request length 443 { 444 att_request[0] = ATT_PREPARE_WRITE_REQUEST; 445 att_request_len = 1; 446 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 447 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], 0x00, 0x00, ATT_ERROR_INVALID_PDU}; 448 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 449 CHECK_EQUAL(sizeof(expected_response), att_response_len); 450 } 451 452 // write not permited: invalid write callback 453 { 454 att_set_write_callback(NULL); 455 456 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 457 CHECK_EQUAL(5, att_request_len); 458 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 459 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 460 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 461 CHECK_EQUAL(sizeof(expected_response), att_response_len); 462 463 att_set_write_callback(&att_write_callback); 464 } 465 466 // invalid handle 467 { 468 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, 0, 0); 469 CHECK_EQUAL(5, att_request_len); 470 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 471 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_HANDLE}; 472 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 473 CHECK_EQUAL(sizeof(expected_response), att_response_len); 474 } 475 476 // write not permited: no ATT_PROPERTY_WRITE 477 { 478 attribute_handle = 0x000c; // 0x2A49 479 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 480 CHECK_EQUAL(5, att_request_len); 481 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 482 483 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 484 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 485 CHECK_EQUAL(sizeof(expected_response), att_response_len); 486 } 487 488 489 // write not permited: no ATT_PROPERTY_DYNAMIC 490 { 491 attribute_handle = 0x0003; 492 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 493 CHECK_EQUAL(5, att_request_len); 494 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 495 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_WRITE_NOT_PERMITTED}; 496 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 497 CHECK_EQUAL(sizeof(expected_response), att_response_len); 498 } 499 500 // security validation 501 { 502 attribute_handle = 0x000f; // 0x2A35 503 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 504 CHECK_EQUAL(5, att_request_len); 505 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 506 const uint8_t expected_response[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INSUFFICIENT_AUTHENTICATION}; 507 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 508 CHECK_EQUAL(sizeof(expected_response), att_response_len); 509 } 510 511 // some callback error other then ATT_INTERNAL_WRITE_RESPONSE_PENDING 512 { 513 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_INVALID_ATTRIBUTE_VALUE_LENGTH; 514 515 attribute_handle = 0x0011; // 0x2A38 516 517 // prepare write 518 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 519 CHECK_EQUAL(5, att_request_len); 520 521 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 522 const uint8_t expected_response_prepare_write[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00}; 523 MEMCMP_EQUAL(expected_response_prepare_write, att_response, att_response_len); 524 CHECK_EQUAL(sizeof(expected_response_prepare_write), att_response_len); 525 526 // execute write 527 att_request_len = att_prepare_write_request(ATT_EXECUTE_WRITE_REQUEST, attribute_handle, value_offset); 528 CHECK_EQUAL(5, att_request_len); 529 530 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 531 const uint8_t expected_response_write_execute[] = {ATT_ERROR_RESPONSE, att_request[0], att_request[1], att_request[2], ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH}; 532 MEMCMP_EQUAL(expected_response_write_execute, att_response, att_response_len); 533 CHECK_EQUAL(sizeof(expected_response_write_execute), att_response_len); 534 535 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 536 } 537 538 #ifdef ENABLE_ATT_DELAYED_RESPONSE 539 // delayed response 540 { 541 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_ERROR_WRITE_RESPONSE_PENDING; 542 543 attribute_handle = 0x0011; // 0x2A38 544 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 545 CHECK_EQUAL(5, att_request_len); 546 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 547 548 549 CHECK_EQUAL(ATT_INTERNAL_WRITE_RESPONSE_PENDING, att_response_len); 550 551 write_callback_mode = WRITE_CALLBACK_MODE_RETURN_DEFAULT; 552 } 553 #endif 554 555 // correct write 556 { 557 attribute_handle = 0x0011; 558 att_request_len = att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, attribute_handle, value_offset); 559 CHECK_EQUAL(5, att_request_len); 560 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 561 const uint8_t expected_response[] = {ATT_PREPARE_WRITE_RESPONSE, 0x11, 0x00, 0x10, 0x00}; 562 MEMCMP_EQUAL(expected_response, att_response, att_response_len); 563 CHECK_EQUAL(sizeof(expected_response), att_response_len); 564 } 565 } 566 567 TEST(AttDb, att_uuid_for_handle){ 568 // existing attribute handle 569 uint16_t uuid = att_uuid_for_handle(0x0011); 570 uint16_t expected_response = 0x2A38; 571 CHECK_EQUAL(expected_response, uuid); 572 573 // unknown attribute handle 574 uuid = att_uuid_for_handle(0xFF00); 575 expected_response = 0; 576 CHECK_EQUAL(expected_response, uuid); 577 578 // attribute handle for uuid128 579 uuid = att_uuid_for_handle(0x0014); 580 expected_response = 0; 581 CHECK_EQUAL(expected_response, uuid); 582 } 583 584 TEST(AttDb, handle_write_command){ 585 uint16_t attribute_handle = 0x03; 586 att_dump_attributes(); 587 588 // not sufficient request length 589 { 590 att_request[0] = ATT_WRITE_COMMAND; 591 att_request_len = 1; 592 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 593 CHECK_EQUAL(0, att_response_len); 594 } 595 596 { 597 att_request[0] = ATT_WRITE_COMMAND; 598 att_request[1] = 0x03; 599 att_request_len = 2; 600 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 601 CHECK_EQUAL(0, att_response_len); 602 } 603 604 // invalid write callback 605 { 606 att_set_write_callback(NULL); 607 608 const uint8_t value[] = {0x50}; 609 att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value); 610 CHECK_EQUAL(3 + sizeof(value), att_request_len); 611 612 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 613 CHECK_EQUAL(0, att_response_len); 614 615 att_set_write_callback(&att_write_callback); 616 } 617 618 // invalid handle 619 { 620 att_request[0] = ATT_WRITE_COMMAND; 621 att_request[1] = 0; 622 att_request[2] = 0; 623 att_request_len = 3; 624 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 625 CHECK_EQUAL(0, att_response_len); 626 } 627 628 // write not permited: no ATT_PROPERTY_DYNAMIC 629 { 630 const uint8_t value[] = {0x50}; 631 attribute_handle = 0x0003; 632 att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value); 633 CHECK_EQUAL(3 + sizeof(value), att_request_len); 634 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 635 CHECK_EQUAL(0, att_response_len); 636 } 637 638 // write not permited: no ATT_PROPERTY_WRITE_WITHOUT_RESPONSE 639 { 640 const uint8_t value[] = {0x50}; 641 attribute_handle = 0x000c; // 0x2A49 642 att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value); 643 CHECK_EQUAL(3 + sizeof(value), att_request_len); 644 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 645 CHECK_EQUAL(0, att_response_len); 646 } 647 648 // security validation 649 { 650 const uint8_t value[] = {0x50}; 651 attribute_handle = 0x0017; // 0x2AA7 652 att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value); 653 CHECK_EQUAL(3 + sizeof(value), att_request_len); 654 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 655 CHECK_EQUAL(0, att_response_len); 656 } 657 658 // correct write 659 { 660 const uint8_t value[] = {0x50}; 661 attribute_handle = 0x001A; // 0x2AAB 662 att_request_len = att_write_request(ATT_WRITE_COMMAND, attribute_handle, sizeof(value), value); 663 CHECK_EQUAL(3 + sizeof(value), att_request_len); 664 att_response_len = att_handle_request(&att_connection, (uint8_t *) att_request, att_request_len, att_response); 665 CHECK_EQUAL(0, att_response_len); 666 } 667 } 668 669 TEST(AttDb, att_read_callback_handle_blob){ 670 { 671 const uint8_t blob[] = {0x44, 0x55}; 672 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, NULL, 0); 673 CHECK_EQUAL(2, blob_size); 674 } 675 676 { 677 const uint8_t blob[] = {}; 678 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer)); 679 CHECK_EQUAL(0, blob_size); 680 } 681 682 { 683 const uint8_t blob[] = {}; 684 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer)); 685 CHECK_EQUAL(0, blob_size); 686 } 687 688 { 689 const uint8_t blob[] = {0x55}; 690 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer)); 691 CHECK_EQUAL(1, blob_size); 692 } 693 694 { 695 const uint8_t blob[] = {0x55}; 696 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer)); 697 CHECK_EQUAL(0, blob_size); 698 } 699 700 { 701 const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA}; 702 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 0, callback_buffer, sizeof(callback_buffer)); 703 CHECK_EQUAL(10, blob_size); 704 } 705 706 { 707 const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA}; 708 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 1, callback_buffer, sizeof(callback_buffer)); 709 CHECK_EQUAL(9, blob_size); 710 } 711 712 { 713 const uint8_t blob[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA}; 714 uint16_t blob_size = att_read_callback_handle_blob(blob, sizeof(blob), 10, callback_buffer, sizeof(callback_buffer)); 715 CHECK_EQUAL(0, blob_size); 716 } 717 } 718 719 TEST(AttDb, att_read_callback_handle_byte){ 720 { 721 uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, NULL, 0); 722 CHECK_EQUAL(1, blob_size); 723 } 724 725 { 726 uint16_t blob_size = att_read_callback_handle_byte(0x55, 10, callback_buffer, sizeof(callback_buffer)); 727 CHECK_EQUAL(0, blob_size); 728 } 729 730 { 731 uint16_t blob_size = att_read_callback_handle_byte(0x55, 0, callback_buffer, sizeof(callback_buffer)); 732 CHECK_EQUAL(1, blob_size); 733 } 734 } 735 736 TEST(AttDb, att_read_callback_handle_little_endian_16){ 737 { 738 uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, NULL, 0); 739 CHECK_EQUAL(2, blob_size); 740 } 741 742 { 743 uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 10, callback_buffer, sizeof(callback_buffer)); 744 CHECK_EQUAL(0, blob_size); 745 } 746 747 { 748 uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 1, callback_buffer, sizeof(callback_buffer)); 749 CHECK_EQUAL(1, blob_size); 750 } 751 752 { 753 uint16_t blob_size = att_read_callback_handle_little_endian_16(0x1122, 0, callback_buffer, sizeof(callback_buffer)); 754 CHECK_EQUAL(2, blob_size); 755 } 756 } 757 758 TEST(AttDb, att_read_callback_handle_little_endian_32){ 759 { 760 uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, NULL, 0); 761 CHECK_EQUAL(4, blob_size); 762 } 763 764 { 765 uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 10, callback_buffer, sizeof(callback_buffer)); 766 CHECK_EQUAL(0, blob_size); 767 } 768 769 { 770 uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 3, callback_buffer, sizeof(callback_buffer)); 771 CHECK_EQUAL(1, blob_size); 772 } 773 774 { 775 uint16_t blob_size = att_read_callback_handle_little_endian_32(0x11223344, 0, callback_buffer, sizeof(callback_buffer)); 776 CHECK_EQUAL(4, blob_size); 777 } 778 } 779 780 781 int main (int argc, const char * argv[]){ 782 return CommandLineTestRunner::RunAllTests(argc, argv); 783 } 784