1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 20 /****************************************************************************** 21 * 22 * This file contains source code for some utility functions to help parse 23 * and build NFC Data Exchange Format (NDEF) messages for Connection 24 * Handover 25 * 26 ******************************************************************************/ 27 28 #include <string.h> 29 #include "ndef_utils.h" 30 31 /******************************************************************************* 32 ** 33 ** Static Local Functions 34 */ 35 static UINT8 *ndef_get_bt_oob_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 36 char *p_id_str); 37 38 /******************************************************************************* 39 ** 40 ** Static data 41 */ 42 43 /* Handover Request Record Type */ 44 static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */ 45 46 /* Handover Select Record Type */ 47 static UINT8 hs_rec_type[HS_REC_TYPE_LEN] = { 0x48, 0x73 }; /* "Hs" */ 48 49 /* Handover Carrier recrod Type */ 50 static UINT8 hc_rec_type[HC_REC_TYPE_LEN] = { 0x48, 0x63 }; /* "Hc" */ 51 52 /* Collision Resolution Record Type */ 53 static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */ 54 55 /* Alternative Carrier Record Type */ 56 static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */ 57 58 /* Error Record Type */ 59 static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */ 60 61 /* Bluetooth OOB Data Type */ 62 static UINT8 *p_bt_oob_rec_type = (UINT8 *)"application/vnd.bluetooth.ep.oob"; 63 64 /* Wifi WSC Data Type */ 65 static UINT8 *p_wifi_wsc_rec_type = (UINT8 *)"application/vnd.wfa.wsc"; 66 67 /******************************************************************************* 68 ** 69 ** Function NDEF_MsgCreateWktHr 70 ** 71 ** Description This function creates Handover Request Record with version. 72 ** 73 ** Returns NDEF_OK if all OK 74 ** 75 *******************************************************************************/ 76 tNDEF_STATUS NDEF_MsgCreateWktHr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 77 UINT8 version ) 78 { 79 tNDEF_STATUS status; 80 81 NDEF_MsgInit (p_msg, max_size, p_cur_size); 82 83 /* Add record with version */ 84 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 85 NDEF_TNF_WKT, hr_rec_type, HR_REC_TYPE_LEN, 86 NULL, 0, &version, 1); 87 88 return (status); 89 } 90 91 /******************************************************************************* 92 ** 93 ** Function NDEF_MsgCreateWktHs 94 ** 95 ** Description This function creates Handover Select Record with version. 96 ** 97 ** Returns NDEF_OK if all OK 98 ** 99 *******************************************************************************/ 100 tNDEF_STATUS NDEF_MsgCreateWktHs (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 101 UINT8 version ) 102 { 103 tNDEF_STATUS status; 104 105 NDEF_MsgInit (p_msg, max_size, p_cur_size); 106 107 /* Add record with version */ 108 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 109 NDEF_TNF_WKT, hs_rec_type, HS_REC_TYPE_LEN, 110 NULL, 0, &version, 1); 111 112 return (status); 113 } 114 115 /******************************************************************************* 116 ** 117 ** Function NDEF_MsgAddWktHc 118 ** 119 ** Description This function adds Handover Carrier Record. 120 ** 121 ** Returns NDEF_OK if all OK 122 ** 123 *******************************************************************************/ 124 tNDEF_STATUS NDEF_MsgAddWktHc (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 125 char *p_id_str, UINT8 ctf, 126 UINT8 carrier_type_len, UINT8 *p_carrier_type, 127 UINT8 carrier_data_len, UINT8 *p_carrier_data) 128 { 129 tNDEF_STATUS status; 130 UINT8 payload[256], *p, id_len; 131 UINT32 payload_len; 132 133 if (carrier_type_len + carrier_data_len + 2 > 256) 134 { 135 return (NDEF_MSG_INSUFFICIENT_MEM); 136 } 137 138 p = payload; 139 140 UINT8_TO_STREAM (p, (ctf & 0x07)); 141 UINT8_TO_STREAM (p, carrier_type_len); 142 ARRAY_TO_STREAM (p, p_carrier_type, carrier_type_len); 143 ARRAY_TO_STREAM (p, p_carrier_data, carrier_data_len); 144 145 payload_len = (UINT32)carrier_type_len + carrier_data_len + 2; 146 147 id_len = (UINT8)strlen (p_id_str); 148 149 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 150 NDEF_TNF_WKT, hc_rec_type, HC_REC_TYPE_LEN, 151 (UINT8*)p_id_str, id_len, payload, payload_len); 152 return (status); 153 } 154 155 /******************************************************************************* 156 ** 157 ** Function NDEF_MsgAddWktAc 158 ** 159 ** Description This function adds Alternative Carrier Record. 160 ** 161 ** Returns NDEF_OK if all OK 162 ** 163 *******************************************************************************/ 164 tNDEF_STATUS NDEF_MsgAddWktAc (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 165 UINT8 cps, char *p_carrier_data_ref_str, 166 UINT8 aux_data_ref_count, char *p_aux_data_ref_str[]) 167 { 168 tNDEF_STATUS status; 169 UINT32 payload_len; 170 UINT8 ref_str_len, xx; 171 UINT8 *p_rec, *p; 172 173 /* get payload length first */ 174 175 /* CPS, length of carrier data ref, carrier data ref, Aux data reference count */ 176 payload_len = 3 + (UINT8)strlen (p_carrier_data_ref_str); 177 for (xx = 0; xx < aux_data_ref_count; xx++) 178 { 179 /* Aux Data Reference length (1 byte) */ 180 payload_len += 1 + (UINT8)strlen (p_aux_data_ref_str[xx]); 181 } 182 183 /* reserve memory for payload */ 184 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 185 NDEF_TNF_WKT, ac_rec_type, AC_REC_TYPE_LEN, 186 NULL, 0, NULL, payload_len); 187 188 if (status == NDEF_OK) 189 { 190 /* get AC record added at the end */ 191 p_rec = NDEF_MsgGetLastRecInMsg (p_msg); 192 193 /* get start pointer of reserved payload */ 194 p = NDEF_RecGetPayload (p_rec, &payload_len); 195 196 /* Add Carrier Power State */ 197 UINT8_TO_BE_STREAM (p, cps); 198 199 /* Carrier Data Reference length */ 200 ref_str_len = (UINT8)strlen (p_carrier_data_ref_str); 201 202 UINT8_TO_BE_STREAM (p, ref_str_len); 203 204 /* Carrier Data Reference */ 205 ARRAY_TO_BE_STREAM (p, p_carrier_data_ref_str, ref_str_len); 206 207 /* Aux Data Reference Count */ 208 UINT8_TO_BE_STREAM (p, aux_data_ref_count); 209 210 for (xx = 0; xx < aux_data_ref_count; xx++) 211 { 212 /* Aux Data Reference length (1 byte) */ 213 ref_str_len = (UINT8)strlen (p_aux_data_ref_str[xx]); 214 215 UINT8_TO_BE_STREAM (p, ref_str_len); 216 217 /* Aux Data Reference */ 218 ARRAY_TO_BE_STREAM (p, p_aux_data_ref_str[xx], ref_str_len); 219 } 220 } 221 222 return (status); 223 } 224 225 /******************************************************************************* 226 ** 227 ** Function NDEF_MsgAddWktCr 228 ** 229 ** Description This function adds Collision Resolution Record. 230 ** 231 ** Returns NDEF_OK if all OK 232 ** 233 *******************************************************************************/ 234 tNDEF_STATUS NDEF_MsgAddWktCr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 235 UINT16 random_number ) 236 { 237 tNDEF_STATUS status; 238 UINT8 data[2], *p; 239 240 p = data; 241 UINT16_TO_BE_STREAM (p, random_number); 242 243 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 244 NDEF_TNF_WKT, cr_rec_type, CR_REC_TYPE_LEN, 245 NULL, 0, data, 2); 246 return (status); 247 } 248 249 /******************************************************************************* 250 ** 251 ** Function NDEF_MsgAddWktErr 252 ** 253 ** Description This function adds Error Record. 254 ** 255 ** Returns NDEF_OK if all OK 256 ** 257 *******************************************************************************/ 258 tNDEF_STATUS NDEF_MsgAddWktErr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 259 UINT8 error_reason, UINT32 error_data ) 260 { 261 tNDEF_STATUS status; 262 UINT8 payload[5], *p; 263 UINT32 payload_len; 264 265 p = payload; 266 267 UINT8_TO_BE_STREAM (p, error_reason); 268 269 if (error_reason == 0x02) 270 { 271 UINT32_TO_BE_STREAM (p, error_data); 272 payload_len = 5; 273 } 274 else 275 { 276 UINT8_TO_BE_STREAM (p, error_data); 277 payload_len = 2; 278 } 279 280 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 281 NDEF_TNF_WKT, err_rec_type, ERR_REC_TYPE_LEN, 282 NULL, 0, payload, payload_len); 283 return (status); 284 } 285 286 /******************************************************************************* 287 ** 288 ** Function NDEF_MsgAddMediaBtOob 289 ** 290 ** Description This function adds BT OOB Record. 291 ** 292 ** Returns NDEF_OK if all OK 293 ** 294 *******************************************************************************/ 295 tNDEF_STATUS NDEF_MsgAddMediaBtOob (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 296 char *p_id_str, BD_ADDR bd_addr) 297 { 298 tNDEF_STATUS status; 299 UINT8 payload[BD_ADDR_LEN + 2]; 300 UINT8 *p; 301 UINT8 payload_len, id_len; 302 303 p = payload; 304 305 /* length including itself */ 306 UINT16_TO_STREAM (p, BD_ADDR_LEN + 2); 307 308 /* BD Addr */ 309 BDADDR_TO_STREAM (p, bd_addr); 310 311 payload_len = BD_ADDR_LEN + 2; 312 id_len = (UINT8)strlen (p_id_str); 313 314 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 315 NDEF_TNF_MEDIA, p_bt_oob_rec_type, BT_OOB_REC_TYPE_LEN, 316 (UINT8*)p_id_str, id_len, payload, payload_len); 317 return (status); 318 } 319 320 /******************************************************************************* 321 ** 322 ** Function NDEF_MsgAppendMediaBtOobCod 323 ** 324 ** Description This function appends COD EIR data at the end of BT OOB Record. 325 ** 326 ** Returns NDEF_OK if all OK 327 ** 328 *******************************************************************************/ 329 tNDEF_STATUS NDEF_MsgAppendMediaBtOobCod (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 330 char *p_id_str, DEV_CLASS cod) 331 { 332 tNDEF_STATUS status; 333 UINT8 *p_rec; 334 UINT8 eir_data[BT_OOB_COD_SIZE + 2]; 335 UINT8 *p; 336 UINT8 eir_data_len; 337 UINT32 oob_data_len; 338 339 /* find record by Payload ID */ 340 p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); 341 342 if (!p_rec) 343 return (NDEF_REC_NOT_FOUND); 344 345 /* create EIR data format for COD */ 346 p = eir_data; 347 UINT8_TO_STREAM (p, BT_OOB_COD_SIZE + 1); 348 UINT8_TO_STREAM (p, BT_EIR_OOB_COD_TYPE); 349 DEVCLASS_TO_STREAM (p, cod); 350 eir_data_len = BT_OOB_COD_SIZE + 2; 351 352 /* append EIR data at the end of record */ 353 status = NDEF_MsgAppendPayload(p_msg, max_size, p_cur_size, 354 p_rec, eir_data, eir_data_len); 355 356 /* update BT OOB data length, if success */ 357 if (status == NDEF_OK) 358 { 359 /* payload length is the same as BT OOB data length */ 360 p = NDEF_RecGetPayload (p_rec, &oob_data_len); 361 UINT16_TO_STREAM (p, oob_data_len); 362 } 363 364 return (status); 365 } 366 367 /******************************************************************************* 368 ** 369 ** Function NDEF_MsgAppendMediaBtOobName 370 ** 371 ** Description This function appends Bluetooth Local Name EIR data 372 ** at the end of BT OOB Record. 373 ** 374 ** Returns NDEF_OK if all OK 375 ** 376 *******************************************************************************/ 377 tNDEF_STATUS NDEF_MsgAppendMediaBtOobName (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 378 char *p_id_str, BOOLEAN is_complete, 379 UINT8 name_len, UINT8 *p_name) 380 { 381 tNDEF_STATUS status; 382 UINT8 *p_rec; 383 UINT8 eir_data[256]; 384 UINT8 *p; 385 UINT8 eir_data_len; 386 UINT32 oob_data_len; 387 388 /* find record by Payload ID */ 389 p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); 390 391 if (!p_rec) 392 return (NDEF_REC_NOT_FOUND); 393 394 /* create EIR data format for COD */ 395 p = eir_data; 396 UINT8_TO_STREAM (p, name_len + 1); 397 398 if (is_complete) 399 { 400 UINT8_TO_STREAM (p, BT_EIR_COMPLETE_LOCAL_NAME_TYPE); 401 } 402 else 403 { 404 UINT8_TO_STREAM (p, BT_EIR_SHORTENED_LOCAL_NAME_TYPE); 405 } 406 407 ARRAY_TO_STREAM (p, p_name, name_len); 408 eir_data_len = name_len + 2; 409 410 /* append EIR data at the end of record */ 411 status = NDEF_MsgAppendPayload(p_msg, max_size, p_cur_size, 412 p_rec, eir_data, eir_data_len); 413 414 /* update BT OOB data length, if success */ 415 if (status == NDEF_OK) 416 { 417 /* payload length is the same as BT OOB data length */ 418 p = NDEF_RecGetPayload (p_rec, &oob_data_len); 419 UINT16_TO_STREAM (p, oob_data_len); 420 } 421 422 return (status); 423 } 424 425 /******************************************************************************* 426 ** 427 ** Function NDEF_MsgAppendMediaBtOobHashCRandR 428 ** 429 ** Description This function appends Hash C and Rand R at the end of BT OOB Record. 430 ** 431 ** Returns NDEF_OK if all OK 432 ** 433 *******************************************************************************/ 434 tNDEF_STATUS NDEF_MsgAppendMediaBtOobHashCRandR (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 435 char *p_id_str, UINT8 *p_hash_c, UINT8 *p_rand_r) 436 { 437 tNDEF_STATUS status; 438 UINT8 *p_rec; 439 UINT8 eir_data[BT_OOB_HASH_C_SIZE + BT_OOB_RAND_R_SIZE + 4]; 440 UINT8 *p; 441 UINT8 eir_data_len; 442 UINT32 oob_data_len; 443 444 /* find record by Payload ID */ 445 p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); 446 447 if (!p_rec) 448 return (NDEF_REC_NOT_FOUND); 449 450 /* create EIR data format */ 451 p = eir_data; 452 453 UINT8_TO_STREAM (p, BT_OOB_HASH_C_SIZE + 1); 454 UINT8_TO_STREAM (p, BT_EIR_OOB_SSP_HASH_C_TYPE); 455 ARRAY16_TO_STREAM (p, p_hash_c); 456 457 UINT8_TO_STREAM (p, BT_OOB_RAND_R_SIZE + 1); 458 UINT8_TO_STREAM (p, BT_EIR_OOB_SSP_RAND_R_TYPE); 459 ARRAY16_TO_STREAM (p, p_rand_r); 460 461 eir_data_len = BT_OOB_HASH_C_SIZE + BT_OOB_RAND_R_SIZE + 4; 462 463 /* append EIR data at the end of record */ 464 status = NDEF_MsgAppendPayload(p_msg, max_size, p_cur_size, 465 p_rec, eir_data, eir_data_len); 466 467 /* update BT OOB data length, if success */ 468 if (status == NDEF_OK) 469 { 470 /* payload length is the same as BT OOB data length */ 471 p = NDEF_RecGetPayload (p_rec, &oob_data_len); 472 UINT16_TO_STREAM (p, oob_data_len); 473 } 474 475 return (status); 476 } 477 478 /******************************************************************************* 479 ** 480 ** Function NDEF_MsgAppendMediaBtOobEirData 481 ** 482 ** Description This function appends EIR Data at the end of BT OOB Record. 483 ** 484 ** Returns NDEF_OK if all OK 485 ** 486 *******************************************************************************/ 487 tNDEF_STATUS NDEF_MsgAppendMediaBtOobEirData (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 488 char *p_id_str, 489 UINT8 eir_type, UINT8 data_len, UINT8 *p_data) 490 { 491 tNDEF_STATUS status; 492 UINT8 *p_rec; 493 UINT8 eir_data[256]; 494 UINT8 *p; 495 UINT8 eir_data_len; 496 UINT32 oob_data_len; 497 498 /* find record by Payload ID */ 499 p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); 500 501 if (!p_rec) 502 return (NDEF_REC_NOT_FOUND); 503 504 /* create EIR data format */ 505 p = eir_data; 506 UINT8_TO_STREAM (p, data_len + 1); 507 UINT8_TO_STREAM (p, eir_type); 508 ARRAY_TO_STREAM (p, p_data, data_len); 509 eir_data_len = data_len + 2; 510 511 /* append EIR data at the end of record */ 512 status = NDEF_MsgAppendPayload(p_msg, max_size, p_cur_size, 513 p_rec, eir_data, eir_data_len); 514 515 /* update BT OOB data length, if success */ 516 if (status == NDEF_OK) 517 { 518 /* payload length is the same as BT OOB data length */ 519 p = NDEF_RecGetPayload (p_rec, &oob_data_len); 520 UINT16_TO_STREAM (p, oob_data_len); 521 } 522 523 return (status); 524 } 525 526 /******************************************************************************* 527 ** 528 ** Function NDEF_MsgAddMediaWifiWsc 529 ** 530 ** Description This function adds Wifi Wsc Record header. 531 ** 532 ** Returns NDEF_OK if all OK 533 ** 534 *******************************************************************************/ 535 tNDEF_STATUS NDEF_MsgAddMediaWifiWsc (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 536 char *p_id_str, UINT8 *p_payload, UINT32 payload_len) 537 { 538 tNDEF_STATUS status; 539 UINT8 id_len = 0; 540 541 if (p_id_str) 542 id_len = (UINT8)strlen (p_id_str); 543 544 status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, 545 NDEF_TNF_MEDIA, p_wifi_wsc_rec_type, WIFI_WSC_REC_TYPE_LEN, 546 (UINT8*)p_id_str, id_len, p_payload, payload_len); 547 return (status); 548 } 549 550 /******************************************************************************* 551 ** 552 ** Static Local Functions 553 ** 554 *******************************************************************************/ 555 /******************************************************************************* 556 ** 557 ** Function ndef_get_bt_oob_record 558 ** 559 ** Description This function returns BT OOB record which has matched payload ID 560 ** 561 ** Returns pointer of record if found, otherwise NULL 562 ** 563 *******************************************************************************/ 564 static UINT8 *ndef_get_bt_oob_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, 565 char *p_id_str) 566 { 567 UINT8 *p_rec, *p_type; 568 UINT8 id_len, tnf, type_len; 569 570 /* find record by Payload ID */ 571 id_len = (UINT8)strlen (p_id_str); 572 p_rec = NDEF_MsgGetFirstRecById (p_msg, (UINT8*)p_id_str, id_len); 573 574 if (!p_rec) 575 return (NULL); 576 577 p_type = NDEF_RecGetType (p_rec, &tnf, &type_len); 578 579 /* check type if this is BT OOB record */ 580 if ((!p_rec) 581 ||(tnf != NDEF_TNF_MEDIA) 582 ||(type_len != BT_OOB_REC_TYPE_LEN) 583 ||(memcmp (p_type, p_bt_oob_rec_type, BT_OOB_REC_TYPE_LEN))) 584 { 585 return (NULL); 586 } 587 588 return (p_rec); 589 } 590 591