Fork for the GitHub

Committer:
DiegoOstuni
Date:
Thu Nov 14 10:34:11 2019 +0000
Revision:
0:de13951f30f6
Add files

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DiegoOstuni 0:de13951f30f6 1 /**
DiegoOstuni 0:de13951f30f6 2 ******************************************************************************
DiegoOstuni 0:de13951f30f6 3 * @file lib_NDEF_Bluetooth.c
DiegoOstuni 0:de13951f30f6 4 * @author MMY Application Team
DiegoOstuni 0:de13951f30f6 5 * @version $Revision: 2702 $
DiegoOstuni 0:de13951f30f6 6 * @date $Date: 2016-07-13 18:45:05 +0200 (Wed, 13 Jul 2016) $
DiegoOstuni 0:de13951f30f6 7 * @brief This file helps to manage a NDEF Handover message.
DiegoOstuni 0:de13951f30f6 8 * @ingroup libNDEF_Handover
DiegoOstuni 0:de13951f30f6 9 ******************************************************************************
DiegoOstuni 0:de13951f30f6 10 * @attention
DiegoOstuni 0:de13951f30f6 11 *
DiegoOstuni 0:de13951f30f6 12 * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
DiegoOstuni 0:de13951f30f6 13 *
DiegoOstuni 0:de13951f30f6 14 * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
DiegoOstuni 0:de13951f30f6 15 * You may not use this file except in compliance with the License.
DiegoOstuni 0:de13951f30f6 16 * You may obtain a copy of the License at:
DiegoOstuni 0:de13951f30f6 17 *
DiegoOstuni 0:de13951f30f6 18 * http://www.st.com/myliberty
DiegoOstuni 0:de13951f30f6 19 *
DiegoOstuni 0:de13951f30f6 20 * Unless required by applicable law or agreed to in writing, software
DiegoOstuni 0:de13951f30f6 21 * distributed under the License is distributed on an "AS IS" BASIS,
DiegoOstuni 0:de13951f30f6 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
DiegoOstuni 0:de13951f30f6 23 * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
DiegoOstuni 0:de13951f30f6 24 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
DiegoOstuni 0:de13951f30f6 25 * See the License for the specific language governing permissions and
DiegoOstuni 0:de13951f30f6 26 * limitations under the License.
DiegoOstuni 0:de13951f30f6 27 *
DiegoOstuni 0:de13951f30f6 28 ******************************************************************************
DiegoOstuni 0:de13951f30f6 29 */
DiegoOstuni 0:de13951f30f6 30 /* Includes ------------------------------------------------------------------*/
DiegoOstuni 0:de13951f30f6 31 #include "lib_NDEF_Handover.h"
DiegoOstuni 0:de13951f30f6 32
DiegoOstuni 0:de13951f30f6 33 /** @addtogroup lib_NDEF_Handover NDEF Handover library
DiegoOstuni 0:de13951f30f6 34 * @ingroup libNDEF
DiegoOstuni 0:de13951f30f6 35 * @brief This module is used to manage the NDEF Handover messages, to negociate the switch to a non-nfc protocol of communication.
DiegoOstuni 0:de13951f30f6 36 * @details
DiegoOstuni 0:de13951f30f6 37 * The NDEF Handover process is described by the NFC Forum Connection Handover specification.
DiegoOstuni 0:de13951f30f6 38 * It consists in a specific NDEF message construct, as:
DiegoOstuni 0:de13951f30f6 39 * - NDEF 1st record: Handover Request or Handover Select record
DiegoOstuni 0:de13951f30f6 40 * - Version
DiegoOstuni 0:de13951f30f6 41 * - Collision Resolution (nested record, optional)
DiegoOstuni 0:de13951f30f6 42 * - Random number
DiegoOstuni 0:de13951f30f6 43 * - Alternative Carrier 1 (nested record)
DiegoOstuni 0:de13951f30f6 44 * - Power state
DiegoOstuni 0:de13951f30f6 45 * - Reference Data
DiegoOstuni 0:de13951f30f6 46 * - Auxiliary Data Reference 1
DiegoOstuni 0:de13951f30f6 47 * - ...
DiegoOstuni 0:de13951f30f6 48 * - Auxiliary Data Reference N
DiegoOstuni 0:de13951f30f6 49 * - ...
DiegoOstuni 0:de13951f30f6 50 * - Alternative Carrier N (nested record)
DiegoOstuni 0:de13951f30f6 51 * - NDEF record 2+: Alternative Carrier or Auxiliary Data: Connection details for one of the AC (record ID is the AC Reference Data or an Auxiliary Data Reference).
DiegoOstuni 0:de13951f30f6 52 * - ...
DiegoOstuni 0:de13951f30f6 53 * - NDEF record N: Alternative Carrier or Auxiliary Data: Connection details for one of the AC (record ID is the AC Reference Data or an Auxiliary Data Reference).
DiegoOstuni 0:de13951f30f6 54 * _________________
DiegoOstuni 0:de13951f30f6 55 * @section Handover_Library_Usage NDEF Handover Library usage:
DiegoOstuni 0:de13951f30f6 56 * @subsection Static_Handover Static Handover
DiegoOstuni 0:de13951f30f6 57 * The Static Handover is used when a device is only equipped with a NFC Tag (no peer-to-peer) to directly propose a set of Alternative Carriers (ACs: bluetooth, wifi,...)
DiegoOstuni 0:de13951f30f6 58 * without running the full handover request-select process.\n
DiegoOstuni 0:de13951f30f6 59 * The Handover Select record use in that case is similar to the one used during a regular Handover negociation.\n
DiegoOstuni 0:de13951f30f6 60 * 1. Declare & initialize an instance of `Ndef_Handover_t`, such as:
DiegoOstuni 0:de13951f30f6 61 *
DiegoOstuni 0:de13951f30f6 62 * Ndef_Handover_t wHandover = {.type = NDEF_HANDOVER_SELECT_TYPE, .version = NDEF_HANDOVER_VERSION_1_2};
DiegoOstuni 0:de13951f30f6 63 * 2. Declare a `sRecordInfo_t` instance:
DiegoOstuni 0:de13951f30f6 64 *
DiegoOstuni 0:de13951f30f6 65 * sRecordInfo_t HandoverRecord;
DiegoOstuni 0:de13951f30f6 66 * 3. Call the `NDEF_CreateHandover` function, to start preparing the Handover Select record
DiegoOstuni 0:de13951f30f6 67 *
DiegoOstuni 0:de13951f30f6 68 * NDEF_CreateHandover(&wHandover,&HandoverRecord);
DiegoOstuni 0:de13951f30f6 69 * 4. Call the `NDEF_AddAlternativeCarrier` for each Alternative Carrier (such as Bluetooth, Wifi, ...)
DiegoOstuni 0:de13951f30f6 70 * 5. Declare and initialize as many `Ndef_Handover_alternative_carrier_t` instances as the number of non-NFC protocol available.
DiegoOstuni 0:de13951f30f6 71 * And then call the `NDEF_AddAlternativeCarrier` for each of them.
DiegoOstuni 0:de13951f30f6 72 *
DiegoOstuni 0:de13951f30f6 73 * Ndef_Handover_alternative_carrier_t wAC_BREDR = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE,
DiegoOstuni 0:de13951f30f6 74 * .aux_data_ref_count = 0};
DiegoOstuni 0:de13951f30f6 75 * Ndef_Handover_alternative_carrier_t wAC_BLE = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE,
DiegoOstuni 0:de13951f30f6 76 * .aux_data_ref_count = 0};
DiegoOstuni 0:de13951f30f6 77 * Ndef_Handover_alternative_carrier_t wAC_Wifi = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE,
DiegoOstuni 0:de13951f30f6 78 * .aux_data_ref_count = 0};
DiegoOstuni 0:de13951f30f6 79 *
DiegoOstuni 0:de13951f30f6 80 * NDEF_AddAlternativeCarrier(&wAC_BREDR,"urn:nfc:handover:bredr", NULL,&HandoverRecord );
DiegoOstuni 0:de13951f30f6 81 * NDEF_AddAlternativeCarrier(&wAC_BLE,"urn:nfc:handover:ble", NULL,&HandoverRecord );
DiegoOstuni 0:de13951f30f6 82 * NDEF_AddAlternativeCarrier(&wAC_Wifi,"urn:nfc:handover:wifi", NULL,&HandoverRecord );
DiegoOstuni 0:de13951f30f6 83 * @note
DiegoOstuni 0:de13951f30f6 84 * 1. In this example a single `Ndef_Handover_alternative_carrier_t` could have been used, as the parameters are the same for all ACs.
DiegoOstuni 0:de13951f30f6 85 * 2. If more than one NDEF record is required to provide the AC connection details, the `aux_data_ref_count` must specify the number of additional records.
DiegoOstuni 0:de13951f30f6 86 *
DiegoOstuni 0:de13951f30f6 87 * Ndef_Handover_alternative_carrier_t wAC_Wifi = {.cps = NDEF_HANDOVER_AC_CPS_ACTIVE,
DiegoOstuni 0:de13951f30f6 88 * .aux_data_ref_count = 2};
DiegoOstuni 0:de13951f30f6 89 * Then, it's required to initialize an array of pointers to these Auxiliary Data Reference, as:
DiegoOstuni 0:de13951f30f6 90 *
DiegoOstuni 0:de13951f30f6 91 * char *aux_data_ref1 = "urn:nfc:handover:wifi:aux_data_ref1";
DiegoOstuni 0:de13951f30f6 92 * char *aux_data_ref2 = "urn:nfc:handover:wifi:aux_data_ref2";
DiegoOstuni 0:de13951f30f6 93 * char *wifi_aux_ref_data_array[2] = {aux_data_ref1,aux_data_ref2};
DiegoOstuni 0:de13951f30f6 94 * And then provide this array as the 3rd argument to the 'NDEF_AddAlternativeCarrier' function:
DiegoOstuni 0:de13951f30f6 95 *
DiegoOstuni 0:de13951f30f6 96 * NDEF_AddAlternativeCarrier(&wAC_Wifi,"urn:nfc:handover:wifi", wifi_aux_ref_data_array,&HandoverRecord );
DiegoOstuni 0:de13951f30f6 97 * 6. Call the `NDEF_WriteHandover` function to finalize the NDEF message and write it to the tag.
DiegoOstuni 0:de13951f30f6 98 *
DiegoOstuni 0:de13951f30f6 99 * NDEF_WriteHandover(&HandoverRecord, NDEF_Buffer);
DiegoOstuni 0:de13951f30f6 100 * 7. Then call other functions (from the libNDEF or not) to add records, describing the Alternative Carriers, to the NDEF message:
DiegoOstuni 0:de13951f30f6 101 *
DiegoOstuni 0:de13951f30f6 102 * NDEF_AppendBluetoothOOB ( &w_ble_oob, "urn:nfc:handover:ble" );
DiegoOstuni 0:de13951f30f6 103 * NDEF_AppendBluetoothOOB ( &w_bredr_oob, "urn:nfc:handover:bredr" );
DiegoOstuni 0:de13951f30f6 104 * @note
DiegoOstuni 0:de13951f30f6 105 * 1. The ID of these additional records (2nd argument in the above example) must match the Data Reference provided within the Handover record.
DiegoOstuni 0:de13951f30f6 106 * 2. If Auxiliary Data References are expected they must also be added to the NDEF message, with their ID matching the ID provided to the Alternative Carrier record.
DiegoOstuni 0:de13951f30f6 107 *
DiegoOstuni 0:de13951f30f6 108 * @section Reading_Handover Reading through a Handover Request message
DiegoOstuni 0:de13951f30f6 109 * 1. Read the 1st record of the NDEF message:
DiegoOstuni 0:de13951f30f6 110 *
DiegoOstuni 0:de13951f30f6 111 * sRecordInfo_t rRecord;
DiegoOstuni 0:de13951f30f6 112 * NDEF_ReadNDEF(NDEF_Buffer);
DiegoOstuni 0:de13951f30f6 113 * NDEF_IdentifyBuffer(rRecord,NDEF_Buffer);
DiegoOstuni 0:de13951f30f6 114 * 2. Decode the handover:
DiegoOstuni 0:de13951f30f6 115 *
DiegoOstuni 0:de13951f30f6 116 * Ndef_Handover_t rHandover;
DiegoOstuni 0:de13951f30f6 117 * NDEF_ReadHandover(&rRecord , &rHandover );
DiegoOstuni 0:de13951f30f6 118 * 3. Read all Alternative Carrier records, and their Auxiliary Data References if any.
DiegoOstuni 0:de13951f30f6 119 *
DiegoOstuni 0:de13951f30f6 120 * uint8_t ac_index, aux_index;
DiegoOstuni 0:de13951f30f6 121 * for(ac_index=0;ac_index<rHandover.nb_alternative_carrier;ac_index++)
DiegoOstuni 0:de13951f30f6 122 * {
DiegoOstuni 0:de13951f30f6 123 * Ndef_Handover_alternative_carrier_t rAC;
DiegoOstuni 0:de13951f30f6 124 * NDEF_ReadAC( ac_index, &rHandover , &rAC );
DiegoOstuni 0:de13951f30f6 125 * for(aux_index = 0; aux_index < rAC.aux_data_ref_count; aux_index++)
DiegoOstuni 0:de13951f30f6 126 * {
DiegoOstuni 0:de13951f30f6 127 * sRecordInfo_t AuxRecord;
DiegoOstuni 0:de13951f30f6 128 * NDEF_ReadAuxData( aux_index, &rAC, &AuxRecord );
DiegoOstuni 0:de13951f30f6 129 * // Do something with this Auxiliary Data
DiegoOstuni 0:de13951f30f6 130 * }
DiegoOstuni 0:de13951f30f6 131 * // Process this AC (Extract OOB/or whatever data), and decide if this Carrier is supported or not.
DiegoOstuni 0:de13951f30f6 132 * }
DiegoOstuni 0:de13951f30f6 133 * 4. Choose the prefered Carrier and write a Handover Select record with the prefered AC as described in the @ref Static_Handover section.
DiegoOstuni 0:de13951f30f6 134 * @{
DiegoOstuni 0:de13951f30f6 135 */
DiegoOstuni 0:de13951f30f6 136
DiegoOstuni 0:de13951f30f6 137
DiegoOstuni 0:de13951f30f6 138
DiegoOstuni 0:de13951f30f6 139 /**
DiegoOstuni 0:de13951f30f6 140 * @brief This function searches the NDEF message to retrieve the nth Auxiliary Data record if present.
DiegoOstuni 0:de13951f30f6 141 * @param aux_data_nb Position of the Auxiliary Data Reference in the Alternative Carrier.
DiegoOstuni 0:de13951f30f6 142 * @param pAC Pointer on the Alternative Carrier structure where to find the Auxiliary Data Reference.
DiegoOstuni 0:de13951f30f6 143 * @param pRecord Pointer to return the output Auxiliary Data record.
DiegoOstuni 0:de13951f30f6 144 * @retval NDEF_OK The Auxiliary Data record has been retrieved.
DiegoOstuni 0:de13951f30f6 145 * @retval NDEF_ERROR Not able to find the Auxiliary Data in the NDEF message.
DiegoOstuni 0:de13951f30f6 146 */
DiegoOstuni 0:de13951f30f6 147 uint16_t NDEF_ReadAuxData( uint8_t aux_data_nb, Ndef_Handover_alternative_carrier_t *pAC, sRecordInfo_t *pRecord )
DiegoOstuni 0:de13951f30f6 148 {
DiegoOstuni 0:de13951f30f6 149 uint16_t status;
DiegoOstuni 0:de13951f30f6 150 uint8_t* pData = pAC->aux_data_ref_start;
DiegoOstuni 0:de13951f30f6 151 uint8_t current_aux = 0;
DiegoOstuni 0:de13951f30f6 152 uint8_t* aux_id;
DiegoOstuni 0:de13951f30f6 153 uint8_t aux_id_length;
DiegoOstuni 0:de13951f30f6 154
DiegoOstuni 0:de13951f30f6 155 if((pAC->aux_data_ref_start == NULL) ||
DiegoOstuni 0:de13951f30f6 156 (pAC->aux_data_ref_end == NULL) ||
DiegoOstuni 0:de13951f30f6 157 (pAC->aux_data_ref_count == 0) ||
DiegoOstuni 0:de13951f30f6 158 (aux_data_nb >= pAC->aux_data_ref_count))
DiegoOstuni 0:de13951f30f6 159 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 160
DiegoOstuni 0:de13951f30f6 161
DiegoOstuni 0:de13951f30f6 162 while((current_aux < aux_data_nb) && (pData < pAC->aux_data_ref_end))
DiegoOstuni 0:de13951f30f6 163 {
DiegoOstuni 0:de13951f30f6 164 aux_id_length = *pData++;
DiegoOstuni 0:de13951f30f6 165 aux_id = pData;
DiegoOstuni 0:de13951f30f6 166 pData += aux_id_length;
DiegoOstuni 0:de13951f30f6 167 current_aux++;
DiegoOstuni 0:de13951f30f6 168 }
DiegoOstuni 0:de13951f30f6 169
DiegoOstuni 0:de13951f30f6 170 pData = pAC->aux_data_ref_end;
DiegoOstuni 0:de13951f30f6 171 /* if ac has been found */
DiegoOstuni 0:de13951f30f6 172 if(current_aux == aux_data_nb)
DiegoOstuni 0:de13951f30f6 173 {
DiegoOstuni 0:de13951f30f6 174 /* let's now look for the corresponding record - must be after the Handover record */
DiegoOstuni 0:de13951f30f6 175 do {
DiegoOstuni 0:de13951f30f6 176 status = NDEF_IdentifyBuffer(pRecord,pData);
DiegoOstuni 0:de13951f30f6 177 if(status != NDEF_OK) return status;
DiegoOstuni 0:de13951f30f6 178 pData = pAC->ac_record.PayloadBufferAdd;
DiegoOstuni 0:de13951f30f6 179
DiegoOstuni 0:de13951f30f6 180 if((pRecord->IDLength == aux_id_length) &&
DiegoOstuni 0:de13951f30f6 181 !memcmp(pRecord->ID, aux_id,aux_id_length))
DiegoOstuni 0:de13951f30f6 182 {
DiegoOstuni 0:de13951f30f6 183 /* this is the record we were looking for, so exit */
DiegoOstuni 0:de13951f30f6 184 return NDEF_OK;
DiegoOstuni 0:de13951f30f6 185 }
DiegoOstuni 0:de13951f30f6 186
DiegoOstuni 0:de13951f30f6 187 // go to next record
DiegoOstuni 0:de13951f30f6 188 pData = pRecord->PayloadBufferAdd + pRecord->PayloadLength;
DiegoOstuni 0:de13951f30f6 189
DiegoOstuni 0:de13951f30f6 190 } while (!(pRecord->RecordFlags & MB_Mask));
DiegoOstuni 0:de13951f30f6 191
DiegoOstuni 0:de13951f30f6 192 }
DiegoOstuni 0:de13951f30f6 193 // if we go there, it means that the record ID is not found
DiegoOstuni 0:de13951f30f6 194 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 195 }
DiegoOstuni 0:de13951f30f6 196
DiegoOstuni 0:de13951f30f6 197
DiegoOstuni 0:de13951f30f6 198
DiegoOstuni 0:de13951f30f6 199 /**
DiegoOstuni 0:de13951f30f6 200 * @brief This function reads the NDEF message and retrieves the nth Alternative Carrier record if present.
DiegoOstuni 0:de13951f30f6 201 * @param ac_nb Position of the Alternative Carrier Reference in the Handover record.
DiegoOstuni 0:de13951f30f6 202 * @param pHandover Pointer to the Handover record where to find the AC Reference Data.
DiegoOstuni 0:de13951f30f6 203 * @param pAC Pointer used to return the output Alternative Carrier record.
DiegoOstuni 0:de13951f30f6 204 * @retval NDEF_OK The Alternative Carrier record has been retrieved.
DiegoOstuni 0:de13951f30f6 205 * @retval NDEF_ERROR Not able to find the Alternative Carrier in the NDEF message.
DiegoOstuni 0:de13951f30f6 206 */
DiegoOstuni 0:de13951f30f6 207 uint16_t NDEF_ReadAC( uint8_t ac_nb, Ndef_Handover_t *pHandover , Ndef_Handover_alternative_carrier_t *pAC )
DiegoOstuni 0:de13951f30f6 208 {
DiegoOstuni 0:de13951f30f6 209 uint16_t status;
DiegoOstuni 0:de13951f30f6 210 uint8_t* pData = pHandover->ac_start;
DiegoOstuni 0:de13951f30f6 211 uint8_t current_ac = 0;
DiegoOstuni 0:de13951f30f6 212 uint8_t* ac_id;
DiegoOstuni 0:de13951f30f6 213 uint8_t ac_id_length;
DiegoOstuni 0:de13951f30f6 214 sRecordInfo_t NestedRecord;
DiegoOstuni 0:de13951f30f6 215 uint8_t ac_found = 0;
DiegoOstuni 0:de13951f30f6 216
DiegoOstuni 0:de13951f30f6 217 if((pHandover->ac_start == NULL) ||
DiegoOstuni 0:de13951f30f6 218 (pHandover->ac_end == NULL) ||
DiegoOstuni 0:de13951f30f6 219 (pHandover->nb_alternative_carrier == 0) ||
DiegoOstuni 0:de13951f30f6 220 (ac_nb >= pHandover->nb_alternative_carrier))
DiegoOstuni 0:de13951f30f6 221 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 222
DiegoOstuni 0:de13951f30f6 223 // Default handover init
DiegoOstuni 0:de13951f30f6 224 pAC->aux_data_ref_count = 0;
DiegoOstuni 0:de13951f30f6 225
DiegoOstuni 0:de13951f30f6 226 while((current_ac <= ac_nb)&&(current_ac <= pHandover->nb_alternative_carrier) && (pData < pHandover->ac_end))
DiegoOstuni 0:de13951f30f6 227 {
DiegoOstuni 0:de13951f30f6 228 status = NDEF_IdentifyBuffer(&NestedRecord,pData);
DiegoOstuni 0:de13951f30f6 229 if(status != NDEF_OK) return status;
DiegoOstuni 0:de13951f30f6 230 // go to payload address
DiegoOstuni 0:de13951f30f6 231 pData = NestedRecord.PayloadBufferAdd;
DiegoOstuni 0:de13951f30f6 232
DiegoOstuni 0:de13951f30f6 233 if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR)))
DiegoOstuni 0:de13951f30f6 234 {
DiegoOstuni 0:de13951f30f6 235 if(current_ac == ac_nb)
DiegoOstuni 0:de13951f30f6 236 {
DiegoOstuni 0:de13951f30f6 237 // parse the AC now
DiegoOstuni 0:de13951f30f6 238 pAC->cps = pData[0] & NDEF_HANDOVER_AC_CPS_MASK;
DiegoOstuni 0:de13951f30f6 239 ac_id_length = pData[1];
DiegoOstuni 0:de13951f30f6 240 ac_id = &pData[2];
DiegoOstuni 0:de13951f30f6 241 pAC->aux_data_ref_count = pData[2 + ac_id_length];
DiegoOstuni 0:de13951f30f6 242 pAC->aux_data_ref_start = &pData[3 + ac_id_length];
DiegoOstuni 0:de13951f30f6 243 pAC->aux_data_ref_end = pData + NestedRecord.PayloadLength;
DiegoOstuni 0:de13951f30f6 244 ac_found = 1;
DiegoOstuni 0:de13951f30f6 245 }
DiegoOstuni 0:de13951f30f6 246 current_ac++;
DiegoOstuni 0:de13951f30f6 247 }
DiegoOstuni 0:de13951f30f6 248 // go to next record
DiegoOstuni 0:de13951f30f6 249 pData += NestedRecord.PayloadLength;
DiegoOstuni 0:de13951f30f6 250 }
DiegoOstuni 0:de13951f30f6 251 pData = pHandover->ac_end;
DiegoOstuni 0:de13951f30f6 252 /* if ac has been found */
DiegoOstuni 0:de13951f30f6 253 if(ac_found)
DiegoOstuni 0:de13951f30f6 254 {
DiegoOstuni 0:de13951f30f6 255 /* let's now look for the corresponding record - must be after the Handover record */
DiegoOstuni 0:de13951f30f6 256 do {
DiegoOstuni 0:de13951f30f6 257 status = NDEF_IdentifyBuffer(&pAC->ac_record,pData);
DiegoOstuni 0:de13951f30f6 258 if(status != NDEF_OK) return status;
DiegoOstuni 0:de13951f30f6 259 pData = pAC->ac_record.PayloadBufferAdd;
DiegoOstuni 0:de13951f30f6 260
DiegoOstuni 0:de13951f30f6 261 if((pAC->ac_record.IDLength == ac_id_length) &&
DiegoOstuni 0:de13951f30f6 262 !memcmp(pAC->ac_record.ID, ac_id,ac_id_length))
DiegoOstuni 0:de13951f30f6 263 {
DiegoOstuni 0:de13951f30f6 264 /* this is the record we were looking for, so exit */
DiegoOstuni 0:de13951f30f6 265 return NDEF_OK;
DiegoOstuni 0:de13951f30f6 266 }
DiegoOstuni 0:de13951f30f6 267
DiegoOstuni 0:de13951f30f6 268 // go to next record
DiegoOstuni 0:de13951f30f6 269 pData = pAC->ac_record.PayloadBufferAdd + pAC->ac_record.PayloadLength;
DiegoOstuni 0:de13951f30f6 270 // TO DO: add a security condition to avoid infinite loop if NDEF file is corrupted
DiegoOstuni 0:de13951f30f6 271 } while (!(pAC->ac_record.RecordFlags & ME_Mask));
DiegoOstuni 0:de13951f30f6 272
DiegoOstuni 0:de13951f30f6 273 }
DiegoOstuni 0:de13951f30f6 274 // if we go there, it means that the record ID is not found
DiegoOstuni 0:de13951f30f6 275 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 276 }
DiegoOstuni 0:de13951f30f6 277
DiegoOstuni 0:de13951f30f6 278
DiegoOstuni 0:de13951f30f6 279 /**
DiegoOstuni 0:de13951f30f6 280 * @brief This function reads a record and retrieves the Handover information if present.
DiegoOstuni 0:de13951f30f6 281 * @param pRecord Pointer on the record structure to be read.
DiegoOstuni 0:de13951f30f6 282 * @param pHandover Pointer used to return the Handover information.
DiegoOstuni 0:de13951f30f6 283 * @retval NDEF_OK Handover information has been retrieved from the record.
DiegoOstuni 0:de13951f30f6 284 * @retval NDEF_ERROR Not able to read the Handover information from the record.
DiegoOstuni 0:de13951f30f6 285 */
DiegoOstuni 0:de13951f30f6 286 uint16_t NDEF_ReadHandover(sRecordInfo_t *pRecord , Ndef_Handover_t *pHandover )
DiegoOstuni 0:de13951f30f6 287 {
DiegoOstuni 0:de13951f30f6 288 uint16_t status;
DiegoOstuni 0:de13951f30f6 289 uint8_t* pData = pRecord->PayloadBufferAdd;
DiegoOstuni 0:de13951f30f6 290 uint8_t* pEnd = pData + pRecord->PayloadLength;
DiegoOstuni 0:de13951f30f6 291 sRecordInfo_t NestedRecord;
DiegoOstuni 0:de13951f30f6 292
DiegoOstuni 0:de13951f30f6 293 /* Default Handover Structure init */
DiegoOstuni 0:de13951f30f6 294 pHandover->version =0;
DiegoOstuni 0:de13951f30f6 295 pHandover->nb_alternative_carrier =0;
DiegoOstuni 0:de13951f30f6 296 pHandover->has_cr = 0;
DiegoOstuni 0:de13951f30f6 297 pHandover->ac_start = NULL;
DiegoOstuni 0:de13951f30f6 298 pHandover->ac_end = NULL;
DiegoOstuni 0:de13951f30f6 299
DiegoOstuni 0:de13951f30f6 300 /* A Handover record should never be the end of the NDEF message */
DiegoOstuni 0:de13951f30f6 301 if(pRecord->RecordFlags & ME_Mask)
DiegoOstuni 0:de13951f30f6 302 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 303
DiegoOstuni 0:de13951f30f6 304 if( !memcmp(pRecord->Type,NDEF_HANDOVER_REQUEST_TYPE_STR,strlen(NDEF_HANDOVER_REQUEST_TYPE_STR)) )
DiegoOstuni 0:de13951f30f6 305 {
DiegoOstuni 0:de13951f30f6 306 pHandover->type = NDEF_HANDOVER_REQUEST_TYPE;
DiegoOstuni 0:de13951f30f6 307 } else if ( !memcmp(pRecord->Type,NDEF_HANDOVER_SELECT_TYPE_STR,strlen(NDEF_HANDOVER_SELECT_TYPE_STR)) )
DiegoOstuni 0:de13951f30f6 308 {
DiegoOstuni 0:de13951f30f6 309 pHandover->type = NDEF_HANDOVER_SELECT_TYPE;
DiegoOstuni 0:de13951f30f6 310 } else {
DiegoOstuni 0:de13951f30f6 311 /* This is not a Handover record! */
DiegoOstuni 0:de13951f30f6 312 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 313 }
DiegoOstuni 0:de13951f30f6 314
DiegoOstuni 0:de13951f30f6 315 pHandover->version = *pData++;
DiegoOstuni 0:de13951f30f6 316
DiegoOstuni 0:de13951f30f6 317 /* Following records are nested into Hr/s record */
DiegoOstuni 0:de13951f30f6 318 while (pData < pEnd)
DiegoOstuni 0:de13951f30f6 319 {
DiegoOstuni 0:de13951f30f6 320 status = NDEF_IdentifyBuffer(&NestedRecord,pData);
DiegoOstuni 0:de13951f30f6 321 if(status != NDEF_OK) return status;
DiegoOstuni 0:de13951f30f6 322 /* save record address */
DiegoOstuni 0:de13951f30f6 323 uint8_t* pACRecord = pData;
DiegoOstuni 0:de13951f30f6 324 /* go to payload address */
DiegoOstuni 0:de13951f30f6 325 pData = NestedRecord.PayloadBufferAdd;
DiegoOstuni 0:de13951f30f6 326
DiegoOstuni 0:de13951f30f6 327 /* Parse Collision Resolution if Handover request */
DiegoOstuni 0:de13951f30f6 328 if(pHandover->type == NDEF_HANDOVER_REQUEST_TYPE)
DiegoOstuni 0:de13951f30f6 329 {
DiegoOstuni 0:de13951f30f6 330
DiegoOstuni 0:de13951f30f6 331 if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_COLLISION_RESOLUTION_TYPE_STR,strlen(NDEF_HANDOVER_COLLISION_RESOLUTION_TYPE_STR)))
DiegoOstuni 0:de13951f30f6 332 {
DiegoOstuni 0:de13951f30f6 333 pHandover->has_cr = 1;
DiegoOstuni 0:de13951f30f6 334 pHandover->cr_random_number = *(uint16_t*)pData;
DiegoOstuni 0:de13951f30f6 335 }
DiegoOstuni 0:de13951f30f6 336 }
DiegoOstuni 0:de13951f30f6 337
DiegoOstuni 0:de13951f30f6 338 /* Parse AlternativeCarriers just to know how many they are */
DiegoOstuni 0:de13951f30f6 339 else if(!memcmp(NestedRecord.Type,NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR)))
DiegoOstuni 0:de13951f30f6 340 {
DiegoOstuni 0:de13951f30f6 341 pHandover->nb_alternative_carrier++;
DiegoOstuni 0:de13951f30f6 342 if(pHandover->ac_start == NULL)
DiegoOstuni 0:de13951f30f6 343 pHandover->ac_start = pACRecord;
DiegoOstuni 0:de13951f30f6 344 pHandover->ac_end = pData + NestedRecord.PayloadLength;
DiegoOstuni 0:de13951f30f6 345 /* don't parse the AC now */
DiegoOstuni 0:de13951f30f6 346 }
DiegoOstuni 0:de13951f30f6 347 else {
DiegoOstuni 0:de13951f30f6 348 /* this is an unexpected type, just ignore it */
DiegoOstuni 0:de13951f30f6 349 }
DiegoOstuni 0:de13951f30f6 350 /* go to next record */
DiegoOstuni 0:de13951f30f6 351 pData += NestedRecord.PayloadLength;
DiegoOstuni 0:de13951f30f6 352
DiegoOstuni 0:de13951f30f6 353 }
DiegoOstuni 0:de13951f30f6 354
DiegoOstuni 0:de13951f30f6 355 return NDEF_OK;
DiegoOstuni 0:de13951f30f6 356 }
DiegoOstuni 0:de13951f30f6 357
DiegoOstuni 0:de13951f30f6 358 /**
DiegoOstuni 0:de13951f30f6 359 * @brief This function prepares the Handover record with the data given in the Handover structure.
DiegoOstuni 0:de13951f30f6 360 * @param pHandover Pointer on structure containing the handover basic information.
DiegoOstuni 0:de13951f30f6 361 * @param pRecord Pointer used to return the prepared Handover record.
DiegoOstuni 0:de13951f30f6 362 * @retval NDEF_OK The record has been prepared.
DiegoOstuni 0:de13951f30f6 363 * @retval NDEF_ERROR The record has not been prepared.
DiegoOstuni 0:de13951f30f6 364 */
DiegoOstuni 0:de13951f30f6 365 uint16_t NDEF_CreateHandover(Ndef_Handover_t *pHandover, sRecordInfo_t* pRecord )
DiegoOstuni 0:de13951f30f6 366 {
DiegoOstuni 0:de13951f30f6 367 uint16_t status = NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 368
DiegoOstuni 0:de13951f30f6 369 /* Use a static buffer to prepare the Handover record */
DiegoOstuni 0:de13951f30f6 370 pRecord->PayloadBufferAdd = NDEF_Record_Buffer;
DiegoOstuni 0:de13951f30f6 371 /* Alternative, where the user must first allocate the Payload buffer in the record:
DiegoOstuni 0:de13951f30f6 372 * if (pRecord->PayloadBufferAdd == NULL)
DiegoOstuni 0:de13951f30f6 373 * return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 374 */
DiegoOstuni 0:de13951f30f6 375
DiegoOstuni 0:de13951f30f6 376 /* Handover MUST be the first record (SR mask to be updated when actually writing the record) */
DiegoOstuni 0:de13951f30f6 377 pRecord->RecordFlags = MB_Mask | ME_Mask | TNF_WellKnown;
DiegoOstuni 0:de13951f30f6 378
DiegoOstuni 0:de13951f30f6 379 if(pHandover->type == NDEF_HANDOVER_SELECT_TYPE)
DiegoOstuni 0:de13951f30f6 380 {
DiegoOstuni 0:de13951f30f6 381 pRecord->TypeLength = strlen(NDEF_HANDOVER_SELECT_TYPE_STR);
DiegoOstuni 0:de13951f30f6 382 memcpy(pRecord->Type, NDEF_HANDOVER_SELECT_TYPE_STR,pRecord->TypeLength);
DiegoOstuni 0:de13951f30f6 383 }
DiegoOstuni 0:de13951f30f6 384 else if (pHandover->type == NDEF_HANDOVER_REQUEST_TYPE)
DiegoOstuni 0:de13951f30f6 385 {
DiegoOstuni 0:de13951f30f6 386 pRecord->TypeLength = strlen(NDEF_HANDOVER_SELECT_TYPE_STR);
DiegoOstuni 0:de13951f30f6 387 memcpy(pRecord->Type, NDEF_HANDOVER_REQUEST_TYPE_STR,pRecord->TypeLength);
DiegoOstuni 0:de13951f30f6 388 }
DiegoOstuni 0:de13951f30f6 389 else
DiegoOstuni 0:de13951f30f6 390 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 391
DiegoOstuni 0:de13951f30f6 392 pRecord->PayloadLength = sizeof(pHandover->version);
DiegoOstuni 0:de13951f30f6 393 *pRecord->PayloadBufferAdd = pHandover->version;
DiegoOstuni 0:de13951f30f6 394
DiegoOstuni 0:de13951f30f6 395 /* Don't write the record for now, additionnal Alternative Carriers to come as nested records. */
DiegoOstuni 0:de13951f30f6 396
DiegoOstuni 0:de13951f30f6 397 return status;
DiegoOstuni 0:de13951f30f6 398 }
DiegoOstuni 0:de13951f30f6 399
DiegoOstuni 0:de13951f30f6 400
DiegoOstuni 0:de13951f30f6 401 /**
DiegoOstuni 0:de13951f30f6 402 * @brief This function adds an Alternative Carrier record to a Handover record using the data given in the AC structure.
DiegoOstuni 0:de13951f30f6 403 * @param pAC Pointer on input AC structure.
DiegoOstuni 0:de13951f30f6 404 * @param CarrierDataRef String with the Alternative Carrier Data Reference (ID of the corresponding record in the NDEF message).
DiegoOstuni 0:de13951f30f6 405 * @param AuxDataRefID Array with pointers to the Auxiliary Data References (as many as defined in pAC structure).
DiegoOstuni 0:de13951f30f6 406 * @param pRecord Pointer on the Handover record to be filled with the AC data, must have been previously initialized with the NDEF_CreateHandover function.
DiegoOstuni 0:de13951f30f6 407 * @retval NDEF_OK The Handover record has been updated with AC information.
DiegoOstuni 0:de13951f30f6 408 * @retval NDEF_ERROR The Handover record cannot be updated with the AC information.
DiegoOstuni 0:de13951f30f6 409 * @retval NDEF_ERROR_MEMORY_INTERNAL The internal buffer for records is too small to add the AC information.
DiegoOstuni 0:de13951f30f6 410 */
DiegoOstuni 0:de13951f30f6 411 uint16_t NDEF_AddAlternativeCarrier(Ndef_Handover_alternative_carrier_t *pAC,char *CarrierDataRef, char **AuxDataRefID, sRecordInfo_t* pRecord, I2C* mi2cChannel )
DiegoOstuni 0:de13951f30f6 412 {
DiegoOstuni 0:de13951f30f6 413 /* Specific buffer to prepare the Alternative Carrier record */
DiegoOstuni 0:de13951f30f6 414 uint8_t NDEF_AlternativeCarrier_Buffer[NDEF_AC_BUFFER_SIZE];
DiegoOstuni 0:de13951f30f6 415
DiegoOstuni 0:de13951f30f6 416 /* check that there is enough space in the buffers */
DiegoOstuni 0:de13951f30f6 417 pAC->ac_record.PayloadLength = NDEF_GetACDataLength(pAC,CarrierDataRef,AuxDataRefID);
DiegoOstuni 0:de13951f30f6 418 if(((pRecord->PayloadLength + pAC->ac_record.PayloadLength) > NDEF_RECORD_MAX_SIZE) ||
DiegoOstuni 0:de13951f30f6 419 (pAC->ac_record.PayloadLength > NDEF_AC_BUFFER_SIZE))
DiegoOstuni 0:de13951f30f6 420 return NDEF_ERROR_MEMORY_INTERNAL;
DiegoOstuni 0:de13951f30f6 421
DiegoOstuni 0:de13951f30f6 422 /* Use specific buffer to prepare the nested record */
DiegoOstuni 0:de13951f30f6 423 uint8_t *pData = NDEF_AlternativeCarrier_Buffer;
DiegoOstuni 0:de13951f30f6 424 pAC->ac_record.PayloadBufferAdd = pData;
DiegoOstuni 0:de13951f30f6 425 /* Following line is an alternative where the user must allocate the payload buffer of the ac_record:
DiegoOstuni 0:de13951f30f6 426 * uint8_t* pData = pAC->ac_record.PayloadBufferAdd ;
DiegoOstuni 0:de13951f30f6 427 */
DiegoOstuni 0:de13951f30f6 428
DiegoOstuni 0:de13951f30f6 429 if ((pRecord->PayloadBufferAdd == NULL) ||
DiegoOstuni 0:de13951f30f6 430 (pRecord->PayloadLength == 0))
DiegoOstuni 0:de13951f30f6 431 return NDEF_ERROR;
DiegoOstuni 0:de13951f30f6 432
DiegoOstuni 0:de13951f30f6 433 /* AC is not the first record */
DiegoOstuni 0:de13951f30f6 434 pAC->ac_record.RecordFlags = TNF_WellKnown;
DiegoOstuni 0:de13951f30f6 435
DiegoOstuni 0:de13951f30f6 436 pAC->ac_record.TypeLength = strlen(NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR);
DiegoOstuni 0:de13951f30f6 437 memcpy(pAC->ac_record.Type, NDEF_HANDOVER_ALTERNATIVE_CARRIER_TYPE_STR,pAC->ac_record.TypeLength);
DiegoOstuni 0:de13951f30f6 438
DiegoOstuni 0:de13951f30f6 439 /* Length : cps byte + data ref length byte + auxiliary data ref count byte + data ref length */
DiegoOstuni 0:de13951f30f6 440 *pData++ = pAC->cps & NDEF_HANDOVER_AC_CPS_MASK;
DiegoOstuni 0:de13951f30f6 441 *pData++ = strlen(CarrierDataRef);
DiegoOstuni 0:de13951f30f6 442 memcpy(pData, CarrierDataRef, strlen(CarrierDataRef));
DiegoOstuni 0:de13951f30f6 443 pData += strlen(CarrierDataRef);
DiegoOstuni 0:de13951f30f6 444 *pData++ = pAC->aux_data_ref_count;
DiegoOstuni 0:de13951f30f6 445
DiegoOstuni 0:de13951f30f6 446 uint8_t AuxDataIndex;
DiegoOstuni 0:de13951f30f6 447 for(AuxDataIndex = 0;AuxDataIndex<pAC->aux_data_ref_count;AuxDataIndex++)
DiegoOstuni 0:de13951f30f6 448 {
DiegoOstuni 0:de13951f30f6 449 *pData++ = strlen(AuxDataRefID[AuxDataIndex]);
DiegoOstuni 0:de13951f30f6 450 memcpy(pData, AuxDataRefID[AuxDataIndex], strlen(AuxDataRefID[AuxDataIndex]));
DiegoOstuni 0:de13951f30f6 451 pData += strlen(AuxDataRefID[AuxDataIndex]);
DiegoOstuni 0:de13951f30f6 452 }
DiegoOstuni 0:de13951f30f6 453
DiegoOstuni 0:de13951f30f6 454 /* Append the nested record right after the Handover record - increase its length accordingly */
DiegoOstuni 0:de13951f30f6 455 pRecord->PayloadLength += NDEF_WriteRecord(&pAC->ac_record,pRecord->PayloadBufferAdd + pRecord->PayloadLength, mi2cChannel);
DiegoOstuni 0:de13951f30f6 456 return NDEF_OK;
DiegoOstuni 0:de13951f30f6 457 }
DiegoOstuni 0:de13951f30f6 458
DiegoOstuni 0:de13951f30f6 459
DiegoOstuni 0:de13951f30f6 460 /**
DiegoOstuni 0:de13951f30f6 461 * @brief This function returns the length of an Alternative Carrier record data (excluding the record metadata).
DiegoOstuni 0:de13951f30f6 462 * @param pAC Pointer on the input AC structure.
DiegoOstuni 0:de13951f30f6 463 * @param CarrierDataRef String with the Alternative Carrier Data Reference.
DiegoOstuni 0:de13951f30f6 464 * @param AuxDataRefID Array with the Auxiliary Data References (as many as defined in the pAC structure).
DiegoOstuni 0:de13951f30f6 465 * @return The computed length in bytes corresponding to the provided Alternative Carrier information.
DiegoOstuni 0:de13951f30f6 466 */
DiegoOstuni 0:de13951f30f6 467 uint32_t NDEF_GetACDataLength(Ndef_Handover_alternative_carrier_t *pAC,char *CarrierDataRef, char **AuxDataRefID)
DiegoOstuni 0:de13951f30f6 468 {
DiegoOstuni 0:de13951f30f6 469 uint8_t AuxDataIndex;
DiegoOstuni 0:de13951f30f6 470
DiegoOstuni 0:de13951f30f6 471 /* First compute the Data length */
DiegoOstuni 0:de13951f30f6 472 uint32_t length = 1 + // cps
DiegoOstuni 0:de13951f30f6 473 1 + // Carrier data ref length
DiegoOstuni 0:de13951f30f6 474 strlen(CarrierDataRef) + // Carrier data ref
DiegoOstuni 0:de13951f30f6 475 1 + // auxiliary data count
DiegoOstuni 0:de13951f30f6 476 pAC->aux_data_ref_count * 1; // auxiliary data lengths
DiegoOstuni 0:de13951f30f6 477
DiegoOstuni 0:de13951f30f6 478 /* Then adds the length of the Auxiliary Data */
DiegoOstuni 0:de13951f30f6 479 for(AuxDataIndex = 0;AuxDataIndex<pAC->aux_data_ref_count;AuxDataIndex++)
DiegoOstuni 0:de13951f30f6 480 {
DiegoOstuni 0:de13951f30f6 481 length += strlen(AuxDataRefID[AuxDataIndex]);
DiegoOstuni 0:de13951f30f6 482 }
DiegoOstuni 0:de13951f30f6 483
DiegoOstuni 0:de13951f30f6 484 return length;
DiegoOstuni 0:de13951f30f6 485 }
DiegoOstuni 0:de13951f30f6 486
DiegoOstuni 0:de13951f30f6 487 /**
DiegoOstuni 0:de13951f30f6 488 * @brief This function writes the Handover record into the memory.
DiegoOstuni 0:de13951f30f6 489 * @param pRecord Pointer on the input Handover record.
DiegoOstuni 0:de13951f30f6 490 * @param pNdef Pointer to a NDEF buffer (used to prepare the data before actual writing to the memory).
DiegoOstuni 0:de13951f30f6 491 * @retval NDEF_OK The memory has been written.
DiegoOstuni 0:de13951f30f6 492 * @retval NDEF_ERROR_MEMORY_INTERNAL Cannot write to tag.
DiegoOstuni 0:de13951f30f6 493 * @retval NDEF_ERROR_NOT_FORMATED CCFile data not supported or not present.
DiegoOstuni 0:de13951f30f6 494 * @retval NDEF_ERROR_MEMORY_TAG Size not compatible with memory.
DiegoOstuni 0:de13951f30f6 495 * @retval NDEF_ERROR_LOCKED Tag locked, cannot be write.
DiegoOstuni 0:de13951f30f6 496 */
DiegoOstuni 0:de13951f30f6 497 uint16_t NDEF_WriteHandover( sRecordInfo_t* pRecord , uint8_t* pNdef, I2C* mi2cChannel)
DiegoOstuni 0:de13951f30f6 498 {
DiegoOstuni 0:de13951f30f6 499 /* Note: in case of Handover Select for no matching alternative carrier, the ME bit flag must be set by the caller */
DiegoOstuni 0:de13951f30f6 500
DiegoOstuni 0:de13951f30f6 501 uint32_t Size = NDEF_WriteRecord(pRecord,pNdef, mi2cChannel);
DiegoOstuni 0:de13951f30f6 502 return NDEF_WriteNDEF(Size,pNdef, mi2cChannel);
DiegoOstuni 0:de13951f30f6 503 }
DiegoOstuni 0:de13951f30f6 504
DiegoOstuni 0:de13951f30f6 505 /**
DiegoOstuni 0:de13951f30f6 506 * @}
DiegoOstuni 0:de13951f30f6 507 */
DiegoOstuni 0:de13951f30f6 508
DiegoOstuni 0:de13951f30f6 509 /******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/