ndef_cho_utils.c revision e9629bad30a9f478b336ab46b8e6e02f7f87af46
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*/
35static 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 */
44static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */
45
46/* Handover Select Record Type */
47static UINT8 hs_rec_type[HS_REC_TYPE_LEN] = { 0x48, 0x73 }; /* "Hs" */
48
49/* Handover Carrier recrod Type */
50static UINT8 hc_rec_type[HC_REC_TYPE_LEN] = { 0x48, 0x63 }; /* "Hc" */
51
52/* Collision Resolution Record Type */
53static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */
54
55/* Alternative Carrier Record Type */
56static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */
57
58/* Error Record Type */
59static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */
60
61/* Bluetooth OOB Data Type */
62static UINT8 *p_bt_oob_rec_type = (UINT8 *)"application/vnd.bluetooth.ep.oob";
63
64/* Wifi WSC Data Type */
65static 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*******************************************************************************/
76tNDEF_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*******************************************************************************/
100tNDEF_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*******************************************************************************/
124tNDEF_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*******************************************************************************/
164tNDEF_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*******************************************************************************/
234tNDEF_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*******************************************************************************/
258tNDEF_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*******************************************************************************/
295tNDEF_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*******************************************************************************/
329tNDEF_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*******************************************************************************/
377tNDEF_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*******************************************************************************/
434tNDEF_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*******************************************************************************/
487tNDEF_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*******************************************************************************/
535tNDEF_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*******************************************************************************/
564static 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