| /****************************************************************************** |
| * |
| * Copyright (C) 2010-2012 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * This file contains source code for some utility functions to help parse |
| * and build NFC Data Exchange Format (NDEF) messages for Connection |
| * Handover |
| * |
| ******************************************************************************/ |
| |
| #include <string.h> |
| #include "ndef_utils.h" |
| |
| /******************************************************************************* |
| ** |
| ** Static Local Functions |
| */ |
| static UINT8 *ndef_get_bt_oob_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| char *p_id_str); |
| |
| /******************************************************************************* |
| ** |
| ** Static data |
| */ |
| |
| /* Handover Request Record Type */ |
| static UINT8 hr_rec_type[HR_REC_TYPE_LEN] = { 0x48, 0x72 }; /* "Hr" */ |
| |
| /* Handover Select Record Type */ |
| static UINT8 hs_rec_type[HS_REC_TYPE_LEN] = { 0x48, 0x73 }; /* "Hs" */ |
| |
| /* Handover Carrier recrod Type */ |
| static UINT8 hc_rec_type[HC_REC_TYPE_LEN] = { 0x48, 0x63 }; /* "Hc" */ |
| |
| /* Collision Resolution Record Type */ |
| static UINT8 cr_rec_type[CR_REC_TYPE_LEN] = { 0x63, 0x72 }; /* "cr" */ |
| |
| /* Alternative Carrier Record Type */ |
| static UINT8 ac_rec_type[AC_REC_TYPE_LEN] = { 0x61, 0x63 }; /* "ac" */ |
| |
| /* Error Record Type */ |
| static UINT8 err_rec_type[ERR_REC_TYPE_LEN] = { 0x65, 0x72, 0x72 }; /* "err" */ |
| |
| /* Bluetooth OOB Data Type */ |
| static UINT8 *p_bt_oob_rec_type = (UINT8 *) "application/vnd.bluetooth.ep.oob"; |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgCreateWktHr |
| ** |
| ** Description This function creates Handover Request Record with version. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgCreateWktHr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| UINT8 version ) |
| { |
| tNDEF_STATUS status; |
| |
| NDEF_MsgInit (p_msg, max_size, p_cur_size); |
| |
| /* Add record with version */ |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, hr_rec_type, HR_REC_TYPE_LEN, |
| NULL, 0, &version, 1); |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgCreateWktHs |
| ** |
| ** Description This function creates Handover Select Record with version. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgCreateWktHs (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| UINT8 version ) |
| { |
| tNDEF_STATUS status; |
| |
| NDEF_MsgInit (p_msg, max_size, p_cur_size); |
| |
| /* Add record with version */ |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, hs_rec_type, HS_REC_TYPE_LEN, |
| NULL, 0, &version, 1); |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAddWktHc |
| ** |
| ** Description This function adds Handover Carrier Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS 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) |
| { |
| tNDEF_STATUS status; |
| UINT8 payload[256], *p, id_len; |
| UINT32 payload_len; |
| |
| if (carrier_type_len + carrier_data_len + 2 > 256) |
| { |
| return (NDEF_MSG_INSUFFICIENT_MEM); |
| } |
| |
| p = payload; |
| |
| UINT8_TO_STREAM (p, (ctf & 0x07)); |
| UINT8_TO_STREAM (p, carrier_type_len); |
| ARRAY_TO_STREAM (p, p_carrier_type, carrier_type_len); |
| ARRAY_TO_STREAM (p, p_carrier_data, carrier_data_len); |
| |
| payload_len = (UINT32) carrier_type_len + carrier_data_len + 2; |
| |
| id_len = (UINT8) strlen (p_id_str); |
| |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, hc_rec_type, HC_REC_TYPE_LEN, |
| (UINT8*) p_id_str, id_len, payload, payload_len); |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAddWktAc |
| ** |
| ** Description This function adds Alternative Carrier Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS 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[]) |
| { |
| tNDEF_STATUS status; |
| UINT32 payload_len; |
| UINT8 ref_str_len, xx; |
| UINT8 *p_rec, *p; |
| |
| /* get payload length first */ |
| |
| /* CPS, length of carrier data ref, carrier data ref, Aux data reference count */ |
| payload_len = 3 + (UINT8) strlen (p_carrier_data_ref_str); |
| for (xx = 0; xx < aux_data_ref_count; xx++) |
| { |
| /* Aux Data Reference length (1 byte) */ |
| payload_len += 1 + (UINT8) strlen (p_aux_data_ref_str[xx]); |
| } |
| |
| /* reserve memory for payload */ |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, ac_rec_type, AC_REC_TYPE_LEN, |
| NULL, 0, NULL, payload_len); |
| |
| if (status == NDEF_OK) |
| { |
| /* get AC record added at the end */ |
| p_rec = NDEF_MsgGetLastRecInMsg (p_msg); |
| |
| /* get start pointer of reserved payload */ |
| p = NDEF_RecGetPayload (p_rec, &payload_len); |
| |
| /* Add Carrier Power State */ |
| UINT8_TO_BE_STREAM (p, cps); |
| |
| /* Carrier Data Reference length */ |
| ref_str_len = (UINT8) strlen (p_carrier_data_ref_str); |
| |
| UINT8_TO_BE_STREAM (p, ref_str_len); |
| |
| /* Carrier Data Reference */ |
| ARRAY_TO_BE_STREAM (p, p_carrier_data_ref_str, ref_str_len); |
| |
| /* Aux Data Reference Count */ |
| UINT8_TO_BE_STREAM (p, aux_data_ref_count); |
| |
| for (xx = 0; xx < aux_data_ref_count; xx++) |
| { |
| /* Aux Data Reference length (1 byte) */ |
| ref_str_len = (UINT8) strlen (p_aux_data_ref_str[xx]); |
| |
| UINT8_TO_BE_STREAM (p, ref_str_len); |
| |
| /* Aux Data Reference */ |
| ARRAY_TO_BE_STREAM (p, p_aux_data_ref_str[xx], ref_str_len); |
| } |
| } |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAddWktCr |
| ** |
| ** Description This function adds Collision Resolution Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgAddWktCr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| UINT16 random_number ) |
| { |
| tNDEF_STATUS status; |
| UINT8 data[2], *p; |
| |
| p = data; |
| UINT16_TO_BE_STREAM (p, random_number); |
| |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, cr_rec_type, CR_REC_TYPE_LEN, |
| NULL, 0, data, 2); |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAddWktErr |
| ** |
| ** Description This function adds Error Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgAddWktErr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| UINT8 error_reason, UINT32 error_data ) |
| { |
| tNDEF_STATUS status; |
| UINT8 payload[5], *p; |
| UINT32 payload_len; |
| |
| p = payload; |
| |
| UINT8_TO_BE_STREAM (p, error_reason); |
| |
| if (error_reason == 0x02) |
| { |
| UINT32_TO_BE_STREAM (p, error_data); |
| payload_len = 5; |
| } |
| else |
| { |
| UINT8_TO_BE_STREAM (p, error_data); |
| payload_len = 2; |
| } |
| |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_WKT, err_rec_type, ERR_REC_TYPE_LEN, |
| NULL, 0, payload, payload_len); |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAddMediaBtOob |
| ** |
| ** Description This function adds BT OOB Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgAddMediaBtOob (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| char *p_id_str, BD_ADDR bd_addr) |
| { |
| tNDEF_STATUS status; |
| UINT8 payload[BD_ADDR_LEN + 2]; |
| UINT8 *p; |
| UINT8 payload_len, id_len; |
| |
| p = payload; |
| |
| /* length including itself */ |
| UINT16_TO_STREAM (p, BD_ADDR_LEN + 2); |
| |
| /* BD Addr */ |
| BDADDR_TO_STREAM (p, bd_addr); |
| |
| payload_len = BD_ADDR_LEN + 2; |
| id_len = (UINT8) strlen (p_id_str); |
| |
| status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, |
| NDEF_TNF_MEDIA, p_bt_oob_rec_type, BT_OOB_REC_TYPE_LEN, |
| (UINT8*) p_id_str, id_len, payload, payload_len); |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAppendMediaBtOobCod |
| ** |
| ** Description This function appends COD EIR data at the end of BT OOB Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgAppendMediaBtOobCod (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| char *p_id_str, DEV_CLASS cod) |
| { |
| tNDEF_STATUS status; |
| UINT8 *p_rec; |
| UINT8 eir_data[BT_OOB_COD_SIZE + 2]; |
| UINT8 *p; |
| UINT8 eir_data_len; |
| UINT32 oob_data_len; |
| |
| /* find record by Payload ID */ |
| p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); |
| |
| if (!p_rec) |
| return (NDEF_REC_NOT_FOUND); |
| |
| /* create EIR data format for COD */ |
| p = eir_data; |
| UINT8_TO_STREAM (p, BT_OOB_COD_SIZE + 1); |
| UINT8_TO_STREAM (p, BT_EIR_OOB_COD_TYPE); |
| DEVCLASS_TO_STREAM (p, cod); |
| eir_data_len = BT_OOB_COD_SIZE + 2; |
| |
| /* append EIR data at the end of record */ |
| status = NDEF_MsgAppendPayload (p_msg, max_size, p_cur_size, |
| p_rec, eir_data, eir_data_len); |
| |
| /* update BT OOB data length, if success */ |
| if (status == NDEF_OK) |
| { |
| /* payload length is the same as BT OOB data length */ |
| p = NDEF_RecGetPayload (p_rec, &oob_data_len); |
| UINT16_TO_STREAM (p, oob_data_len); |
| } |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAppendMediaBtOobName |
| ** |
| ** Description This function appends Bluetooth Local Name EIR data |
| ** at the end of BT OOB Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS 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) |
| { |
| tNDEF_STATUS status; |
| UINT8 *p_rec; |
| UINT8 eir_data[256]; |
| UINT8 *p; |
| UINT8 eir_data_len; |
| UINT32 oob_data_len; |
| |
| /* find record by Payload ID */ |
| p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); |
| |
| if (!p_rec) |
| return (NDEF_REC_NOT_FOUND); |
| |
| /* create EIR data format for COD */ |
| p = eir_data; |
| UINT8_TO_STREAM (p, name_len + 1); |
| |
| if (is_complete) |
| { |
| UINT8_TO_STREAM (p, BT_EIR_COMPLETE_LOCAL_NAME_TYPE); |
| } |
| else |
| { |
| UINT8_TO_STREAM (p, BT_EIR_SHORTENED_LOCAL_NAME_TYPE); |
| } |
| |
| ARRAY_TO_STREAM (p, p_name, name_len); |
| eir_data_len = name_len + 2; |
| |
| /* append EIR data at the end of record */ |
| status = NDEF_MsgAppendPayload (p_msg, max_size, p_cur_size, |
| p_rec, eir_data, eir_data_len); |
| |
| /* update BT OOB data length, if success */ |
| if (status == NDEF_OK) |
| { |
| /* payload length is the same as BT OOB data length */ |
| p = NDEF_RecGetPayload (p_rec, &oob_data_len); |
| UINT16_TO_STREAM (p, oob_data_len); |
| } |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAppendMediaBtOobHashCRandR |
| ** |
| ** Description This function appends Hash C and Rand R at the end of BT OOB Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS NDEF_MsgAppendMediaBtOobHashCRandR (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| char *p_id_str, UINT8 *p_hash_c, UINT8 *p_rand_r) |
| { |
| tNDEF_STATUS status; |
| UINT8 *p_rec; |
| UINT8 eir_data[BT_OOB_HASH_C_SIZE + BT_OOB_RAND_R_SIZE + 4]; |
| UINT8 *p; |
| UINT8 eir_data_len; |
| UINT32 oob_data_len; |
| |
| /* find record by Payload ID */ |
| p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); |
| |
| if (!p_rec) |
| return (NDEF_REC_NOT_FOUND); |
| |
| /* create EIR data format */ |
| p = eir_data; |
| |
| UINT8_TO_STREAM (p, BT_OOB_HASH_C_SIZE + 1); |
| UINT8_TO_STREAM (p, BT_EIR_OOB_SSP_HASH_C_TYPE); |
| ARRAY16_TO_STREAM (p, p_hash_c); |
| |
| UINT8_TO_STREAM (p, BT_OOB_RAND_R_SIZE + 1); |
| UINT8_TO_STREAM (p, BT_EIR_OOB_SSP_RAND_R_TYPE); |
| ARRAY16_TO_STREAM (p, p_rand_r); |
| |
| eir_data_len = BT_OOB_HASH_C_SIZE + BT_OOB_RAND_R_SIZE + 4; |
| |
| /* append EIR data at the end of record */ |
| status = NDEF_MsgAppendPayload (p_msg, max_size, p_cur_size, |
| p_rec, eir_data, eir_data_len); |
| |
| /* update BT OOB data length, if success */ |
| if (status == NDEF_OK) |
| { |
| /* payload length is the same as BT OOB data length */ |
| p = NDEF_RecGetPayload (p_rec, &oob_data_len); |
| UINT16_TO_STREAM (p, oob_data_len); |
| } |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function NDEF_MsgAppendMediaBtOobEirData |
| ** |
| ** Description This function appends EIR Data at the end of BT OOB Record. |
| ** |
| ** Returns NDEF_OK if all OK |
| ** |
| *******************************************************************************/ |
| tNDEF_STATUS 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) |
| { |
| tNDEF_STATUS status; |
| UINT8 *p_rec; |
| UINT8 eir_data[256]; |
| UINT8 *p; |
| UINT8 eir_data_len; |
| UINT32 oob_data_len; |
| |
| /* find record by Payload ID */ |
| p_rec = ndef_get_bt_oob_record (p_msg, max_size, p_cur_size, p_id_str); |
| |
| if (!p_rec) |
| return (NDEF_REC_NOT_FOUND); |
| |
| /* create EIR data format */ |
| p = eir_data; |
| UINT8_TO_STREAM (p, data_len + 1); |
| UINT8_TO_STREAM (p, eir_type); |
| ARRAY_TO_STREAM (p, p_data, data_len); |
| eir_data_len = data_len + 2; |
| |
| /* append EIR data at the end of record */ |
| status = NDEF_MsgAppendPayload (p_msg, max_size, p_cur_size, |
| p_rec, eir_data, eir_data_len); |
| |
| /* update BT OOB data length, if success */ |
| if (status == NDEF_OK) |
| { |
| /* payload length is the same as BT OOB data length */ |
| p = NDEF_RecGetPayload (p_rec, &oob_data_len); |
| UINT16_TO_STREAM (p, oob_data_len); |
| } |
| |
| return (status); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Static Local Functions |
| ** |
| *******************************************************************************/ |
| /******************************************************************************* |
| ** |
| ** Function ndef_get_bt_oob_record |
| ** |
| ** Description This function returns BT OOB record which has matched payload ID |
| ** |
| ** Returns pointer of record if found, otherwise NULL |
| ** |
| *******************************************************************************/ |
| static UINT8 *ndef_get_bt_oob_record (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, |
| char *p_id_str) |
| { |
| UINT8 *p_rec, *p_type; |
| UINT8 id_len, tnf, type_len; |
| |
| /* find record by Payload ID */ |
| id_len = (UINT8) strlen (p_id_str); |
| p_rec = NDEF_MsgGetFirstRecById (p_msg, (UINT8*) p_id_str, id_len); |
| |
| if (!p_rec) |
| return (NULL); |
| |
| p_type = NDEF_RecGetType (p_rec, &tnf, &type_len); |
| |
| /* check type if this is BT OOB record */ |
| if ( (!p_rec) |
| ||(tnf != NDEF_TNF_MEDIA) |
| ||(type_len != BT_OOB_REC_TYPE_LEN) |
| ||(memcmp (p_type, p_bt_oob_rec_type, BT_OOB_REC_TYPE_LEN)) ) |
| { |
| return (NULL); |
| } |
| |
| return (p_rec); |
| } |
| |