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