• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
34 static 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 */
43 static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */
44 
45 /* Handover Select Record Type */
46 static UINT8 hs_rec_type[HS_REC_TYPE_LEN] = { 0x48, 0x73 }; /* "Hs" */
47 
48 /* Handover Carrier recrod Type */
49 static UINT8 hc_rec_type[HC_REC_TYPE_LEN] = { 0x48, 0x63 }; /* "Hc" */
50 
51 /* Collision Resolution Record Type */
52 static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */
53 
54 /* Alternative Carrier Record Type */
55 static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */
56 
57 /* Error Record Type */
58 static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */
59 
60 /* Bluetooth OOB Data Type */
61 static 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 *******************************************************************************/
NDEF_MsgCreateWktHr(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT8 version)72 tNDEF_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 *******************************************************************************/
NDEF_MsgCreateWktHs(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT8 version)96 tNDEF_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 *******************************************************************************/
NDEF_MsgAddWktHc(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,UINT8 ctf,UINT8 carrier_type_len,UINT8 * p_carrier_type,UINT8 carrier_data_len,UINT8 * p_carrier_data)120 tNDEF_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 *******************************************************************************/
NDEF_MsgAddWktAc(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT8 cps,char * p_carrier_data_ref_str,UINT8 aux_data_ref_count,char * p_aux_data_ref_str[])160 tNDEF_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 *******************************************************************************/
NDEF_MsgAddWktCr(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT16 random_number)230 tNDEF_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 *******************************************************************************/
NDEF_MsgAddWktErr(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,UINT8 error_reason,UINT32 error_data)254 tNDEF_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 *******************************************************************************/
NDEF_MsgAddMediaBtOob(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,BD_ADDR bd_addr)291 tNDEF_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 *******************************************************************************/
NDEF_MsgAppendMediaBtOobCod(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,DEV_CLASS cod)325 tNDEF_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 *******************************************************************************/
NDEF_MsgAppendMediaBtOobName(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,BOOLEAN is_complete,UINT8 name_len,UINT8 * p_name)373 tNDEF_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 *******************************************************************************/
NDEF_MsgAppendMediaBtOobHashCRandR(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,UINT8 * p_hash_c,UINT8 * p_rand_r)430 tNDEF_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 *******************************************************************************/
NDEF_MsgAppendMediaBtOobEirData(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str,UINT8 eir_type,UINT8 data_len,UINT8 * p_data)483 tNDEF_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 *******************************************************************************/
ndef_get_bt_oob_record(UINT8 * p_msg,UINT32 max_size,UINT32 * p_cur_size,char * p_id_str)536 static 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