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