Home | History | Annotate | Download | only in ndef
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-2013 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