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